You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
4.8 KiB

<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreSignupChannelRequest;
use App\Http\Requests\Admin\UpdateSignupChannelRequest;
use App\Models\Competition;
use App\Models\SignupChannel;
use App\Support\ChannelEntryEncryption;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
class SignupChannelController extends Controller
{
public function index(Competition $competition): JsonResponse
{
$channels = $competition->signupChannels()
->orderByDesc('id')
->get()
->map(fn (SignupChannel $channel) => $this->toSummary($channel, $competition))
->values();
return response()->json([
'data' => $channels,
]);
}
public function store(StoreSignupChannelRequest $request, Competition $competition): JsonResponse
{
/** @var SignupChannel $channel */
$channel = $competition->signupChannels()->create(
$this->normalizePayload($request->validated(), true)
);
return response()->json($this->toDetail($channel, $competition), 201);
}
public function show(Competition $competition, SignupChannel $signupChannel): JsonResponse
{
$this->assertChannelBelongs($competition, $signupChannel);
$this->ensureEncryptionKeyPair($signupChannel);
return response()->json($this->toDetail($signupChannel, $competition));
}
public function update(
UpdateSignupChannelRequest $request,
Competition $competition,
SignupChannel $signupChannel
): JsonResponse {
$this->assertChannelBelongs($competition, $signupChannel);
$signupChannel->fill($this->normalizePayload($request->validated()));
$signupChannel->ensureEncryptionKeyPair();
$signupChannel->save();
return response()->json($this->toDetail($signupChannel, $competition));
}
public function destroy(Competition $competition, SignupChannel $signupChannel): Response
{
$this->assertChannelBelongs($competition, $signupChannel);
$signupChannel->delete();
return response()->noContent();
}
/**
* @return array<string, mixed>
*/
private function toSummary(SignupChannel $channel, Competition $competition): array
{
return [
'id' => $channel->id,
'competition_id' => $channel->competition_id,
'competition_name' => $competition->name,
'channel_code' => $channel->channel_code,
'channel_name' => $channel->channel_name,
'status' => $channel->status,
'encryption_algorithm' => $channel->encryption_algorithm ?: ChannelEntryEncryption::ALGORITHM,
'entry_encryption_enabled' => (bool) $channel->entry_encryption_enabled,
'success_callback_url' => $channel->success_callback_url,
'success_callback_type' => $channel->success_callback_type ?: SignupChannel::CALLBACK_TYPE_WEB,
'mini_program_callback_path' => $channel->mini_program_callback_path,
'mini_program_callback_method' => $channel->mini_program_callback_method
?: SignupChannel::MINI_PROGRAM_METHOD_REDIRECT_TO,
'remark' => $channel->remark,
'created_at' => $channel->created_at?->toIso8601String(),
'updated_at' => $channel->updated_at?->toIso8601String(),
];
}
/**
* @return array<string, mixed>
*/
private function toDetail(SignupChannel $channel, Competition $competition): array
{
$row = $this->toSummary($channel, $competition);
$row['shared_secret'] = $channel->shared_secret;
$row['encryption_public_key'] = $channel->encryption_public_key;
return $row;
}
private function assertChannelBelongs(Competition $competition, SignupChannel $channel): void
{
if ((int) $channel->competition_id !== (int) $competition->id) {
abort(404);
}
}
private function ensureEncryptionKeyPair(SignupChannel $channel): void
{
$channel->ensureEncryptionKeyPair();
if ($channel->isDirty()) {
$channel->save();
}
}
/**
* @param array<string, mixed> $payload
* @return array<string, mixed>
*/
private function normalizePayload(array $payload, bool $isCreate = false): array
{
if ($isCreate || array_key_exists('success_callback_url', $payload)) {
$payload['success_callback_url'] = trim((string) ($payload['success_callback_url'] ?? ''));
}
if ($isCreate || array_key_exists('mini_program_callback_path', $payload)) {
$payload['mini_program_callback_path'] = trim((string) ($payload['mini_program_callback_path'] ?? ''));
}
return $payload;
}
}