Skip to content
Merged
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
10 changes: 7 additions & 3 deletions src/Assets/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class Asset implements Arrayable, ArrayAccess, AssetContract, Augmentable, Conta
resolveGqlValue as traitResolveGqlValue;
}

const AUDIO_EXTENSIONS = ['aac', 'flac', 'm4a', 'mp3', 'ogg', 'wav'];
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif'];
const VIDEO_EXTENSIONS = ['h264', 'mp4', 'm4v', 'ogv', 'webm', 'mov'];

protected $container;
protected $path;
protected $meta;
Expand Down Expand Up @@ -471,7 +475,7 @@ public function manipulate($params = null)
*/
public function isAudio()
{
return $this->extensionIsOneOf(['aac', 'flac', 'm4a', 'mp3', 'ogg', 'wav']);
return $this->extensionIsOneOf(self::AUDIO_EXTENSIONS);
}

/**
Expand Down Expand Up @@ -504,7 +508,7 @@ public function isPreviewable()
*/
public function isImage()
{
return $this->extensionIsOneOf(['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif']);
return $this->extensionIsOneOf(self::IMAGE_EXTENSIONS);
}

/**
Expand All @@ -524,7 +528,7 @@ public function isSvg()
*/
public function isVideo()
{
return $this->extensionIsOneOf(['h264', 'mp4', 'm4v', 'ogv', 'webm', 'mov']);
return $this->extensionIsOneOf(self::VIDEO_EXTENSIONS);
}

/**
Expand Down
133 changes: 101 additions & 32 deletions src/Tags/Assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

namespace Statamic\Tags;

use Statamic\Assets\Asset as AssetModel;
use Statamic\Assets\AssetCollection;
use Statamic\Contracts\Query\Builder;
use Statamic\Facades\Asset;
use Statamic\Facades\AssetContainer;
use Statamic\Facades\Entry;
use Statamic\Facades\Pattern;
use Statamic\Fields\Value;
use Statamic\Support\Arr;

class Assets extends Tags
{
use Concerns\QueriesConditions,
Concerns\QueriesOrderBys,
Concerns\QueriesScopes;

/**
* @var AssetCollection
*/
Expand Down Expand Up @@ -40,7 +46,7 @@ public function wildcard($method)

$this->assets = (new AssetCollection([$value]))->flatten();

return $this->output();
return $this->outputCollection($this->assets);
}

if ($value instanceof Value) {
Expand All @@ -66,15 +72,17 @@ public function index()
$path = $this->params->get('path');
$collection = $this->params->get('collection');

$this->assets = $collection
? $this->assetsFromCollection($collection)
: $this->assetsFromContainer($id, $path);
if ($collection) {
return $this->outputCollection($this->assetsFromCollection($collection));
}

$this->assets = $this->assetsFromContainer($id, $path);

if ($this->assets->isEmpty()) {
return $this->parseNoResults();
}

return $this->output();
return $this->assets;
}

protected function assetsFromContainer($id, $path)
Expand All @@ -95,9 +103,29 @@ protected function assetsFromContainer($id, $path)
return collect();
}

$assets = $container->assets($this->params->get('folder'), $this->params->get('recursive', false));
$query = $container->queryAssets();

$this->queryFolder($query);
$this->queryType($query);
$this->queryConditions($query);
$this->queryScopes($query);
$this->queryOrderBys($query);

if ($this->params->get('not_in')) {
$assets = $this->filterNotIn($query->get());

return $this->limitCollection($assets);
}

if ($limit = $this->params->int('limit')) {
$query->limit($limit);
}

return $this->filterByType($assets);
if ($offset = $this->params->int('offset')) {
$query->offset($offset);
}

return $query->get();
}

protected function assetsFromCollection($collection)
Expand Down Expand Up @@ -143,6 +171,10 @@ protected function filterByType($value)
}

return $value->filter(function ($value) use ($type) {
if ($type === 'audio') {
return $value->isAudio();
}

if ($type === 'image') {
return $value->isImage();
}
Expand All @@ -161,18 +193,17 @@ protected function filterByType($value)

/**
* Filter out assets from a requested folder.
*
* @return void
*/
private function filterNotIn()
private function filterNotIn($assets)
{
if ($not_in = $this->params->get('not_in')) {
$regex = '#^('.$not_in.')#';

$this->assets = $this->assets->reject(function ($path) use ($regex) {
return preg_match($regex, $path);
});
if (! $not_in = $this->params->get('not_in')) {
return $assets;
}

$regex = '#^('.$not_in.')#';

// Checking against path for backwards compatibility. Technically folder would be more correct.
return $assets->reject(fn ($asset) => preg_match($regex, $asset->path()));
}

/**
Expand Down Expand Up @@ -204,36 +235,74 @@ protected function assets($urls)
];
});

return $this->output();
return $this->outputCollection($this->assets);
}

private function output()
private function outputCollection($assets)
{
$this->filterNotIn();
$this->assets = $this->filterNotIn($assets);

$this->sort();
$this->limit();
if ($sort = $this->params->get('sort')) {
$this->assets = $this->assets->multisort($sort);
}

$this->assets = $this->limitCollection($this->assets);

if ($this->assets->isEmpty()) {
return $this->parseNoResults();
}

return $this->assets;
}

private function sort()
private function limitCollection($assets)
{
if ($sort = $this->params->get('sort')) {
$this->assets = $this->assets->multisort($sort);
$limit = $this->params->int('limit');
$limit = ($limit == 0) ? $assets->count() : $limit;
$offset = $this->params->int('offset');

return $assets->splice($offset, $limit);
}

protected function queryType($query)
{
$type = $this->params->get('type');

if (! $type) {
return;
}

$extensions = match ($type) {
'audio' => AssetModel::AUDIO_EXTENSIONS,
'image' => AssetModel::IMAGE_EXTENSIONS,
'svg' => ['svg'],
'video' => AssetModel::VIDEO_EXTENSIONS,
default => [],
};

$query->whereIn('extension', $extensions);
}

/**
* Limit and offset the asset collection.
*/
private function limit()
protected function queryFolder($query)
{
$limit = $this->params->int('limit');
$limit = ($limit == 0) ? $this->assets->count() : $limit;
$offset = $this->params->int('offset');
$folder = $this->params->get('folder');
$recursive = $this->params->get('recursive', false);

if ($folder === '/' && $recursive) {
$folder = null;
}

if ($folder === null) {
return;
}

if ($recursive) {
$query->where('path', 'like', Pattern::sqlLikeQuote($folder).'/%');

return;
}

$this->assets = $this->assets->splice($offset, $limit);
$query->where('folder', $folder);
}

private function isAssetsFieldValue($value)
Expand Down
Loading
Loading