2025-07-05 18:26:04 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
use App\Models\Feed;
|
2025-07-06 20:37:55 +02:00
|
|
|
use App\Models\FeedPlatformChannel;
|
2025-07-05 18:26:04 +02:00
|
|
|
use App\Models\PlatformChannel;
|
|
|
|
|
use App\Services\RoutingValidationService;
|
|
|
|
|
use App\Exceptions\RoutingMismatchException;
|
2025-07-07 02:48:46 +02:00
|
|
|
use Illuminate\Database\Eloquent\Collection;
|
2025-07-05 18:26:04 +02:00
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Illuminate\Contracts\View\View;
|
|
|
|
|
use Illuminate\Http\RedirectResponse;
|
|
|
|
|
|
|
|
|
|
class RoutingController extends Controller
|
|
|
|
|
{
|
|
|
|
|
public function index(): View
|
|
|
|
|
{
|
|
|
|
|
$feeds = Feed::with(['channels.platformInstance'])
|
|
|
|
|
->where('is_active', true)
|
|
|
|
|
->orderBy('name')
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
$channels = PlatformChannel::with(['platformInstance', 'feeds'])
|
|
|
|
|
->where('is_active', true)
|
|
|
|
|
->orderBy('name')
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
return view('pages.routing.index', compact('feeds', 'channels'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function create(): View
|
|
|
|
|
{
|
|
|
|
|
$feeds = Feed::where('is_active', true)
|
|
|
|
|
->orderBy('name')
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
$channels = PlatformChannel::with('platformInstance')
|
|
|
|
|
->where('is_active', true)
|
|
|
|
|
->orderBy('name')
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
return view('pages.routing.create', compact('feeds', 'channels'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
|
|
|
{
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'feed_id' => 'required|exists:feeds,id',
|
|
|
|
|
'channel_ids' => 'required|array|min:1',
|
|
|
|
|
'channel_ids.*' => 'exists:platform_channels,id',
|
|
|
|
|
'priority' => 'integer|min:0|max:100',
|
|
|
|
|
'filters' => 'nullable|string'
|
|
|
|
|
]);
|
|
|
|
|
|
2025-07-07 02:48:46 +02:00
|
|
|
/** @var Feed $feed */
|
2025-07-05 18:26:04 +02:00
|
|
|
$feed = Feed::findOrFail($validated['feed_id']);
|
2025-07-07 02:48:46 +02:00
|
|
|
|
|
|
|
|
/** @var Collection<int, PlatformChannel> $channels */
|
2025-07-05 18:26:04 +02:00
|
|
|
$channels = PlatformChannel::findMany($validated['channel_ids']);
|
|
|
|
|
$priority = $validated['priority'] ?? 0;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
app(RoutingValidationService::class)->validateLanguageCompatibility($feed, $channels);
|
|
|
|
|
} catch (RoutingMismatchException $e) {
|
|
|
|
|
return redirect()->back()
|
|
|
|
|
->withInput()
|
|
|
|
|
->withErrors(['language' => $e->getMessage()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$filters = $this->parseJsonFilters($validated['filters'] ?? null);
|
|
|
|
|
|
|
|
|
|
// Attach channels to feed
|
|
|
|
|
$syncData = [];
|
|
|
|
|
foreach ($validated['channel_ids'] as $channelId) {
|
|
|
|
|
$syncData[$channelId] = [
|
|
|
|
|
'is_active' => true,
|
|
|
|
|
'priority' => $priority,
|
|
|
|
|
'filters' => $filters,
|
|
|
|
|
'created_at' => now(),
|
|
|
|
|
'updated_at' => now()
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$feed->channels()->syncWithoutDetaching($syncData);
|
|
|
|
|
|
|
|
|
|
return redirect()->route('routing.index')
|
|
|
|
|
->with('success', 'Feed routing created successfully!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function edit(Feed $feed, PlatformChannel $channel): View
|
|
|
|
|
{
|
|
|
|
|
$routing = $feed->channels()
|
|
|
|
|
->wherePivot('platform_channel_id', $channel->id)
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (! $routing) {
|
|
|
|
|
abort(404, 'Routing not found');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return view('pages.routing.edit', compact('feed', 'channel', 'routing'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function update(Request $request, Feed $feed, PlatformChannel $channel): RedirectResponse
|
|
|
|
|
{
|
|
|
|
|
$validated = $request->validate([
|
|
|
|
|
'is_active' => 'boolean',
|
|
|
|
|
'priority' => 'integer|min:0|max:100',
|
|
|
|
|
'filters' => 'nullable|string'
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$filters = $this->parseJsonFilters($validated['filters'] ?? null);
|
|
|
|
|
|
|
|
|
|
$feed->channels()->updateExistingPivot($channel->id, [
|
|
|
|
|
'is_active' => $validated['is_active'] ?? true,
|
|
|
|
|
'priority' => $validated['priority'] ?? 0,
|
|
|
|
|
'filters' => $filters,
|
|
|
|
|
'updated_at' => now()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return redirect()->route('routing.index')
|
|
|
|
|
->with('success', 'Routing updated successfully!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function destroy(Feed $feed, PlatformChannel $channel): RedirectResponse
|
|
|
|
|
{
|
|
|
|
|
$feed->channels()->detach($channel->id);
|
|
|
|
|
|
|
|
|
|
return redirect()->route('routing.index')
|
|
|
|
|
->with('success', 'Routing deleted successfully!');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function toggle(Request $request, Feed $feed, PlatformChannel $channel): RedirectResponse
|
|
|
|
|
{
|
2025-07-06 20:37:55 +02:00
|
|
|
$routing = FeedPlatformChannel::where('feed_id', $feed->id)
|
|
|
|
|
->where('platform_channel_id', $channel->id)
|
2025-07-05 18:26:04 +02:00
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (! $routing) {
|
|
|
|
|
abort(404, 'Routing not found');
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-06 20:37:55 +02:00
|
|
|
$newStatus = ! $routing->is_active;
|
2025-07-05 18:26:04 +02:00
|
|
|
|
|
|
|
|
$feed->channels()->updateExistingPivot($channel->id, [
|
|
|
|
|
'is_active' => $newStatus,
|
|
|
|
|
'updated_at' => now()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$status = $newStatus ? 'activated' : 'deactivated';
|
|
|
|
|
|
|
|
|
|
return redirect()->route('routing.index')
|
|
|
|
|
->with('success', "Routing {$status} successfully!");
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-07 00:51:32 +02:00
|
|
|
/**
|
|
|
|
|
* @return array<string, mixed>|null
|
|
|
|
|
*/
|
2025-07-05 18:26:04 +02:00
|
|
|
private function parseJsonFilters(?string $json): ?array
|
|
|
|
|
{
|
|
|
|
|
if (empty($json)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$decoded = json_decode($json, true);
|
|
|
|
|
|
|
|
|
|
if (json_last_error() === JSON_ERROR_NONE) {
|
|
|
|
|
return $decoded;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|