optimizations
This commit is contained in:
115
app/Services/EditorialAutomationService.php
Normal file
115
app/Services/EditorialAutomationService.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Collection;
|
||||
|
||||
class EditorialAutomationService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CollectionAiCurationService $curation,
|
||||
private readonly CollectionRecommendationService $recommendations,
|
||||
private readonly CollectionQualityService $quality,
|
||||
private readonly CollectionCampaignService $campaigns,
|
||||
) {
|
||||
}
|
||||
|
||||
public function qualityReview(Collection $collection): array
|
||||
{
|
||||
$scores = $this->quality->scores($collection);
|
||||
|
||||
return [
|
||||
'quality_score' => $scores['quality_score'],
|
||||
'ranking_score' => $scores['ranking_score'],
|
||||
'missing_metadata' => $this->missingMetadata($collection),
|
||||
'attention_flags' => $this->attentionFlags($collection),
|
||||
'campaign_summary' => $this->campaigns->campaignSummary($collection),
|
||||
'suggested_surface_assignments' => $this->campaigns->suggestedSurfaceAssignments($collection),
|
||||
'suggested_cover' => $this->curation->suggestCover($collection),
|
||||
'suggested_summary' => $this->curation->suggestSummary($collection),
|
||||
'suggested_related_collections' => $this->recommendations->relatedPublicCollections($collection, 4)->map(fn (Collection $item) => [
|
||||
'id' => (int) $item->id,
|
||||
'title' => $item->title,
|
||||
'slug' => $item->slug,
|
||||
])->values()->all(),
|
||||
'source' => 'editorial-automation-v1',
|
||||
];
|
||||
}
|
||||
|
||||
private function missingMetadata(Collection $collection): array
|
||||
{
|
||||
$missing = [];
|
||||
|
||||
if (blank($collection->summary)) {
|
||||
$missing[] = 'Add a sharper summary for social previews and homepage modules.';
|
||||
}
|
||||
|
||||
if (! $collection->resolvedCoverArtwork(false)) {
|
||||
$missing[] = 'Choose a cover artwork to strengthen click-through and placement eligibility.';
|
||||
}
|
||||
|
||||
if ((int) $collection->artworks_count < 4) {
|
||||
$missing[] = 'Expand the collection with a few more artworks to improve curation depth.';
|
||||
}
|
||||
|
||||
if (blank($collection->campaign_key) && blank($collection->event_key) && blank($collection->season_key)) {
|
||||
$missing[] = 'Set campaign or seasonal metadata if this collection should power event-aware discovery.';
|
||||
}
|
||||
|
||||
if (blank($collection->brand_safe_status) && (bool) $collection->commercial_eligibility) {
|
||||
$missing[] = 'Mark brand-safe status before using this collection for commercial or partner-facing placements.';
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
private function attentionFlags(Collection $collection): array
|
||||
{
|
||||
$flags = [];
|
||||
|
||||
if ($collection->last_activity_at?->lt(now()->subDays(90)) && $collection->isPubliclyAccessible()) {
|
||||
$flags[] = [
|
||||
'key' => 'stale_collection',
|
||||
'severity' => 'medium',
|
||||
'message' => 'This public collection has not been updated recently and may need editorial review.',
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->hasDuplicateTitleWithinOwner($collection)) {
|
||||
$flags[] = [
|
||||
'key' => 'possible_duplicate',
|
||||
'severity' => 'medium',
|
||||
'message' => 'Another collection from the same owner has the same title, so this set may duplicate an existing curation theme.',
|
||||
];
|
||||
}
|
||||
|
||||
if ($collection->moderation_status !== Collection::MODERATION_ACTIVE) {
|
||||
$flags[] = [
|
||||
'key' => 'moderation_block',
|
||||
'severity' => 'high',
|
||||
'message' => 'Moderation status currently blocks this collection from editorial promotion.',
|
||||
];
|
||||
}
|
||||
|
||||
if ($collection->unpublished_at?->between(now(), now()->addDays(14))) {
|
||||
$flags[] = [
|
||||
'key' => 'campaign_expiring',
|
||||
'severity' => 'low',
|
||||
'message' => 'This collection is approaching the end of its scheduled campaign window.',
|
||||
];
|
||||
}
|
||||
|
||||
return $flags;
|
||||
}
|
||||
|
||||
private function hasDuplicateTitleWithinOwner(Collection $collection): bool
|
||||
{
|
||||
return Collection::query()
|
||||
->where('id', '!=', $collection->id)
|
||||
->where('user_id', $collection->user_id)
|
||||
->whereRaw('LOWER(title) = ?', [mb_strtolower(trim((string) $collection->title))])
|
||||
->exists();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user