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' ]); /** @var Feed $feed */ $feed = Feed::findOrFail($validated['feed_id']); /** @var Collection $channels */ $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 { $routing = FeedPlatformChannel::where('feed_id', $feed->id) ->where('platform_channel_id', $channel->id) ->first(); if (! $routing) { abort(404, 'Routing not found'); } $newStatus = ! $routing->is_active; $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!"); } /** * @return array|null */ 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; } }