New_Micro_Learning/backend/app/Modules/Assets/Application/AssetUsage.php

101 خطوط
4.6 KiB
PHP

<?php
namespace App\Modules\Assets\Application;
use App\Modules\Courses\Domain\Block;
use App\Modules\Courses\Domain\Course;
use App\Modules\Courses\Domain\CourseVersion;
use App\Modules\Courses\Domain\Enums\CourseVersionStatus;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
final class AssetUsage
{
/** @return array<string, int> */
public function counts(string $organizationId): array
{
$counts = [];
Block::query()->where('organization_id', $organizationId)->get(['data'])->each(function (Block $block) use (&$counts) {
foreach ($this->assetIds($block->data) as $id) {
$counts[$id] = ($counts[$id] ?? 0) + 1;
}
});
Course::query()->where('organization_id', $organizationId)->whereNotNull('cover_asset_id')->pluck('cover_asset_id')->each(function (string $id) use (&$counts) {
$counts[$id] = ($counts[$id] ?? 0) + 1;
});
foreach (['review_threads', 'review_replies'] as $table) {
DB::table($table)->where('organization_id', $organizationId)->whereNotNull('attachment_asset_ids')->pluck('attachment_asset_ids')->each(function ($value) use (&$counts) {
foreach (json_decode($value, true) ?? [] as $id) {
$counts[$id] = ($counts[$id] ?? 0) + 1;
}
});
}
return $counts;
}
/** @param array<string, mixed>|list<mixed> $value @return list<string> */
public function assetIds(array $value): array
{
$ids = [];
foreach ($value as $key => $item) {
if (is_string($key) && ($key === 'assetId' || str_ends_with($key, 'AssetId')) && is_string($item) && $item !== '') {
$ids[] = $item;
} elseif (is_array($item)) {
array_push($ids, ...$this->assetIds($item));
}
}
return array_values(array_unique($ids));
}
public function detach(string $organizationId, string $assetId): void
{
$publishedVersionIds = CourseVersion::query()
->where('organization_id', $organizationId)
->where('status', CourseVersionStatus::Published)
->pluck('id')
->map(fn ($id): string => (string) $id)
->all();
$blocks = Block::query()->where('organization_id', $organizationId)->get();
foreach ($blocks as $block) {
if (in_array($assetId, $this->assetIds($block->data), true) && in_array((string) $block->course_version_id, $publishedVersionIds, true)) {
throw ValidationException::withMessages(['asset' => ['این فایل در نسخه منتشرشده استفاده شده و تا زمان ایجاد نسخه قابل‌ویرایش قابل حذف نیست.']]);
}
}
foreach ($blocks as $block) {
if (! in_array($assetId, $this->assetIds($block->data), true)) {
continue;
}
$block->update(['data' => $this->withoutAsset($block->data, $assetId), 'revision' => $block->revision + 1]);
}
Course::query()->where('organization_id', $organizationId)->where('cover_asset_id', $assetId)->update(['cover_asset_id' => null]);
foreach (['review_threads', 'review_replies'] as $table) {
DB::table($table)->where('organization_id', $organizationId)->whereNotNull('attachment_asset_ids')->get(['id', 'attachment_asset_ids'])->each(function ($row) use ($table, $assetId): void {
$ids = array_values(array_filter(json_decode($row->attachment_asset_ids, true) ?? [], fn ($id) => $id !== $assetId));
DB::table($table)->where('id', $row->id)->update(['attachment_asset_ids' => json_encode($ids), 'updated_at' => now()]);
});
}
}
/** @param array<string, mixed>|list<mixed> $value @return array<string, mixed>|list<mixed> */
private function withoutAsset(array $value, string $assetId): array
{
if (array_is_list($value)) {
return array_values(array_map(
fn ($item) => is_array($item) ? $this->withoutAsset($item, $assetId) : $item,
array_filter($value, fn ($item): bool => ! (is_array($item) && ($item['assetId'] ?? null) === $assetId)),
));
}
foreach ($value as $key => $item) {
if (is_string($key) && ($key === 'assetId' || str_ends_with($key, 'AssetId')) && $item === $assetId) {
$value[$key] = null;
} elseif (is_array($item)) {
$value[$key] = $this->withoutAsset($item, $assetId);
}
}
return $value;
}
}