Implement creator studio and upload updates
This commit is contained in:
194
app/Services/Studio/CreatorStudioScheduledService.php
Normal file
194
app/Services/Studio/CreatorStudioScheduledService.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Studio;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Services\Studio\Contracts\CreatorStudioProvider;
|
||||
|
||||
final class CreatorStudioScheduledService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CreatorStudioContentService $content,
|
||||
) {
|
||||
}
|
||||
|
||||
public function upcoming(User $user, int $limit = 20): array
|
||||
{
|
||||
return collect($this->content->providers())
|
||||
->flatMap(fn (CreatorStudioProvider $provider) => $provider->scheduledItems($user, $limit * 2))
|
||||
->sortBy(fn (array $item): int => $this->scheduledTimestamp($item))
|
||||
->take($limit)
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $filters
|
||||
*/
|
||||
public function list(User $user, array $filters = []): array
|
||||
{
|
||||
$module = $this->normalizeModule((string) ($filters['module'] ?? 'all'));
|
||||
$q = trim((string) ($filters['q'] ?? ''));
|
||||
$range = $this->normalizeRange((string) ($filters['range'] ?? 'upcoming'));
|
||||
$startDate = $this->normalizeDate((string) ($filters['start_date'] ?? ''));
|
||||
$endDate = $this->normalizeDate((string) ($filters['end_date'] ?? ''));
|
||||
$page = max(1, (int) ($filters['page'] ?? 1));
|
||||
$perPage = min(max((int) ($filters['per_page'] ?? 24), 12), 48);
|
||||
|
||||
$items = $module === 'all'
|
||||
? collect($this->content->providers())->flatMap(fn (CreatorStudioProvider $provider) => $provider->scheduledItems($user, 120))
|
||||
: ($this->content->provider($module)?->scheduledItems($user, 120) ?? collect());
|
||||
|
||||
if ($q !== '') {
|
||||
$needle = mb_strtolower($q);
|
||||
$items = $items->filter(function (array $item) use ($needle): bool {
|
||||
return collect([
|
||||
$item['title'] ?? '',
|
||||
$item['subtitle'] ?? '',
|
||||
$item['module_label'] ?? '',
|
||||
])->contains(fn ($value): bool => is_string($value) && str_contains(mb_strtolower($value), $needle));
|
||||
});
|
||||
}
|
||||
|
||||
$items = $items->filter(function (array $item) use ($range, $startDate, $endDate): bool {
|
||||
$timestamp = $this->scheduledTimestamp($item);
|
||||
if ($timestamp === PHP_INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($range === 'today') {
|
||||
return $timestamp >= now()->startOfDay()->getTimestamp() && $timestamp <= now()->endOfDay()->getTimestamp();
|
||||
}
|
||||
|
||||
if ($range === 'week') {
|
||||
return $timestamp >= now()->startOfDay()->getTimestamp() && $timestamp <= now()->addDays(7)->endOfDay()->getTimestamp();
|
||||
}
|
||||
|
||||
if ($range === 'month') {
|
||||
return $timestamp >= now()->startOfDay()->getTimestamp() && $timestamp <= now()->addDays(30)->endOfDay()->getTimestamp();
|
||||
}
|
||||
|
||||
if ($startDate !== null && $timestamp < strtotime($startDate . ' 00:00:00')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($endDate !== null && $timestamp > strtotime($endDate . ' 23:59:59')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$items = $items
|
||||
->sortBy(fn (array $item): int => $this->scheduledTimestamp($item))
|
||||
->values();
|
||||
|
||||
$total = $items->count();
|
||||
$lastPage = max(1, (int) ceil($total / $perPage));
|
||||
$page = min($page, $lastPage);
|
||||
|
||||
return [
|
||||
'items' => $items->forPage($page, $perPage)->values()->all(),
|
||||
'meta' => [
|
||||
'current_page' => $page,
|
||||
'last_page' => $lastPage,
|
||||
'per_page' => $perPage,
|
||||
'total' => $total,
|
||||
],
|
||||
'filters' => [
|
||||
'module' => $module,
|
||||
'q' => $q,
|
||||
'range' => $range,
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
],
|
||||
'module_options' => array_merge([
|
||||
['value' => 'all', 'label' => 'All scheduled content'],
|
||||
], collect($this->content->moduleSummaries($user))->map(fn (array $summary): array => [
|
||||
'value' => $summary['key'],
|
||||
'label' => $summary['label'],
|
||||
])->all()),
|
||||
'range_options' => [
|
||||
['value' => 'upcoming', 'label' => 'All upcoming'],
|
||||
['value' => 'today', 'label' => 'Today'],
|
||||
['value' => 'week', 'label' => 'Next 7 days'],
|
||||
['value' => 'month', 'label' => 'Next 30 days'],
|
||||
['value' => 'custom', 'label' => 'Custom range'],
|
||||
],
|
||||
'summary' => $this->summary($user),
|
||||
'agenda' => $this->agenda($user, 14),
|
||||
];
|
||||
}
|
||||
|
||||
public function summary(User $user): array
|
||||
{
|
||||
$items = collect($this->upcoming($user, 200));
|
||||
|
||||
return [
|
||||
'total' => $items->count(),
|
||||
'next_publish_at' => $items->first()['scheduled_at'] ?? null,
|
||||
'by_module' => collect($this->content->moduleSummaries($user))
|
||||
->map(fn (array $summary): array => [
|
||||
'key' => $summary['key'],
|
||||
'label' => $summary['label'],
|
||||
'count' => $items->where('module', $summary['key'])->count(),
|
||||
'icon' => $summary['icon'],
|
||||
])
|
||||
->values()
|
||||
->all(),
|
||||
];
|
||||
}
|
||||
|
||||
public function agenda(User $user, int $days = 14): array
|
||||
{
|
||||
return collect($this->upcoming($user, 200))
|
||||
->filter(fn (array $item): bool => $this->scheduledTimestamp($item) <= now()->addDays($days)->getTimestamp())
|
||||
->groupBy(function (array $item): string {
|
||||
$value = (string) ($item['scheduled_at'] ?? $item['published_at'] ?? now()->toIso8601String());
|
||||
|
||||
return date('Y-m-d', strtotime($value));
|
||||
})
|
||||
->map(fn ($group, string $date): array => [
|
||||
'date' => $date,
|
||||
'label' => date('M j', strtotime($date)),
|
||||
'count' => $group->count(),
|
||||
'items' => $group->values()->all(),
|
||||
])
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
private function normalizeModule(string $module): string
|
||||
{
|
||||
return in_array($module, ['all', 'artworks', 'cards', 'collections', 'stories'], true)
|
||||
? $module
|
||||
: 'all';
|
||||
}
|
||||
|
||||
private function normalizeRange(string $range): string
|
||||
{
|
||||
return in_array($range, ['upcoming', 'today', 'week', 'month', 'custom'], true)
|
||||
? $range
|
||||
: 'upcoming';
|
||||
}
|
||||
|
||||
private function normalizeDate(string $value): ?string
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) === 1 ? $value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $item
|
||||
*/
|
||||
private function scheduledTimestamp(array $item): int
|
||||
{
|
||||
return strtotime((string) ($item['scheduled_at'] ?? $item['published_at'] ?? $item['updated_at'] ?? now()->toIso8601String())) ?: PHP_INT_MAX;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user