194 lines
6.0 KiB
PHP
194 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\FollowService;
|
|
use App\Services\UserStatsService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
final class ArtworkInteractionController extends Controller
|
|
{
|
|
public function favorite(Request $request, int $artworkId): JsonResponse
|
|
{
|
|
$state = $request->boolean('state', true);
|
|
|
|
$this->toggleSimple(
|
|
request: $request,
|
|
table: 'user_favorites',
|
|
keyColumns: ['user_id', 'artwork_id'],
|
|
keyValues: ['user_id' => (int) $request->user()->id, 'artwork_id' => $artworkId],
|
|
insertPayload: ['created_at' => now()],
|
|
requiredTable: 'user_favorites'
|
|
);
|
|
|
|
$this->syncArtworkStats($artworkId);
|
|
|
|
// Update creator's favorites_received_count
|
|
$creatorId = (int) DB::table('artworks')->where('id', $artworkId)->value('user_id');
|
|
if ($creatorId) {
|
|
$svc = app(UserStatsService::class);
|
|
if ($state) {
|
|
$svc->incrementFavoritesReceived($creatorId);
|
|
$svc->setLastActiveAt((int) $request->user()->id);
|
|
} else {
|
|
$svc->decrementFavoritesReceived($creatorId);
|
|
}
|
|
}
|
|
|
|
return response()->json($this->statusPayload((int) $request->user()->id, $artworkId));
|
|
}
|
|
|
|
public function like(Request $request, int $artworkId): JsonResponse
|
|
{
|
|
$this->toggleSimple(
|
|
request: $request,
|
|
table: 'artwork_likes',
|
|
keyColumns: ['user_id', 'artwork_id'],
|
|
keyValues: ['user_id' => (int) $request->user()->id, 'artwork_id' => $artworkId],
|
|
insertPayload: ['created_at' => now(), 'updated_at' => now()],
|
|
requiredTable: 'artwork_likes'
|
|
);
|
|
|
|
$this->syncArtworkStats($artworkId);
|
|
|
|
return response()->json($this->statusPayload((int) $request->user()->id, $artworkId));
|
|
}
|
|
|
|
public function report(Request $request, int $artworkId): JsonResponse
|
|
{
|
|
if (! Schema::hasTable('artwork_reports')) {
|
|
return response()->json(['message' => 'Reporting unavailable'], 422);
|
|
}
|
|
|
|
$data = $request->validate([
|
|
'reason' => ['nullable', 'string', 'max:1000'],
|
|
]);
|
|
|
|
DB::table('artwork_reports')->updateOrInsert(
|
|
[
|
|
'artwork_id' => $artworkId,
|
|
'reporter_user_id' => (int) $request->user()->id,
|
|
],
|
|
[
|
|
'reason' => trim((string) ($data['reason'] ?? '')) ?: null,
|
|
'reported_at' => now(),
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
|
|
return response()->json(['ok' => true, 'reported' => true]);
|
|
}
|
|
|
|
public function follow(Request $request, int $userId): JsonResponse
|
|
{
|
|
$actorId = (int) $request->user()->id;
|
|
|
|
if ($actorId === $userId) {
|
|
return response()->json(['message' => 'Cannot follow yourself'], 422);
|
|
}
|
|
|
|
$svc = app(FollowService::class);
|
|
$state = $request->boolean('state', true);
|
|
|
|
if ($state) {
|
|
$svc->follow($actorId, $userId);
|
|
} else {
|
|
$svc->unfollow($actorId, $userId);
|
|
}
|
|
|
|
return response()->json([
|
|
'ok' => true,
|
|
'is_following' => $state,
|
|
'followers_count' => $svc->followersCount($userId),
|
|
]);
|
|
}
|
|
|
|
private function toggleSimple(
|
|
Request $request,
|
|
string $table,
|
|
array $keyColumns,
|
|
array $keyValues,
|
|
array $insertPayload,
|
|
string $requiredTable
|
|
): void {
|
|
if (! Schema::hasTable($requiredTable)) {
|
|
abort(422, 'Interaction unavailable');
|
|
}
|
|
|
|
$state = $request->boolean('state', true);
|
|
|
|
$query = DB::table($table);
|
|
foreach ($keyColumns as $column) {
|
|
$query->where($column, $keyValues[$column]);
|
|
}
|
|
|
|
if ($state) {
|
|
if (! $query->exists()) {
|
|
DB::table($table)->insert(array_merge($keyValues, $insertPayload));
|
|
}
|
|
} else {
|
|
$query->delete();
|
|
}
|
|
}
|
|
|
|
private function syncArtworkStats(int $artworkId): void
|
|
{
|
|
if (! Schema::hasTable('artwork_stats')) {
|
|
return;
|
|
}
|
|
|
|
$favorites = Schema::hasTable('user_favorites')
|
|
? (int) DB::table('user_favorites')->where('artwork_id', $artworkId)->count()
|
|
: 0;
|
|
|
|
$likes = Schema::hasTable('artwork_likes')
|
|
? (int) DB::table('artwork_likes')->where('artwork_id', $artworkId)->count()
|
|
: 0;
|
|
|
|
DB::table('artwork_stats')->updateOrInsert(
|
|
['artwork_id' => $artworkId],
|
|
[
|
|
'favorites' => $favorites,
|
|
'rating_count' => $likes,
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
|
|
private function statusPayload(int $viewerId, int $artworkId): array
|
|
{
|
|
$isFavorited = Schema::hasTable('user_favorites')
|
|
? DB::table('user_favorites')->where('user_id', $viewerId)->where('artwork_id', $artworkId)->exists()
|
|
: false;
|
|
|
|
$isLiked = Schema::hasTable('artwork_likes')
|
|
? DB::table('artwork_likes')->where('user_id', $viewerId)->where('artwork_id', $artworkId)->exists()
|
|
: false;
|
|
|
|
$favorites = Schema::hasTable('user_favorites')
|
|
? (int) DB::table('user_favorites')->where('artwork_id', $artworkId)->count()
|
|
: 0;
|
|
|
|
$likes = Schema::hasTable('artwork_likes')
|
|
? (int) DB::table('artwork_likes')->where('artwork_id', $artworkId)->count()
|
|
: 0;
|
|
|
|
return [
|
|
'ok' => true,
|
|
'is_favorited' => $isFavorited,
|
|
'is_liked' => $isLiked,
|
|
'stats' => [
|
|
'favorites' => $favorites,
|
|
'likes' => $likes,
|
|
],
|
|
];
|
|
}
|
|
}
|