Skip to content

Commit 77f3814

Browse files
committed
Add tests
1 parent 863da68 commit 77f3814

File tree

15 files changed

+433
-22
lines changed

15 files changed

+433
-22
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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\VolumeFolder;
9+
use CraftCms\Cms\Element\Models\Element;
10+
use Illuminate\Database\Eloquent\Factories\Factory;
11+
use Override;
12+
13+
final class AssetFactory extends Factory
14+
{
15+
protected $model = Asset::class;
16+
17+
#[Override]
18+
public function definition(): array
19+
{
20+
return [
21+
'id' => Element::factory()->set('type', \CraftCms\Cms\Element\Elements\Asset::class),
22+
'folderId' => VolumeFolder::factory(),
23+
'filename' => fake()->word().'.jpg',
24+
'kind' => 'image',
25+
];
26+
}
27+
28+
#[\Override]
29+
public function configure(): self
30+
{
31+
return $this->afterCreating(function (Asset $asset) {
32+
$asset->element->update([
33+
'dateCreated' => $asset->dateCreated,
34+
'dateUpdated' => $asset->dateCreated,
35+
]);
36+
37+
$asset->update(['volumeId' => $asset->folder->volume?->id]);
38+
});
39+
}
40+
}
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/Models/Asset.php

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

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 \Illuminate\Database\Eloquent\Relations\BelongsTo<\CraftCms\Cms\FieldLayout\Models\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 \Illuminate\Database\Eloquent\Relations\BelongsTo<\CraftCms\Cms\Asset\Models\VolumeFolder, $this>
23+
*/
24+
public function parent(): BelongsTo
25+
{
26+
return $this->belongsTo(self::class, 'parentId');
27+
}
28+
29+
/**
30+
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\CraftCms\Cms\Asset\Models\VolumeFolder, $this>
31+
*/
32+
public function children(): HasMany
33+
{
34+
return $this->hasMany(self::class, 'parentId');
35+
}
36+
37+
/**
38+
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\CraftCms\Cms\Asset\Models\Volume, $this>
39+
*/
40+
public function volume(): BelongsTo
41+
{
42+
return $this->belongsTo(Volume::class, 'volumeId');
43+
}
44+
}

src/Database/Queries/AssetQuery.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ public function __construct(array $config = [])
6363
'assets.keptFile as keptFile',
6464
'assets.dateModified as dateModified',
6565
'assets.mimeType as mimeType',
66-
'siteAlt' => 'assets_sites.alt as siteAlt',
67-
'folderPath' => 'volumeFolders.path as folderPath',
66+
'assets_sites.alt as siteAlt',
67+
'volumeFolders.path as folderPath',
6868
]);
6969

7070
$this->beforeQuery(function (self $elementQuery) {
7171
$elementQuery->query->leftJoin(new Alias(Table::ASSETS_SITES, 'assets_sites'), function (JoinClause $join) {
7272
$join->on('assets_sites.assetId', '=', 'assets.id')
73-
->where('assets_sites.siteId', '=', 'elements_sites.siteId');
73+
->whereColumn('assets_sites.siteId', '=', 'elements_sites.siteId');
7474
});
7575

7676
$elementQuery->applyAuthParam($elementQuery->editable, 'viewAssets', 'viewPeerAssets');
@@ -170,10 +170,7 @@ private function applyAuthParam(?bool $value, string $permissionPrefix, string $
170170
});
171171
}
172172

173-
/**
174-
* {@inheritdoc}
175-
*/
176-
public function createElement(array $row): ElementInterface
173+
protected function createElement(array $row): ElementInterface
177174
{
178175
// Use the site-specific alt text, if set
179176
$siteAlt = Arr::pull($row, 'siteAlt');
@@ -217,7 +214,7 @@ protected function fieldLayouts(): Collection
217214
$fieldLayouts = [];
218215
$volumesService = Craft::$app->getVolumes();
219216

220-
foreach ($this->volumeId as $volumeId) {
217+
foreach (Arr::wrap($this->volumeId) as $volumeId) {
221218
if ($volume = $volumesService->getVolumeById($volumeId)) {
222219
$fieldLayouts[] = $volume->getFieldLayout();
223220
}

src/Database/Queries/Concerns/Asset/QueriesAlt.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ protected function initQueriesAlt(): void
5252
$this->subQuery
5353
->leftJoin(new Alias(Table::ASSETS_SITES, 'assets_sites'), function (JoinClause $join) {
5454
$join->on('assets_sites.assetId', '=', 'assets.id')
55-
->where('assets_sites.siteId', '=', 'elements_sites.siteId');
55+
->whereColumn('assets_sites.siteId', '=', 'elements_sites.siteId');
5656
})
5757
->where($this->hasAlt ? $hasAltCondition : $withoutAltCondition);
5858
});

src/Database/Queries/Concerns/Asset/QueriesAssetLocation.php

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ function (Builder $query) use ($assetQuery) {
105105
}
106106

107107
if ($assetQuery->folderPath) {
108-
$folderPath = (array) $assetQuery->folderPath;
108+
$folderPath = Arr::wrap($assetQuery->folderPath);
109+
109110
foreach ($folderPath as &$path) {
110111
if (
111112
is_string($path) &&
@@ -150,9 +151,6 @@ function (Builder $query) use ($assetQuery) {
150151
* ->all();
151152
* ```
152153
*
153-
* @param mixed $value The property value
154-
* @return static self reference
155-
*
156154
* @uses $volumeId
157155
*/
158156
public function volume(mixed $value): static
@@ -162,6 +160,10 @@ public function volume(mixed $value): static
162160
$item = Craft::$app->getVolumes()->getVolumeByHandle($item);
163161
}
164162

163+
if (is_numeric($item)) {
164+
return (int) $item;
165+
}
166+
165167
return $item instanceof Volume ? $item->id : null;
166168
})) {
167169
$this->volumeId = $value;
@@ -207,9 +209,6 @@ public function volume(mixed $value): static
207209
* ->all();
208210
* ```
209211
*
210-
* @param mixed $value The property value
211-
* @return static self reference
212-
*
213212
* @uses $volumeId
214213
*/
215214
public function volumeId(mixed $value): static
@@ -253,9 +252,6 @@ public function volumeId(mixed $value): static
253252
* This can be combined with [[includeSubfolders()]] if you want to include assets in all the subfolders of a certain folder.
254253
* :::
255254
*
256-
* @param mixed $value The property value
257-
* @return static self reference
258-
*
259255
* @uses $folderId
260256
*/
261257
public function folderId(mixed $value): static
@@ -333,9 +329,6 @@ public function includeSubfolders(bool $value = true): static
333329
* ->all();
334330
* ```
335331
*
336-
* @param mixed $value The property value
337-
* @return static self reference
338-
*
339332
* @uses $folderPath
340333
*/
341334
public function folderPath(mixed $value): static
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
use CraftCms\Cms\Asset\Models\Asset as AssetModel;
4+
use CraftCms\Cms\Edition;
5+
use CraftCms\Cms\Element\Elements\Asset;
6+
use CraftCms\Cms\User\Models\User;
7+
8+
use function Pest\Laravel\actingAs;
9+
10+
test('editable/savable returns 0 when having no access', function (string $method) {
11+
actingAs(User::first());
12+
13+
Edition::set(Edition::Pro);
14+
15+
AssetModel::factory()->create();
16+
17+
expect(assetQuery()->$method()->count())->toBe(1);
18+
19+
actingAs(User::factory()->create());
20+
21+
// Access to nothing
22+
expect(assetQuery()->$method()->count())->toBe(0);
23+
})->with([
24+
'editable',
25+
'savable',
26+
]);
27+
28+
test('it adds the volume as a cache tag', function () {
29+
Craft::$app->getElements()->startCollectingCacheInfo();
30+
31+
$asset = AssetModel::factory()->create();
32+
33+
assetQuery()->volumeId($asset->volumeId)->all();
34+
35+
/** @var \CraftCms\DependencyAwareCache\Dependency\TagDependency $dependency */
36+
$dependency = Craft::$app->getElements()->stopCollectingCacheInfo()[0];
37+
38+
expect($dependency->tags)->toContain('element::'.Asset::class.'::volume:'.$asset->volumeId);
39+
});

0 commit comments

Comments
 (0)