Skip to content

Commit d061836

Browse files
authored
Merge pull request #18085 from craftcms/feature/asset-query
[6.x] Asset Query
2 parents 992d5d1 + bc19311 commit d061836

28 files changed

+1779
-49
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Database\Factories;
6+
7+
use CraftCms\Cms\Asset\Models\Asset;
8+
use CraftCms\Cms\Asset\Models\Volume;
9+
use CraftCms\Cms\Asset\Models\VolumeFolder;
10+
use CraftCms\Cms\Element\Models\Element;
11+
use Illuminate\Database\Eloquent\Factories\Factory;
12+
use Override;
13+
14+
final class AssetFactory extends Factory
15+
{
16+
protected $model = Asset::class;
17+
18+
#[Override]
19+
public function definition(): array
20+
{
21+
return [
22+
'id' => Element::factory()->set('type', \CraftCms\Cms\Element\Elements\Asset::class),
23+
'volumeId' => Volume::factory(),
24+
'folderId' => VolumeFolder::factory(),
25+
'filename' => fake()->word().'.jpg',
26+
'kind' => 'image',
27+
];
28+
}
29+
30+
#[\Override]
31+
public function configure(): self
32+
{
33+
return $this->afterCreating(function (Asset $asset) {
34+
// For some reason the element factory doesn't get saved properly
35+
if ($asset->id === 0) {
36+
$asset->update([
37+
'id' => Element::query()
38+
->where('type', \CraftCms\Cms\Element\Elements\Asset::class)
39+
->latest('id')
40+
->first()
41+
->id,
42+
]);
43+
}
44+
});
45+
}
46+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Database\Factories;
6+
7+
use craft\fs\Local;
8+
use CraftCms\Cms\Asset\Models\Volume;
9+
use Illuminate\Database\Eloquent\Factories\Factory;
10+
use Override;
11+
12+
final class VolumeFactory extends Factory
13+
{
14+
protected $model = Volume::class;
15+
16+
#[Override]
17+
public function definition(): array
18+
{
19+
return [
20+
'name' => fake()->word(),
21+
'handle' => fake()->slug(),
22+
'fs' => Local::class,
23+
];
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Database\Factories;
6+
7+
use CraftCms\Cms\Asset\Models\Volume;
8+
use CraftCms\Cms\Asset\Models\VolumeFolder;
9+
use Illuminate\Database\Eloquent\Factories\Factory;
10+
use Override;
11+
12+
final class VolumeFolderFactory extends Factory
13+
{
14+
protected $model = VolumeFolder::class;
15+
16+
#[Override]
17+
public function definition(): array
18+
{
19+
return [
20+
'volumeId' => Volume::factory(),
21+
'name' => fake()->word(),
22+
];
23+
}
24+
}

src/Asset/Commands/Concerns/IndexesAssets.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace CraftCms\Cms\Asset\Commands\Concerns;
66

77
use craft\console\Application;
8-
use craft\elements\Asset;
98
use craft\errors\AssetDisallowedExtensionException;
109
use craft\errors\AssetNotIndexableException;
1110
use craft\errors\MissingAssetException;
@@ -15,6 +14,7 @@
1514
use craft\models\Volume;
1615
use craft\services\AssetIndexer;
1716
use CraftCms\Cms\Database\Table;
17+
use CraftCms\Cms\Element\Elements\Asset;
1818
use CraftCms\Cms\Support\Str;
1919
use Illuminate\Support\Collection;
2020
use Illuminate\Support\Facades\DB;
@@ -109,8 +109,8 @@ protected function indexAssets(Application $craft, array $volumes, string $path
109109
$this->components->task(
110110
'Deleting the'.($totalMissingFiles > 1 ? ' '.$totalMissingFiles : '').' missing asset record'.Str::plural('record', $totalMissingFiles),
111111
function () use ($craft, $assetIds) {
112-
/** @var Asset[] $assets */
113-
$assets = Asset::find()->id($assetIds)->all();
112+
/** @var \craft\elements\ElementCollection<Asset> $assets */
113+
$assets = Asset::find()->id($assetIds)->get();
114114

115115
foreach ($assets as $asset) {
116116
$craft->getImageTransforms()->deleteCreatedTransformsForAsset($asset);

src/Asset/Models/Asset.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Asset\Models;
6+
7+
use CraftCms\Cms\Database\Table;
8+
use CraftCms\Cms\Element\Models\Element;
9+
use CraftCms\Cms\Shared\BaseModel;
10+
use CraftCms\Cms\Site\Models\Site;
11+
use CraftCms\Cms\User\Models\User;
12+
use Illuminate\Database\Eloquent\Factories\HasFactory;
13+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
14+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
15+
use Illuminate\Database\Eloquent\Relations\Pivot;
16+
17+
final class Asset extends BaseModel
18+
{
19+
use HasFactory;
20+
21+
protected $table = Table::ASSETS;
22+
23+
protected function casts(): array
24+
{
25+
return [
26+
'width' => 'int',
27+
'height' => 'int',
28+
'size' => 'int',
29+
'deletedWithVolume' => 'bool',
30+
'keptFile' => 'bool',
31+
'dateModified' => 'datetime',
32+
];
33+
}
34+
35+
/**
36+
* @return BelongsTo<Element, $this>
37+
*/
38+
public function element(): BelongsTo
39+
{
40+
return $this->belongsTo(Element::class, 'id');
41+
}
42+
43+
/**
44+
* @return BelongsToMany<Site, $this, Pivot>
45+
*/
46+
public function sites(): BelongsToMany
47+
{
48+
return $this->belongsToMany(Site::class, 'assets_sites', 'assetId', 'siteId')
49+
->withPivot('alt');
50+
}
51+
52+
/**
53+
* @return BelongsTo<Volume, $this>
54+
*/
55+
public function volume(): BelongsTo
56+
{
57+
return $this->belongsTo(Volume::class, 'volumeId');
58+
}
59+
60+
/**
61+
* @return BelongsTo<VolumeFolder, $this>
62+
*/
63+
public function folder(): BelongsTo
64+
{
65+
return $this->belongsTo(VolumeFolder::class, 'folderId');
66+
}
67+
68+
/**
69+
* @return BelongsTo<User, $this>
70+
*/
71+
public function uploader(): BelongsTo
72+
{
73+
return $this->belongsTo(User::class, 'uploaderId');
74+
}
75+
}

src/Asset/Models/Volume.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Asset\Models;
6+
7+
use CraftCms\Cms\Database\Table;
8+
use CraftCms\Cms\FieldLayout\Models\FieldLayout;
9+
use CraftCms\Cms\Shared\BaseModel;
10+
use CraftCms\Cms\Shared\Concerns\HasUid;
11+
use Illuminate\Database\Eloquent\Factories\HasFactory;
12+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
13+
use Illuminate\Database\Eloquent\SoftDeletes;
14+
15+
final class Volume extends BaseModel
16+
{
17+
use HasFactory;
18+
use HasUid;
19+
use SoftDeletes;
20+
21+
protected $table = Table::VOLUMES;
22+
23+
protected function casts(): array
24+
{
25+
return [
26+
'sortOrder' => 'int',
27+
];
28+
}
29+
30+
/**
31+
* @return BelongsTo<FieldLayout, $this>
32+
*/
33+
public function fieldLayout(): BelongsTo
34+
{
35+
return $this->belongsTo(FieldLayout::class, 'fieldLayoutId');
36+
}
37+
}

src/Asset/Models/VolumeFolder.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CraftCms\Cms\Asset\Models;
6+
7+
use CraftCms\Cms\Database\Table;
8+
use CraftCms\Cms\Shared\BaseModel;
9+
use CraftCms\Cms\Shared\Concerns\HasUid;
10+
use Illuminate\Database\Eloquent\Factories\HasFactory;
11+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
12+
use Illuminate\Database\Eloquent\Relations\HasMany;
13+
14+
final class VolumeFolder extends BaseModel
15+
{
16+
use HasFactory;
17+
use HasUid;
18+
19+
protected $table = Table::VOLUMEFOLDERS;
20+
21+
/**
22+
* @return BelongsTo<VolumeFolder, $this>
23+
*/
24+
public function parent(): BelongsTo
25+
{
26+
return $this->belongsTo(self::class, 'parentId');
27+
}
28+
29+
/**
30+
* @return HasMany<VolumeFolder, $this>
31+
*/
32+
public function children(): HasMany
33+
{
34+
return $this->hasMany(self::class, 'parentId');
35+
}
36+
37+
/**
38+
* @return BelongsTo<Volume, $this>
39+
*/
40+
public function volume(): BelongsTo
41+
{
42+
return $this->belongsTo(Volume::class, 'volumeId');
43+
}
44+
}

src/Console/Commands/Utils/AsciiFilenamesCommand.php

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
namespace CraftCms\Cms\Console\Commands\Utils;
66

77
use Craft;
8-
use craft\elements\Asset;
98
use craft\errors\InvalidElementException;
109
use craft\helpers\FileHelper;
1110
use CraftCms\Cms\Config\GeneralConfig;
1211
use CraftCms\Cms\Console\CraftCommand;
12+
use CraftCms\Cms\Element\Elements\Asset;
13+
use Exception;
1314
use Illuminate\Console\Command;
1415
use Illuminate\Support\Facades\DB;
1516
use Throwable;
16-
use yii\db\Expression;
1717

1818
use function Laravel\Prompts\confirm;
1919

@@ -42,15 +42,15 @@ public function handle(GeneralConfig $generalConfig): int
4242

4343
match (DB::connection()->getDriverName()) {
4444
// h/t https://stackoverflow.com/a/11741314/1688568
45-
'mysql' => $query->andWhere(new Expression('[[filename]] <> CONVERT([[filename]] USING ASCII)')),
45+
'mysql' => $query->whereRaw('filename <> CONVERT(filename USING ASCII)'),
4646
// h/t https://dba.stackexchange.com/a/167571/205387
47-
'pgsql' => $query->andWhere(new Expression("[[filename]] ~ '[^[:ascii:]]'")),
48-
default => throw new \Exception('Invalid driver name: '.DB::connection()->getDriverName().'.')
47+
'pgsql' => $query->whereRaw("filename ~ '[^[:ascii:]]'"),
48+
default => throw new Exception('Invalid driver name: '.DB::connection()->getDriverName().'.')
4949
};
5050

51-
/** @var Asset[] $assets */
52-
$assets = $query->all();
53-
$total = count($assets);
51+
/** @var \Illuminate\Support\Collection<Asset> $assets */
52+
$assets = $query->get();
53+
$total = $assets->count();
5454

5555
if ($total === 0) {
5656
$this->components->success('No assets found with non-ASCII filenames.');
@@ -60,10 +60,9 @@ public function handle(GeneralConfig $generalConfig): int
6060

6161
$this->components->info("$total assets found with non-ASCII filenames:");
6262

63-
$this->components->bulletList(array_map(
63+
$this->components->bulletList($assets->map(
6464
fn (Asset $asset) => $asset->getFilename(),
65-
$assets,
66-
));
65+
)->all());
6766

6867
if (! confirm('Ready to rename these filenames as ASCII?')) {
6968
return self::SUCCESS;

0 commit comments

Comments
 (0)