Save workspace changes
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Artworks;
|
||||
|
||||
final class ArtworkDraftResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly int $artworkId,
|
||||
public readonly string $status
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadChunkResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $sessionId,
|
||||
public readonly string $status,
|
||||
public readonly int $receivedBytes,
|
||||
public readonly int $totalBytes,
|
||||
public readonly int $progress
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadInitResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $sessionId,
|
||||
public readonly string $token,
|
||||
public readonly string $status
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadScanResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly bool $ok,
|
||||
public readonly string $reason
|
||||
) {
|
||||
}
|
||||
|
||||
public static function clean(): self
|
||||
{
|
||||
return new self(true, '');
|
||||
}
|
||||
|
||||
public static function infected(string $reason): self
|
||||
{
|
||||
return new self(false, $reason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
|
||||
final class UploadSessionData
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $id,
|
||||
public readonly int $userId,
|
||||
public readonly string $tempPath,
|
||||
public readonly string $status,
|
||||
public readonly string $ip,
|
||||
public readonly CarbonImmutable $createdAt,
|
||||
public readonly int $progress,
|
||||
public readonly ?string $failureReason
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadStoredFile
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $path,
|
||||
public readonly int $size,
|
||||
public readonly string $extension
|
||||
) {
|
||||
}
|
||||
|
||||
public static function fromPath(string $path): self
|
||||
{
|
||||
$size = is_file($path) ? (int) filesize($path) : 0;
|
||||
$extension = (string) pathinfo($path, PATHINFO_EXTENSION);
|
||||
|
||||
return new self($path, $size, $extension);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadValidatedFile
|
||||
{
|
||||
public function __construct(
|
||||
public readonly UploadValidationResult $validation,
|
||||
public readonly ?string $hash
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs\Uploads;
|
||||
|
||||
final class UploadValidationResult
|
||||
{
|
||||
public function __construct(
|
||||
public readonly bool $ok,
|
||||
public readonly string $reason,
|
||||
public readonly ?int $width,
|
||||
public readonly ?int $height,
|
||||
public readonly ?string $mime,
|
||||
public readonly ?int $size
|
||||
) {
|
||||
}
|
||||
|
||||
public static function ok(int $width, int $height, string $mime, int $size): self
|
||||
{
|
||||
return new self(true, '', $width, $height, $mime, $size);
|
||||
}
|
||||
|
||||
public static function fail(string $reason, ?int $width = null, ?int $height = null, ?string $mime = null, ?int $size = null): self
|
||||
{
|
||||
return new self(false, $reason, $width, $height, $mime, $size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DTOs;
|
||||
|
||||
/**
|
||||
* Lightweight value object representing a user's recommendation preference profile.
|
||||
*
|
||||
* Built by UserPreferenceBuilder from signals:
|
||||
* - favourited artworks (+3)
|
||||
* - awards given (+5)
|
||||
* - creator follows (+2 for their tags)
|
||||
* - own uploads (category bias)
|
||||
*
|
||||
* Cached in `user_reco_profiles` with a configurable TTL (default 6 hours).
|
||||
*/
|
||||
final class UserRecoProfileDTO
|
||||
{
|
||||
/**
|
||||
* @param array<int, string> $topTagSlugs Top tag slugs by weighted score (up to 20)
|
||||
* @param array<int, string> $topCategorySlugs Top category slugs (up to 5)
|
||||
* @param array<int, int> $strongCreatorIds Followed creator user IDs (up to 50)
|
||||
* @param array<string, float> $tagWeights Tag slug → normalised weight (0–1)
|
||||
* @param array<string, float> $categoryWeights Category slug → normalised weight
|
||||
* @param array<int, string> $dislikedTagSlugs Future: blocked/hidden tag slugs
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly array $topTagSlugs = [],
|
||||
public readonly array $topCategorySlugs = [],
|
||||
public readonly array $strongCreatorIds = [],
|
||||
public readonly array $tagWeights = [],
|
||||
public readonly array $categoryWeights = [],
|
||||
public readonly array $dislikedTagSlugs = [],
|
||||
) {}
|
||||
|
||||
/**
|
||||
* True if the user has enough signals to drive personalised recommendations.
|
||||
*/
|
||||
public function hasSignals(): bool
|
||||
{
|
||||
return $this->topTagSlugs !== [] || $this->strongCreatorIds !== [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalised tag weight for a given slug (0.0 if unknown).
|
||||
*/
|
||||
public function tagWeight(string $slug): float
|
||||
{
|
||||
return (float) ($this->tagWeights[$slug] ?? 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the creator is in the user's strong-follow list.
|
||||
*/
|
||||
public function followsCreator(int $userId): bool
|
||||
{
|
||||
return in_array($userId, $this->strongCreatorIds, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialise for storage in the DB / Redis cache.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'top_tags' => $this->topTagSlugs,
|
||||
'top_categories' => $this->topCategorySlugs,
|
||||
'strong_creators' => $this->strongCreatorIds,
|
||||
'tag_weights' => $this->tagWeights,
|
||||
'category_weights' => $this->categoryWeights,
|
||||
'disliked_tags' => $this->dislikedTagSlugs,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-hydrate from a stored array (e.g. from the DB JSON column).
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
return new self(
|
||||
topTagSlugs: (array) ($data['top_tags'] ?? []),
|
||||
topCategorySlugs: (array) ($data['top_categories'] ?? []),
|
||||
strongCreatorIds: array_map('intval', (array) ($data['strong_creators'] ?? [])),
|
||||
tagWeights: array_map('floatval', (array) ($data['tag_weights'] ?? [])),
|
||||
categoryWeights: array_map('floatval', (array) ($data['category_weights'] ?? [])),
|
||||
dislikedTagSlugs: (array) ($data['disliked_tags'] ?? []),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user