src/Controller/Api/Society/SocietyApiController.php line 526

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller\Api\Society;
  4. use App\Controller\Api\Society\Shared\Game\SharedNextGameEndpoint;
  5. use App\Controller\Api\Society\Auth\Service\FirebaseTokenInvalidException;
  6. use App\Controller\Api\Society\Auth\Service\LogoutSessionEndpoint;
  7. use App\Controller\Api\Society\Auth\Service\NextApiSessionException;
  8. use App\Controller\Api\Society\Auth\Service\RefreshTokenEndpoint;
  9. use App\Controller\Api\Society\Auth\Service\RegisterConfirmEndpoint;
  10. use App\Controller\Api\Society\Auth\Service\SearchPlayerByLicenseEndpoint;
  11. use App\Controller\Api\Society\Auth\Service\SessionStateEndpoint;
  12. use App\Controller\Api\Society\Auth\Service\SocietyPhoneChangeService;
  13. use App\Controller\Api\Society\Auth\Service\SocietyAuthV2Service;
  14. use App\Controller\Api\Society\Auth\Service\SocietyV2RegistrationEndpoint;
  15. use App\Controller\Api\Society\Auth\Service\UnregisterAccountEndpoint;
  16. use App\Controller\Api\Society\Card\Service\ECardEndpoint;
  17. use App\Controller\Api\Society\Card\Service\CardMarkedCandidatesEndpoint;
  18. use App\Controller\Api\Society\Card\Service\CreateCardMarkedAssignmentEndpoint;
  19. use App\Controller\Api\Society\Card\Service\LogResultEndpoint;
  20. use App\Controller\Api\Society\Card\Service\SaveCardResultsEndpoint;
  21. use App\Controller\Api\Society\Card\Service\SubmitCardEndpoint;
  22. use App\Controller\Api\Society\Classification\Service\ClassificationDetailEndpoint;
  23. use App\Controller\Api\Society\Classification\Service\ClassificationListEndpoint;
  24. use App\Controller\Api\Society\Classification\Service\NextcaddyClassificationDetailEndpoint;
  25. use App\Controller\Api\Society\Classification\Service\NextcaddyClassificationListEndpoint;
  26. use App\Controller\Api\Society\Classified\Service\ClassifiedResultsEndpoint;
  27. use App\Controller\Api\Society\Classified\Service\NextcaddyClassifiedResultsEndpoint;
  28. use App\Controller\Api\Society\Booking\Service\CancelBookingEndpoint;
  29. use App\Controller\Api\Society\Booking\Service\ConfirmBookingEndpoint;
  30. use App\Controller\Api\Society\Booking\Service\CreateBookingEndpoint;
  31. use App\Controller\Api\Society\Booking\Service\CreatePaymentSessionEndpoint;
  32. use App\Controller\Api\Society\Booking\Service\GetBookingEndpoint;
  33. use App\Controller\Api\Society\Booking\Service\ListBookingsEndpoint;
  34. use App\Controller\Api\Society\Booking\Service\PreviewBookingCancellationEndpoint;
  35. use App\Controller\Api\Society\Booking\Service\SearchBookableClubsEndpoint;
  36. use App\Controller\Api\Society\Booking\Service\SearchBookingAvailabilityEndpoint;
  37. use App\Controller\Api\Society\Booking\Service\SearchBookingsEndpoint;
  38. use App\Controller\Api\Society\Club\Service\ClubListEndpoint;
  39. use App\Controller\Api\Society\Competitions\Service\AvailableInscriptionsEndpoint;
  40. use App\Controller\Api\Society\Competitions\Service\CompetitionScorecardEndpoint;
  41. use App\Controller\Api\Society\Competitions\Service\CompetitionShowEndpoint;
  42. use App\Controller\Api\Society\Competitions\Service\CreateRfcCompetitionEndpoint;
  43. use App\Controller\Api\Society\Competitions\Service\SendRfcCardsEndpoint;
  44. use App\Controller\Api\Society\Competitions\Service\FutureCompetitionsEndpoint as NextcaddyFutureCompetitionsEndpoint;
  45. use App\Controller\Api\Society\Competitions\Service\PlayedCompetitionsEndpoint as NextcaddyPlayedCompetitionsEndpoint;
  46. use App\Controller\Api\Society\Contact\Service\CreateContactMessageEndpoint;
  47. use App\Controller\Api\Society\Course\Service\CoursesByClubEndpoint;
  48. use App\Controller\Api\Society\Course\Service\CourseTeesByCourseEndpoint;
  49. use App\Controller\Api\Society\Feed\Service\CreateFeedCommentEndpoint;
  50. use App\Controller\Api\Society\Feed\Service\CreateFeedPostEndpoint;
  51. use App\Controller\Api\Society\Feed\Service\DeleteFeedCommentEndpoint;
  52. use App\Controller\Api\Society\Feed\Service\DeleteFeedPostEndpoint;
  53. use App\Controller\Api\Society\Feed\Service\FeedCommentRepliesEndpoint;
  54. use App\Controller\Api\Society\Feed\Service\FeedCommentsListEndpoint;
  55. use App\Controller\Api\Society\Feed\Service\FeedListEndpoint;
  56. use App\Controller\Api\Society\Feed\Service\FeedPostDetailEndpoint;
  57. use App\Controller\Api\Society\Feed\Service\UpdateFeedCommentEndpoint;
  58. use App\Controller\Api\Society\Feed\Service\UpdateFeedPostEndpoint;
  59. use App\Controller\Api\Society\Feed\Service\UserFeedListEndpoint;
  60. use App\Controller\Api\Society\Follow\Service\AcceptFollowRequestEndpoint;
  61. use App\Controller\Api\Society\Follow\Service\BlockedUsersListEndpoint;
  62. use App\Controller\Api\Society\Follow\Service\BlockFollowUserEndpoint;
  63. use App\Controller\Api\Society\Follow\Service\CancelFollowRequestEndpoint;
  64. use App\Controller\Api\Society\Follow\Service\DiscoverFollowUsersEndpoint;
  65. use App\Controller\Api\Society\Follow\Service\FollowersListEndpoint;
  66. use App\Controller\Api\Society\Follow\Service\FollowingListEndpoint;
  67. use App\Controller\Api\Society\Follow\Service\FollowingPlayingTodayEndpoint;
  68. use App\Controller\Api\Society\Follow\Service\FollowUserEndpoint;
  69. use App\Controller\Api\Society\Follow\Service\FriendsListEndpoint;
  70. use App\Controller\Api\Society\Follow\Service\PendingReceivedFollowRequestsEndpoint;
  71. use App\Controller\Api\Society\Follow\Service\PendingSentFollowRequestsEndpoint;
  72. use App\Controller\Api\Society\Follow\Service\RejectFollowRequestEndpoint;
  73. use App\Controller\Api\Society\Follow\Service\RemoveFollowerEndpoint;
  74. use App\Controller\Api\Society\Follow\Service\UnblockFollowUserEndpoint;
  75. use App\Controller\Api\Society\Follow\Service\UnfollowUserEndpoint;
  76. use App\Controller\Api\Society\Shared\Exception\ApiEndpointException;
  77. use App\Controller\Api\Society\Shared\Logging\SocietyExceptionLogger;
  78. use App\Controller\Api\Society\Match\Service\MatchLivescoringEndpoint;
  79. use App\Controller\Api\Society\Friendly\Service\FriendlyAvailableFriendsEndpoint;
  80. use App\Controller\Api\Society\Friendly\Service\FriendlyByCodeEndpoint;
  81. use App\Controller\Api\Society\Friendly\Service\FriendlyClosestEndpoint;
  82. use App\Controller\Api\Society\Friendly\Service\FriendlyCreateEndpoint;
  83. use App\Controller\Api\Society\Friendly\Service\FriendlyDeleteEndpoint;
  84. use App\Controller\Api\Society\Friendly\Service\FriendlyDetailEndpoint;
  85. use App\Controller\Api\Society\Friendly\Service\FriendlyEditEndpoint;
  86. use App\Controller\Api\Society\Friendly\Service\FriendlyInscriptionEndpoint;
  87. use App\Controller\Api\Society\Friendly\Service\FriendlyListEndpoint;
  88. use App\Controller\Api\Society\Friendly\Service\FriendlyLivescoringEndpoint;
  89. use App\Controller\Api\Society\Friendly\Service\FriendlyParticipantHandicapsRefreshEndpoint;
  90. use App\Controller\Api\Society\Friendly\Service\FriendlySlotsAvailableEndpoint;
  91. use App\Controller\Api\Society\Match\Service\ReadMatchResults;
  92. use App\Controller\Api\Society\Notification\Service\DeleteAllNotificationsEndpoint;
  93. use App\Controller\Api\Society\Notification\Service\DeleteNotificationEndpoint;
  94. use App\Controller\Api\Society\Notification\Service\GetUnreadNotificationCountEndpoint;
  95. use App\Controller\Api\Society\Notification\Service\ListNotificationHistoryEndpoint;
  96. use App\Controller\Api\Society\Notification\Service\MarkAllNotificationsReadEndpoint;
  97. use App\Controller\Api\Society\Notification\Service\MarkNotificationReadByDispatchEndpoint;
  98. use App\Controller\Api\Society\Notification\Service\MarkNotificationReadEndpoint;
  99. use App\Controller\Api\Society\Notification\Service\RegisterNotificationDeviceEndpoint;
  100. use App\Controller\Api\Society\Notification\Service\UnregisterNotificationDeviceEndpoint;
  101. use App\Controller\Api\Society\Notification\Service\GetNotificationPreferencesEndpoint;
  102. use App\Controller\Api\Society\Notification\Service\UpdateNotificationPreferencesEndpoint;
  103. use App\Controller\Api\Society\General\Service\FormatsByModalityEndpoint;
  104. use App\Controller\Api\Society\Info\Service\SocietyAppInfoData;
  105. use App\Controller\Api\Society\InformationPanel\Service\InformationPanelEndpoint;
  106. use App\Controller\Api\Society\Participant\Service\DeleteParticipantEndpoint;
  107. use App\Controller\Api\Society\ProAm\Service\GetProAmConfigEndpoint;
  108. use App\Controller\Api\Society\ProAm\Service\ProAmProfessionalEndpoint;
  109. use App\Controller\Api\Society\ProAm\Service\UpdateProAmConfigEndpoint;
  110. use App\Controller\Api\Society\Profile\Service\PlayerCoursePlayingHandicapsEndpoint;
  111. use App\Controller\Api\Society\Profile\Service\RfegHandicapRoundsEndpoint;
  112. use App\Controller\Api\Society\Profile\Service\UserHandicapRefreshEndpoint;
  113. use App\Controller\Api\Society\Profile\Service\UserProfileDetailEndpoint;
  114. use App\Controller\Api\Society\Profile\Service\UserProfileInfoEndpoint;
  115. use App\Controller\Api\Society\Profile\Service\UserProfileUpdateEndpoint;
  116. use App\Controller\Api\Society\Profile\Service\SocietyV2ProfileLifecycleEndpoint;
  117. use App\Controller\Api\Society\Player\Service\PlayerLicenseCourseTeesEndpoint;
  118. use App\Controller\Api\Society\Ranking\Service\RankingByDataEndpoint;
  119. use App\Controller\Api\Society\Ranking\Service\PlayerVisibleRankingsEndpoint;
  120. use App\Controller\Api\Society\Ranking\Service\RankingClassifiedNxtDetailEndpoint;
  121. use App\Controller\Api\Society\Ranking\Service\RankingDetailEndpoint;
  122. use App\Controller\Api\Society\Ranking\Service\RankingLeaderboardEndpoint;
  123. use App\Controller\Api\Society\Ranking\Service\RankingNxtDetailEndpoint;
  124. use App\Controller\Api\Society\Ranking\Service\RankingUserDetailEndpoint;
  125. use App\Controller\Api\Society\Ranking\Service\RankingsSharedEndpoint;
  126. use App\Controller\Api\Society\Ranking\Service\UserRankingsEndpoint;
  127. use App\Controller\Api\Society\Round\Service\FinalizeRoundEndpoint;
  128. use App\Controller\Api\Society\Schedule\Service\AddScheduleGroupPlayerEndpoint;
  129. use App\Controller\Api\Society\Schedule\Service\CreateScheduleEndpoint;
  130. use App\Controller\Api\Society\Schedule\Service\CreateScheduleGroupEndpoint;
  131. use App\Controller\Api\Society\Schedule\Service\CreateScheduleLayoutEndpoint;
  132. use App\Controller\Api\Society\Schedule\Service\DeleteScheduleEndpoint;
  133. use App\Controller\Api\Society\Schedule\Service\DeleteScheduleGroupEndpoint;
  134. use App\Controller\Api\Society\Schedule\Service\DeleteScheduleGroupPlayerEndpoint;
  135. use App\Controller\Api\Society\Schedule\Service\ListSchedulesEndpoint;
  136. use App\Controller\Api\Society\Schedule\Service\MoveScheduleGroupPlayerEndpoint;
  137. use App\Controller\Api\Society\Schedule\Service\PublishScheduleEndpoint;
  138. use App\Controller\Api\Society\Schedule\Service\SaveScheduleLayoutEndpoint;
  139. use App\Controller\Api\Society\Schedule\Service\ScheduleDetailEndpoint;
  140. use App\Controller\Api\Society\Schedule\Service\ScheduleShowEndpoint;
  141. use App\Controller\Api\Society\Schedule\Service\UnpublishScheduleEndpoint;
  142. use App\Controller\Api\Society\Schedule\Service\UpdateScheduleGroupEndpoint;
  143. use App\Controller\Api\Society\Shared\Response\SocietyErrorMessageTranslator;
  144. use App\Controller\Api\Society\Shared\Service\FutureCompetitionsEndpoint;
  145. use App\Controller\Api\Society\Shared\Service\OpenInscriptionCompetitionsEndpoint;
  146. use App\Controller\Api\Society\Shared\Service\PlayedCompetitionsEndpoint;
  147. use App\Controller\Api\Society\Shared\Service\SearchCompetitionsEndpoint;
  148. use App\Controller\Api\Society\Shared\Service\UserCompetitionsEndpoint;
  149. use App\Controller\Api\Society\Statistics\Service\CompetitionsByClubStatsEndpoint;
  150. use App\Controller\Api\Society\Statistics\Service\HcpEvolutionEndpoint;
  151. use App\Controller\Api\Society\Statistics\Service\PlayedResultsStatsEndpoint;
  152. use App\Controller\Api\Society\Statistics\Service\StatisticsEndpoint;
  153. use App\Controller\Api\Society\User\Service\DeleteSocietyUserEndpoint;
  154. use App\Repository\Society\UserRepository as SocietyUserRepository;
  155. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  156. use Symfony\Component\HttpFoundation\JsonResponse;
  157. use Symfony\Component\HttpFoundation\Request;
  158. use Symfony\Component\HttpFoundation\Response;
  159. use Symfony\Component\Routing\Annotation\Route;
  160. /**
  161. * @Route("/next-api/society")
  162. */
  163. final class SocietyApiController extends AbstractController
  164. {
  165. public function __construct(
  166. private readonly SocietyErrorMessageTranslator $societyErrorMessageTranslator,
  167. private readonly SocietyExceptionLogger $societyExceptionLogger
  168. )
  169. {
  170. }
  171. /**
  172. * @Route("/me", name="next_api_society_me", methods={"GET"})
  173. */
  174. public function me(Request $request): JsonResponse
  175. {
  176. try {
  177. $response = [
  178. 'userId' => (int)$request->attributes->get('resolvedUserId', 0),
  179. 'playerId' => (int)$request->attributes->get('resolvedPlayerId', 0),
  180. 'societyUserId' => (int)$request->attributes->get('resolvedSocietyUserId', 0),
  181. 'societyNxtUserId' => (int)$request->attributes->get('resolvedSocietyNxtUserId', 0),
  182. 'player' => $request->attributes->get('resolvedPlayer'),
  183. ];
  184. } catch (\Throwable $exception) {
  185. return $this->endpointExceptionResponse($exception);
  186. }
  187. return $this->endpointResponse($response, Response::HTTP_OK);
  188. }
  189. /**
  190. * @Route("/me", name="next_api_society_me_delete", methods={"DELETE"})
  191. */
  192. public function deleteMe(Request $request, DeleteSocietyUserEndpoint $deleteSocietyUserEndpoint): JsonResponse
  193. {
  194. try {
  195. $response = $deleteSocietyUserEndpoint->__invoke(
  196. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  197. (string)$request->attributes->get('firebaseUserId', ''),
  198. (string)$request->attributes->get('phoneFromToken', '')
  199. );
  200. } catch (\Throwable $exception) {
  201. return $this->endpointExceptionResponse($exception);
  202. }
  203. return $this->endpointResponse($response, Response::HTTP_OK);
  204. }
  205. /**
  206. * @Route("/info", name="next_api_society_app_info", methods={"GET"})
  207. */
  208. public function appInfo(SocietyAppInfoData $societyAppInfoData): Response
  209. {
  210. try {
  211. $viewData = $societyAppInfoData->__invoke();
  212. } catch (\RuntimeException $exception) {
  213. return new Response($exception->getMessage(), Response::HTTP_NOT_FOUND);
  214. }
  215. return $this->render('api/nextcaddy_app/info.html.twig', $viewData);
  216. }
  217. /**
  218. * @Route("/auth/token/generate", name="next_api_society_auth_token_generate", methods={"GET"})
  219. */
  220. public function generateToken(): JsonResponse
  221. {
  222. return new JsonResponse([
  223. 'error' => 'auth-v2-required',
  224. 'message' => 'Update the app to use Play authentication v2.',
  225. ], Response::HTTP_GONE);
  226. }
  227. /**
  228. * @Route("/auth/token/refresh", name="next_api_society_auth_token_refresh", methods={"POST"})
  229. */
  230. public function refreshToken(Request $request, RefreshTokenEndpoint $refreshTokenEndpoint): JsonResponse
  231. {
  232. $payload = $this->parseJsonPayload($request);
  233. if (null === $payload) {
  234. return $this->invalidJsonResponse();
  235. }
  236. return $this->runSocietyJsonEndpoint(fn(): array => $refreshTokenEndpoint->__invoke($payload));
  237. }
  238. /**
  239. * @Route("/auth/session/state", name="next_api_society_auth_session_state", methods={"GET"})
  240. */
  241. public function sessionState(Request $request, SessionStateEndpoint $sessionStateEndpoint): JsonResponse
  242. {
  243. return $this->runSocietyJsonEndpoint(fn(): array => $sessionStateEndpoint->__invoke(
  244. (string) $request->attributes->get('firebaseUserId', ''),
  245. (string) $request->attributes->get('phoneFromToken', '')
  246. ));
  247. }
  248. /** @Route("/auth/v2/accounts", name="next_api_society_auth_v2_accounts", methods={"GET"}) */
  249. public function societyAuthV2Accounts(Request $request, SocietyAuthV2Service $service): JsonResponse|Response
  250. {
  251. $claims = (array) $request->attributes->get('firebaseTokenClaims', []);
  252. return $this->runSocietyJsonEndpoint(fn(): array => $service->accounts(
  253. (string) ($claims['aud'] ?? ''),
  254. (string) $request->attributes->get('firebaseUserId', ''),
  255. (string) $request->attributes->get('phoneFromToken', '')
  256. ));
  257. }
  258. /** @Route("/auth/v2/sessions", name="next_api_society_auth_v2_session_create", methods={"POST"}) */
  259. public function createSocietyAuthV2Session(Request $request, SocietyAuthV2Service $service): JsonResponse|Response
  260. {
  261. $payload = $this->parseJsonPayload($request);
  262. if (null === $payload) {
  263. return $this->invalidJsonResponse();
  264. }
  265. $nxtUserId = filter_var($payload['nxtUserId'] ?? null, FILTER_VALIDATE_INT);
  266. $playerId = filter_var($payload['playerId'] ?? null, FILTER_VALIDATE_INT);
  267. if (false === $nxtUserId || false === $playerId || $nxtUserId <= 0 || $playerId <= 0) {
  268. return $this->societyErrorResponse('invalid-request', Response::HTTP_BAD_REQUEST, 'The "nxtUserId" and "playerId" fields are required.');
  269. }
  270. $claims = (array) $request->attributes->get('firebaseTokenClaims', []);
  271. return $this->runSocietyJsonEndpoint(fn(): array => $service->createSession(
  272. (string) ($claims['aud'] ?? ''),
  273. (string) $request->attributes->get('firebaseUserId', ''),
  274. (string) $request->attributes->get('phoneFromToken', ''),
  275. (int) $nxtUserId,
  276. (int) $playerId
  277. ));
  278. }
  279. /** @Route("/auth/v2/sessions/current", name="next_api_society_auth_v2_session_current", methods={"GET"}) */
  280. public function currentSocietyAuthV2Session(Request $request, SocietyAuthV2Service $service): JsonResponse|Response
  281. {
  282. $token = (string) $request->attributes->get('societyV2Token', '');
  283. return $this->runSocietyJsonEndpoint(fn(): array => $service->current($token));
  284. }
  285. /** @Route("/auth/v2/sessions/refresh", name="next_api_society_auth_v2_session_refresh", methods={"POST"}) */
  286. public function refreshSocietyAuthV2Session(Request $request, SocietyAuthV2Service $service): JsonResponse|Response
  287. {
  288. $payload = $this->parseJsonPayload($request);
  289. if (null === $payload) {
  290. return $this->invalidJsonResponse();
  291. }
  292. return $this->runSocietyJsonEndpoint(fn(): array => $service->refresh((string) ($payload['refreshToken'] ?? '')));
  293. }
  294. /** @Route("/auth/v2/sessions/logout", name="next_api_society_auth_v2_session_logout", methods={"POST"}) */
  295. public function logoutSocietyAuthV2Session(Request $request, SocietyAuthV2Service $service): JsonResponse|Response
  296. {
  297. $token = (string) $request->attributes->get('societyV2Token', '');
  298. return $this->runSocietyJsonEndpoint(fn(): array => $service->logout($token));
  299. }
  300. /** @Route("/auth/v2/registration/verify", name="next_api_society_auth_v2_registration_verify", methods={"POST"}) */
  301. public function verifySocietyAuthV2Registration(Request $request, SocietyV2RegistrationEndpoint $endpoint): JsonResponse|Response
  302. {
  303. $payload = $this->parseJsonPayload($request);
  304. if (null === $payload) {
  305. return $this->invalidJsonResponse();
  306. }
  307. $claims = (array) $request->attributes->get('firebaseTokenClaims', []);
  308. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->verify(
  309. (string) ($claims['aud'] ?? ''),
  310. (string) $request->attributes->get('firebaseUserId', ''),
  311. (string) $request->attributes->get('phoneFromToken', ''),
  312. $payload
  313. ));
  314. }
  315. /** @Route("/auth/v2/registration/confirm", name="next_api_society_auth_v2_registration_confirm", methods={"POST"}) */
  316. public function confirmSocietyAuthV2Registration(Request $request, SocietyV2RegistrationEndpoint $endpoint): JsonResponse|Response
  317. {
  318. $payload = $this->parseJsonPayload($request);
  319. if (null === $payload) {
  320. return $this->invalidJsonResponse();
  321. }
  322. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->confirm($payload));
  323. }
  324. /** @Route("/auth/v2/phone-changes", name="next_api_society_phone_change", methods={"POST"}) */
  325. public function beginSocietyPhoneChange(Request $request, SocietyPhoneChangeService $service): JsonResponse|Response
  326. {
  327. $payload = $this->parseJsonPayload($request);
  328. if (null === $payload) {
  329. return $this->invalidJsonResponse();
  330. }
  331. return $this->runSocietyJsonEndpoint(fn(): array => $service->begin(
  332. (array) $request->attributes->get('societyV2Context', []),
  333. (string) ($payload['phone'] ?? ''),
  334. (string) ($payload['phoneCountry'] ?? 'es')
  335. ));
  336. }
  337. /** @Route("/auth/v2/phone-changes/confirm", name="next_api_society_phone_change_confirm", methods={"POST"}) */
  338. public function confirmSocietyPhoneChange(Request $request, SocietyPhoneChangeService $service): JsonResponse|Response
  339. {
  340. $payload = $this->parseJsonPayload($request);
  341. if (null === $payload) {
  342. return $this->invalidJsonResponse();
  343. }
  344. return $this->runSocietyJsonEndpoint(fn(): array => $service->confirm(
  345. (string) ($payload['changeToken'] ?? ''),
  346. (string) ($payload['firebaseToken'] ?? '')
  347. ));
  348. }
  349. /** @Route("/auth/v2/profile/contact", name="next_api_society_auth_v2_profile_contact", methods={"PATCH"}) */
  350. public function updateSocietyAuthV2ProfileContact(Request $request, SocietyV2ProfileLifecycleEndpoint $endpoint): JsonResponse|Response
  351. {
  352. $payload = $this->parseJsonPayload($request);
  353. if (null === $payload) {
  354. return $this->invalidJsonResponse();
  355. }
  356. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->updateContact(
  357. (int) $request->attributes->get('resolvedUserId', 0),
  358. (int) $request->attributes->get('resolvedPlayerId', 0),
  359. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  360. $payload
  361. ));
  362. }
  363. /** @Route("/auth/v2/profile", name="next_api_society_auth_v2_profile_delete", methods={"DELETE"}) */
  364. public function unlinkSocietyAuthV2Profile(Request $request, SocietyV2ProfileLifecycleEndpoint $endpoint): JsonResponse|Response
  365. {
  366. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->unlink(
  367. (int) $request->attributes->get('resolvedUserId', 0),
  368. (int) $request->attributes->get('resolvedPlayerId', 0),
  369. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  370. ));
  371. }
  372. /**
  373. * @Route("/auth/session/search-license", name="next_api_society_auth_session_search_license", methods={"POST"})
  374. */
  375. public function searchPlayerByLicense(Request $request, SearchPlayerByLicenseEndpoint $searchPlayerByLicenseEndpoint): JsonResponse
  376. {
  377. $payload = $this->parseJsonPayload($request);
  378. if (null === $payload) {
  379. return $this->invalidJsonResponse();
  380. }
  381. return $this->runSocietyJsonEndpoint(fn(): array => $searchPlayerByLicenseEndpoint->__invoke($payload));
  382. }
  383. /**
  384. * @Route("/auth/session/register-confirm", name="next_api_society_auth_session_register_confirm", methods={"POST"})
  385. */
  386. public function registerConfirm(Request $request, RegisterConfirmEndpoint $registerConfirmEndpoint): JsonResponse
  387. {
  388. $payload = $this->parseJsonPayload($request);
  389. if (null === $payload) {
  390. return $this->invalidJsonResponse();
  391. }
  392. return $this->runSocietyJsonEndpoint(fn(): array => $registerConfirmEndpoint->__invoke(
  393. $payload,
  394. (string) $request->attributes->get('firebaseUserId', ''),
  395. (string) $request->attributes->get('phoneFromToken', '')
  396. ));
  397. }
  398. /**
  399. * @Route("/auth/session/logout", name="next_api_society_auth_session_logout", methods={"POST"})
  400. */
  401. public function logoutSession(Request $request, LogoutSessionEndpoint $logoutSessionEndpoint): JsonResponse
  402. {
  403. return $this->runSocietyJsonEndpoint(fn(): array => $logoutSessionEndpoint->__invoke(
  404. (string) $request->attributes->get('firebaseUserId', ''),
  405. (string) $request->attributes->get('phoneFromToken', '')
  406. ));
  407. }
  408. /**
  409. * @Route("/auth/session/unregister", name="next_api_society_auth_session_unregister", methods={"POST"})
  410. */
  411. public function unregisterAccount(Request $request, UnregisterAccountEndpoint $unregisterAccountEndpoint): JsonResponse
  412. {
  413. return $this->runSocietyJsonEndpoint(fn(): array => $unregisterAccountEndpoint->__invoke(
  414. (string) $request->attributes->get('firebaseUserId', ''),
  415. (string) $request->attributes->get('phoneFromToken', ''),
  416. (int) $request->attributes->get('resolvedUserId', 0),
  417. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  418. ));
  419. }
  420. /**
  421. * @Route("/notifications/devices/register", name="next_api_society_notification_device_register", methods={"POST"})
  422. */
  423. public function registerNotificationDevice(Request $request, RegisterNotificationDeviceEndpoint $endpoint): JsonResponse|Response
  424. {
  425. $payload = $this->parseJsonPayload($request);
  426. if (null === $payload) {
  427. return $this->invalidJsonResponse();
  428. }
  429. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  430. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  431. $payload
  432. ));
  433. }
  434. /**
  435. * @Route("/notifications/devices/unregister", name="next_api_society_notification_device_unregister", methods={"POST"})
  436. */
  437. public function unregisterNotificationDevice(Request $request, UnregisterNotificationDeviceEndpoint $endpoint): JsonResponse|Response
  438. {
  439. $payload = $this->parseJsonPayload($request);
  440. if (null === $payload) {
  441. return $this->invalidJsonResponse();
  442. }
  443. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  444. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  445. $payload
  446. ));
  447. }
  448. /**
  449. * @Route("/notifications/preferences", name="next_api_society_notification_preferences_get", methods={"GET"})
  450. */
  451. public function getNotificationPreferences(Request $request, GetNotificationPreferencesEndpoint $endpoint): JsonResponse|Response
  452. {
  453. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  454. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  455. ));
  456. }
  457. /**
  458. * @Route("/notifications/preferences", name="next_api_society_notification_preferences_update", methods={"PUT"})
  459. */
  460. public function updateNotificationPreferences(Request $request, UpdateNotificationPreferencesEndpoint $endpoint): JsonResponse|Response
  461. {
  462. $payload = $this->parseJsonPayload($request);
  463. if (null === $payload) {
  464. return $this->invalidJsonResponse();
  465. }
  466. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  467. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  468. $payload
  469. ));
  470. }
  471. /**
  472. * @Route("/notifications", name="next_api_society_notification_history", methods={"GET"})
  473. */
  474. public function notificationHistory(Request $request, ListNotificationHistoryEndpoint $endpoint): JsonResponse|Response
  475. {
  476. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  477. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  478. (int) $request->query->get('page', 1),
  479. (int) $request->query->get('pageSize', 20)
  480. ));
  481. }
  482. /**
  483. * @Route("/notifications", name="next_api_society_notification_delete_all", methods={"DELETE"})
  484. */
  485. public function deleteAllNotifications(Request $request, DeleteAllNotificationsEndpoint $endpoint): JsonResponse|Response
  486. {
  487. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  488. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  489. ));
  490. }
  491. /**
  492. * @Route("/notifications/{notificationId}", name="next_api_society_notification_delete", methods={"DELETE"}, requirements={"notificationId"="\d+"})
  493. */
  494. public function deleteNotification(
  495. int $notificationId,
  496. Request $request,
  497. DeleteNotificationEndpoint $endpoint
  498. ): JsonResponse|Response {
  499. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  500. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  501. $notificationId
  502. ));
  503. }
  504. /**
  505. * @Route("/notifications/unread-count", name="next_api_society_notification_unread_count", methods={"GET"})
  506. */
  507. public function unreadNotificationCount(Request $request, GetUnreadNotificationCountEndpoint $endpoint): JsonResponse|Response
  508. {
  509. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  510. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  511. ));
  512. }
  513. /**
  514. * @Route("/notifications/read-all", name="next_api_society_notification_read_all", methods={"PUT"})
  515. */
  516. public function markAllNotificationsRead(Request $request, MarkAllNotificationsReadEndpoint $endpoint): JsonResponse|Response
  517. {
  518. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  519. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  520. ));
  521. }
  522. /**
  523. * @Route("/notifications/dispatch/{dispatchId}/read", name="next_api_society_notification_dispatch_read", methods={"PUT"}, requirements={"dispatchId"="\d+"})
  524. */
  525. public function markNotificationReadByDispatch(
  526. int $dispatchId,
  527. Request $request,
  528. MarkNotificationReadByDispatchEndpoint $endpoint
  529. ): JsonResponse|Response {
  530. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  531. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  532. $dispatchId
  533. ));
  534. }
  535. /**
  536. * @Route("/notifications/{notificationId}/read", name="next_api_society_notification_read", methods={"PUT"}, requirements={"notificationId"="\d+"})
  537. */
  538. public function markNotificationRead(
  539. int $notificationId,
  540. Request $request,
  541. MarkNotificationReadEndpoint $endpoint
  542. ): JsonResponse|Response {
  543. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  544. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  545. $notificationId
  546. ));
  547. }
  548. /**
  549. * @Route("/profile/info", name="next_api_society_profile_info", methods={"POST"})
  550. */
  551. public function profileInfo(Request $request, UserProfileInfoEndpoint $userProfileInfoEndpoint): JsonResponse
  552. {
  553. $payload = $this->parseJsonPayload($request);
  554. if (null === $payload) {
  555. return $this->invalidJsonResponse();
  556. }
  557. if ('society-v2' === (string) $request->attributes->get('authMode', '')) {
  558. return $this->runSocietyJsonEndpoint(fn(): array => $userProfileInfoEndpoint->forSocietyV2(
  559. (int) $request->attributes->get('resolvedUserId', 0),
  560. (int) $request->attributes->get('resolvedPlayerId', 0),
  561. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  562. (string) ($payload['locale'] ?? 'es')
  563. ));
  564. }
  565. $payload = $this->injectResolvedUserId($request, $payload);
  566. return $this->runSocietyJsonEndpoint(fn(): array => $userProfileInfoEndpoint->__invoke($payload));
  567. }
  568. /**
  569. * @Route("/profile/handicap/refresh", name="next_api_society_profile_handicap_refresh", methods={"POST"})
  570. */
  571. public function profileHandicapRefresh(Request $request, UserHandicapRefreshEndpoint $endpoint): JsonResponse
  572. {
  573. return $this->runSocietyJsonEndpoint(fn(): array => $endpoint->__invoke(
  574. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  575. ));
  576. }
  577. /**
  578. * @Route("/profile/detail/{id}", name="next_api_society_profile_detail", methods={"GET"}, requirements={"id"="\d+"})
  579. */
  580. public function profileDetail(int $id, Request $request, UserProfileDetailEndpoint $userProfileDetailEndpoint): JsonResponse
  581. {
  582. return $this->runSocietyJsonEndpoint(fn(): array => $userProfileDetailEndpoint->__invoke(
  583. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  584. $id
  585. ));
  586. }
  587. /**
  588. * @Route("/profile/playing-handicaps", name="next_api_society_profile_playing_handicaps", methods={"POST"})
  589. */
  590. public function profilePlayingHandicaps(Request $request, PlayerCoursePlayingHandicapsEndpoint $playerCoursePlayingHandicapsEndpoint): JsonResponse
  591. {
  592. $payload = $this->parseJsonPayload($request);
  593. if (null === $payload) {
  594. return $this->invalidJsonResponse();
  595. }
  596. $payload = $this->injectResolvedUserId($request, $payload);
  597. $isSocietyV2 = 'society-v2' === (string) $request->attributes->get('authMode', '');
  598. $selectedPlayerId = $isSocietyV2 ? (int) $request->attributes->get('resolvedPlayerId', 0) : null;
  599. $selectedSocietyUserId = $isSocietyV2 ? (int) $request->attributes->get('resolvedSocietyUserId', 0) : null;
  600. return $this->runSocietyJsonEndpoint(fn(): array => $playerCoursePlayingHandicapsEndpoint->__invoke($payload, $selectedPlayerId, $selectedSocietyUserId));
  601. }
  602. /**
  603. * @Route("/profile/rfeg-handicap-rounds", name="next_api_society_profile_rfeg_handicap_rounds", methods={"POST"})
  604. */
  605. public function profileRfegHandicapRounds(Request $request, RfegHandicapRoundsEndpoint $rfegHandicapRoundsEndpoint): JsonResponse
  606. {
  607. $payload = $this->parseJsonPayload($request);
  608. if (null === $payload) {
  609. return $this->invalidJsonResponse();
  610. }
  611. $payload = $this->injectResolvedUserId($request, $payload);
  612. $isSocietyV2 = 'society-v2' === (string) $request->attributes->get('authMode', '');
  613. $selectedPlayerId = $isSocietyV2 ? (int) $request->attributes->get('resolvedPlayerId', 0) : null;
  614. $selectedSocietyUserId = $isSocietyV2 ? (int) $request->attributes->get('resolvedSocietyUserId', 0) : null;
  615. return $this->runSocietyJsonEndpoint(function () use ($rfegHandicapRoundsEndpoint, $payload, $selectedPlayerId, $selectedSocietyUserId): array {
  616. $response = $rfegHandicapRoundsEndpoint->__invoke($payload, $selectedPlayerId, $selectedSocietyUserId);
  617. return [
  618. '_statusCode' => (int) $response['statusCode'],
  619. 'data' => $response['data'],
  620. ];
  621. }, Response::HTTP_OK);
  622. }
  623. /**
  624. * @Route("/profile/update", name="next_api_society_profile_update", methods={"POST"})
  625. */
  626. public function profileUpdate(Request $request, UserProfileUpdateEndpoint $userProfileUpdateEndpoint): JsonResponse
  627. {
  628. $payload = $this->parseJsonPayload($request);
  629. if (null === $payload) {
  630. return $this->invalidJsonResponse();
  631. }
  632. $isSocietyV2 = 'society-v2' === (string) $request->attributes->get('authMode', '');
  633. if (!$isSocietyV2) {
  634. $payload = $this->injectResolvedUserId($request, $payload);
  635. $payload['firebaseUserId'] = (string) $request->attributes->get('firebaseUserId', '');
  636. $payload['phoneFromToken'] = (string) $request->attributes->get('phoneFromToken', '');
  637. }
  638. return $this->runSocietyJsonEndpoint(function () use ($userProfileUpdateEndpoint, $payload, $request, $isSocietyV2): array {
  639. $response = $isSocietyV2
  640. ? $userProfileUpdateEndpoint->updateForSocietyV2(
  641. (int) $request->attributes->get('resolvedUserId', 0),
  642. (int) $request->attributes->get('resolvedPlayerId', 0),
  643. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  644. $payload
  645. )
  646. : $userProfileUpdateEndpoint->__invoke($payload);
  647. return [
  648. '_statusCode' => (int) $response['statusCode'],
  649. 'success' => $response['success'],
  650. 'hasChanges' => $response['hasChanges'],
  651. 'errors' => $response['errors'],
  652. 'data' => $response['data'],
  653. ];
  654. });
  655. }
  656. /**
  657. * @Route("/general/formats-by-modality", name="next_api_society_general_formats_by_modality", methods={"GET"})
  658. */
  659. public function formatsByModality(Request $request, FormatsByModalityEndpoint $formatsByModalityEndpoint): JsonResponse
  660. {
  661. try {
  662. $response = $formatsByModalityEndpoint->__invoke((int)$request->query->get('modality', 0));
  663. } catch (\Throwable $exception) {
  664. return $this->endpointExceptionResponse($exception);
  665. }
  666. return $this->endpointResponse($response, Response::HTTP_OK);
  667. }
  668. /**
  669. * @Route("/classification/{id}", name="next_api_society_classification_detail", methods={"GET"}, requirements={"id"="\d+"})
  670. */
  671. public function classificationDetail(int $id, Request $request, ClassificationDetailEndpoint $classificationDetailEndpoint): JsonResponse
  672. {
  673. try {
  674. $response = $classificationDetailEndpoint->__invoke(
  675. $id,
  676. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  677. );
  678. } catch (\Throwable $exception) {
  679. return $this->endpointExceptionResponse($exception);
  680. }
  681. return $this->endpointResponse($response, Response::HTTP_OK);
  682. }
  683. /**
  684. * @Route("/classification/{classificationId}/classified/{classifiedId}/results", name="next_api_society_classification_classified_results", methods={"GET"}, requirements={"classificationId"="\d+", "classifiedId"="\d+"})
  685. */
  686. public function classifiedsResults(int $classificationId, int $classifiedId, ClassifiedResultsEndpoint $classifiedResultEndpoint): JsonResponse
  687. {
  688. try {
  689. $response = $classifiedResultEndpoint->__invoke($classificationId, $classifiedId);
  690. } catch (\Throwable $exception) {
  691. return $this->endpointExceptionResponse($exception);
  692. }
  693. return $this->endpointResponse($response, Response::HTTP_OK);
  694. }
  695. /**
  696. * @Route("/nextcaddy/classification/{id}", name="next_api_society_nextcaddy_classification_show", methods={"GET"})
  697. */
  698. public function nextcaddyClassificationShow($id, NextcaddyClassificationDetailEndpoint $classificationShowEndpoint): JsonResponse
  699. {
  700. return $this->runSocietyJsonEndpoint(fn(): array => $classificationShowEndpoint->__invoke($id));
  701. }
  702. /**
  703. * @Route("/nextcaddy/classification/{classificationId}/classified/{classifiedId}/results", name="next_api_society_nextcaddy_classification_classified_results", methods={"GET"}, requirements={"classificationId"="\d+", "classifiedId"="\d+"})
  704. */
  705. public function nextcaddyClassifiedResults($classificationId, $classifiedId, NextcaddyClassifiedResultsEndpoint $classifiedResultsEndpoint): JsonResponse
  706. {
  707. return $this->runSocietyJsonEndpoint(fn(): array => $classifiedResultsEndpoint->__invoke($classificationId, $classifiedId)['data']);
  708. }
  709. /**
  710. * @Route("/matches/{source}/{matchId}/results", name="next_api_society_match_results", methods={"GET"}, requirements={"source"="competition|friendly", "matchId"="\d+"})
  711. */
  712. public function matchResults(
  713. string $source,
  714. int $matchId,
  715. Request $request,
  716. ReadMatchResults $matchResultsEndpoint
  717. ): JsonResponse
  718. {
  719. $response = $this->runSocietyJsonEndpoint(fn(): array => $matchResultsEndpoint->__invoke(
  720. $source,
  721. $matchId,
  722. (int) $request->attributes->get('resolvedUserId', 0),
  723. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  724. $request->query->all(),
  725. 'society-v2' === $request->attributes->get('authMode')
  726. ));
  727. $response->headers->set('Cache-Control', 'private, no-store, max-age=0');
  728. return $response;
  729. }
  730. /**
  731. * @Route("/matches/{source}/{matchId}/livescoring", name="next_api_society_match_livescoring", methods={"GET"}, requirements={"source"="competition|friendly", "matchId"="\d+"})
  732. */
  733. public function matchLivescoring(
  734. string $source,
  735. string $matchId,
  736. Request $request,
  737. MatchLivescoringEndpoint $endpoint
  738. ): JsonResponse|Response {
  739. $query = $request->query->all();
  740. $response = $this->runSocietyJsonEndpoint(fn(): array => $endpoint(
  741. $source,
  742. $matchId,
  743. (int) $request->attributes->get('resolvedUserId', 0),
  744. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  745. $query['roundId'] ?? null,
  746. 'society-v2' === $request->attributes->get('authMode')
  747. ));
  748. $response->headers->set('Cache-Control', 'private, no-store, max-age=0');
  749. return $response;
  750. }
  751. /**
  752. * @Route("/card/ecard/participant/{participant}/round/{round}", name="next_api_society_card_ecard", methods={"GET", "POST"}, requirements={"participant"="\d+", "round"="\d+"})
  753. */
  754. public function eCard(int $participant, int $round, Request $request, ECardEndpoint $eCardEndpoint): JsonResponse|Response
  755. {
  756. try {
  757. $response = $eCardEndpoint->__invoke(
  758. $participant,
  759. $round,
  760. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  761. $request
  762. );
  763. } catch (\Throwable $exception) {
  764. return $this->endpointExceptionResponse($exception);
  765. }
  766. return $this->endpointResponse($response, Response::HTTP_OK);
  767. }
  768. /**
  769. * @Route("/round/{roundId}/pro-am/config", name="next_api_society_pro_am_config_get", methods={"GET"}, requirements={"roundId"="\d+"})
  770. */
  771. public function proAmConfig(int $roundId, Request $request, GetProAmConfigEndpoint $getProAmConfigEndpoint): JsonResponse
  772. {
  773. try {
  774. $response = $getProAmConfigEndpoint->__invoke($roundId, (int) $request->attributes->get('resolvedSocietyUserId', 0));
  775. } catch (\Throwable $exception) {
  776. return $this->endpointExceptionResponse($exception);
  777. }
  778. return $this->endpointResponse($response, Response::HTTP_OK);
  779. }
  780. /**
  781. * @Route("/round/{roundId}/pro-am/config", name="next_api_society_pro_am_config_update", methods={"PUT"}, requirements={"roundId"="\d+"})
  782. */
  783. public function updateProAmConfig(int $roundId, Request $request, UpdateProAmConfigEndpoint $updateProAmConfigEndpoint): JsonResponse
  784. {
  785. $payload = $this->parseJsonPayload($request);
  786. if (null === $payload) {
  787. return $this->invalidJsonResponse();
  788. }
  789. try {
  790. $response = $updateProAmConfigEndpoint->__invoke($roundId, (int) $request->attributes->get('resolvedSocietyUserId', 0), $payload);
  791. } catch (\Throwable $exception) {
  792. return $this->endpointExceptionResponse($exception);
  793. }
  794. return $this->endpointResponse($response, Response::HTTP_OK);
  795. }
  796. /**
  797. * @Route("/round/{roundId}/team/{teamId}/professional", name="next_api_society_pro_am_professional_update", methods={"PUT"}, requirements={"roundId"="\d+", "teamId"="\d+"})
  798. */
  799. public function updateProAmProfessional(int $roundId, int $teamId, Request $request, ProAmProfessionalEndpoint $proAmProfessionalEndpoint): JsonResponse
  800. {
  801. $payload = $this->parseJsonPayload($request);
  802. if (null === $payload) {
  803. return $this->invalidJsonResponse();
  804. }
  805. try {
  806. $response = $proAmProfessionalEndpoint->__invoke($roundId, $teamId, (int) $request->attributes->get('resolvedSocietyUserId', 0), $payload);
  807. } catch (\Throwable $exception) {
  808. return $this->endpointExceptionResponse($exception);
  809. }
  810. return $this->endpointResponse($response, Response::HTTP_OK);
  811. }
  812. /**
  813. * @Route("/card/marked-candidates/participant/{participant}/round/{round}", name="next_api_society_card_marked_candidates", methods={"GET"}, requirements={"participant"="\d+", "round"="\d+"})
  814. */
  815. public function cardMarkedCandidates(int $participant, int $round, Request $request, CardMarkedCandidatesEndpoint $cardMarkedCandidatesEndpoint): JsonResponse
  816. {
  817. try {
  818. $response = $cardMarkedCandidatesEndpoint->__invoke($participant, $round, (int) $request->attributes->get('resolvedSocietyUserId', 0));
  819. } catch (\Throwable $exception) {
  820. return $this->endpointExceptionResponse($exception);
  821. }
  822. return $this->endpointResponse($response, Response::HTTP_OK);
  823. }
  824. /**
  825. * @Route("/card/marked-assignment", name="next_api_society_card_marked_assignment", methods={"POST"})
  826. */
  827. public function cardMarkedAssignment(Request $request, CreateCardMarkedAssignmentEndpoint $createCardMarkedAssignmentEndpoint): JsonResponse
  828. {
  829. try {
  830. $response = $createCardMarkedAssignmentEndpoint->__invoke($request, (int) $request->attributes->get('resolvedSocietyUserId', 0));
  831. } catch (\Throwable $exception) {
  832. return $this->endpointExceptionResponse($exception);
  833. }
  834. return $this->endpointResponse($response, Response::HTTP_OK);
  835. }
  836. /**
  837. * @Route("/card/save-card-results", name="next_api_society_save_card_results", methods={"POST"})
  838. */
  839. public function saveCardResults(Request $request, SaveCardResultsEndpoint $saveCardResultsEndpoint): JsonResponse
  840. {
  841. try {
  842. $response = $saveCardResultsEndpoint->__invoke(
  843. $request,
  844. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  845. );
  846. } catch (\Throwable $exception) {
  847. return $this->endpointExceptionResponse($exception);
  848. }
  849. return $this->endpointResponse($response, Response::HTTP_OK);
  850. }
  851. /**
  852. * @Route("/card/submit-card", name="next_api_society_submit_card", methods={"POST"})
  853. */
  854. public function submitCard(Request $request, SubmitCardEndpoint $submitCardEndpoint): JsonResponse
  855. {
  856. try {
  857. $response = $submitCardEndpoint->__invoke(
  858. $request,
  859. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  860. );
  861. } catch (\Throwable $exception) {
  862. return $this->endpointExceptionResponse($exception);
  863. }
  864. return $this->endpointResponse($response, Response::HTTP_OK);
  865. }
  866. /**
  867. * @Route("/card/log-result", name="next_api_society_show_log_result", methods={"POST"})
  868. */
  869. public function logResults(Request $request, LogResultEndpoint $logResultEndpoint): Response
  870. {
  871. try {
  872. $response = $logResultEndpoint->__invoke(
  873. $request,
  874. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  875. );
  876. } catch (\Throwable $exception) {
  877. return $this->endpointExceptionResponse($exception);
  878. }
  879. return $this->endpointResponse($response, Response::HTTP_OK);
  880. }
  881. /**
  882. * @Route("/statistics", name="next_api_society_statistics", methods={"GET"})
  883. */
  884. public function statistics(Request $request, StatisticsEndpoint $statisticsEndpoint): JsonResponse
  885. {
  886. try {
  887. $response = $statisticsEndpoint->__invoke(
  888. $request,
  889. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  890. 'society-v2' === (string) $request->attributes->get('authMode', '')
  891. );
  892. } catch (\Throwable $exception) {
  893. return $this->endpointExceptionResponse($exception);
  894. }
  895. return $this->endpointResponse($response, Response::HTTP_OK);
  896. }
  897. /**
  898. * @Route("/stats/hcp-evolution", name="next_api_society_stats_hcp_evolution", methods={"POST"})
  899. */
  900. public function hcpEvolution(Request $request, HcpEvolutionEndpoint $hcpEvolutionEndpoint): JsonResponse
  901. {
  902. $payload = $this->parseJsonPayload($request);
  903. if (null === $payload) {
  904. return $this->invalidJsonResponse();
  905. }
  906. $payload = $this->injectResolvedUserId($request, $payload);
  907. return $this->runSocietyJsonEndpoint(fn(): array => $hcpEvolutionEndpoint->__invoke($payload));
  908. }
  909. /**
  910. * @Route("/stats/played-results", name="next_api_society_stats_played_results", methods={"POST"})
  911. */
  912. public function playedResults(Request $request, PlayedResultsStatsEndpoint $playedResultsStatsEndpoint): JsonResponse
  913. {
  914. $payload = $this->parseJsonPayload($request);
  915. if (null === $payload) {
  916. return $this->invalidJsonResponse();
  917. }
  918. $payload = $this->injectResolvedUserId($request, $payload);
  919. return $this->runSocietyJsonEndpoint(fn(): array => $playedResultsStatsEndpoint->__invoke($payload));
  920. }
  921. /**
  922. * @Route("/stats/competitions-by-club", name="next_api_society_stats_competitions_by_club", methods={"POST"})
  923. */
  924. public function competitionsByClub(Request $request, CompetitionsByClubStatsEndpoint $competitionsByClubStatsEndpoint): JsonResponse
  925. {
  926. $payload = $this->parseJsonPayload($request);
  927. if (null === $payload) {
  928. return $this->invalidJsonResponse();
  929. }
  930. $payload = $this->injectResolvedUserId($request, $payload);
  931. return $this->runSocietyJsonEndpoint(fn(): array => $competitionsByClubStatsEndpoint->__invoke($payload));
  932. }
  933. /**
  934. * @Route("/club/list", name="next_api_society_club_list", methods={"GET"})
  935. */
  936. public function clubList(Request $request, ClubListEndpoint $clubListEndpoint): JsonResponse
  937. {
  938. try {
  939. $response = $clubListEndpoint->__invoke($request);
  940. } catch (\Throwable $exception) {
  941. return $this->endpointExceptionResponse($exception);
  942. }
  943. return $this->endpointResponse($response, Response::HTTP_OK);
  944. }
  945. /**
  946. * @Route("/reservations/clubs", name="next_api_society_booking_clubs", methods={"GET"})
  947. */
  948. public function bookingClubs(Request $request, SearchBookableClubsEndpoint $endpoint): JsonResponse
  949. {
  950. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($request));
  951. }
  952. /**
  953. * @Route("/reservations/availability", name="next_api_society_booking_availability", methods={"GET"})
  954. */
  955. public function bookingAvailability(Request $request, SearchBookingAvailabilityEndpoint $endpoint): JsonResponse
  956. {
  957. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($request));
  958. }
  959. /**
  960. * @Route("/reservations", name="next_api_society_booking_list", methods={"GET"})
  961. */
  962. public function bookings(Request $request, ListBookingsEndpoint $endpoint): JsonResponse
  963. {
  964. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint(
  965. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  966. $request
  967. ));
  968. }
  969. /**
  970. * @Route("/reservations/search", name="next_api_society_booking_search", methods={"GET"})
  971. */
  972. public function searchBookings(Request $request, SearchBookingsEndpoint $endpoint): JsonResponse
  973. {
  974. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint(
  975. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  976. $request
  977. ));
  978. }
  979. /**
  980. * @Route("/reservations", name="next_api_society_booking_create", methods={"POST"})
  981. */
  982. public function createBooking(Request $request, CreateBookingEndpoint $endpoint): JsonResponse
  983. {
  984. $payload = $this->parseJsonPayload($request);
  985. if (null === $payload) {
  986. return $this->invalidJsonResponse();
  987. }
  988. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint(
  989. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  990. (string) $request->headers->get('Idempotency-Key', ''),
  991. $payload
  992. ), Response::HTTP_CREATED);
  993. }
  994. /**
  995. * @Route("/reservations/{id}", name="next_api_society_booking_detail", methods={"GET"}, requirements={"id"="\d+"})
  996. */
  997. public function bookingDetail(int $id, Request $request, GetBookingEndpoint $endpoint): JsonResponse
  998. {
  999. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($id, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  1000. }
  1001. /**
  1002. * @Route("/reservations/{id}/payment-session", name="next_api_society_booking_payment_session", methods={"POST"}, requirements={"id"="\d+"})
  1003. */
  1004. public function bookingPaymentSession(int $id, Request $request, CreatePaymentSessionEndpoint $endpoint): JsonResponse
  1005. {
  1006. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($id, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  1007. }
  1008. /**
  1009. * @Route("/reservations/{id}/confirm", name="next_api_society_booking_confirm", methods={"POST"}, requirements={"id"="\d+"})
  1010. */
  1011. public function confirmBooking(int $id, Request $request, ConfirmBookingEndpoint $endpoint): JsonResponse
  1012. {
  1013. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($id, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  1014. }
  1015. /**
  1016. * @Route("/reservations/{id}/cancel-preview", name="next_api_society_booking_cancel_preview", methods={"POST"}, requirements={"id"="\d+"})
  1017. */
  1018. public function previewBookingCancellation(int $id, Request $request, PreviewBookingCancellationEndpoint $endpoint): JsonResponse
  1019. {
  1020. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($id, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  1021. }
  1022. /**
  1023. * @Route("/reservations/{id}/cancel", name="next_api_society_booking_cancel", methods={"POST"}, requirements={"id"="\d+"})
  1024. */
  1025. public function cancelBooking(int $id, Request $request, CancelBookingEndpoint $endpoint): JsonResponse
  1026. {
  1027. return $this->runSocietyJsonEndpoint(fn (): array => $endpoint($id, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  1028. }
  1029. /**
  1030. * @Route("/course/club/{club}", name="next_api_society_course_by_club", methods={"GET"})
  1031. */
  1032. public function coursesByClub(string $club, CoursesByClubEndpoint $coursesByClubEndpoint): JsonResponse
  1033. {
  1034. try {
  1035. $response = $coursesByClubEndpoint->__invoke($club);
  1036. } catch (\Throwable $exception) {
  1037. return $this->endpointExceptionResponse($exception);
  1038. }
  1039. return $this->endpointResponse($response, Response::HTTP_OK);
  1040. }
  1041. /**
  1042. * @Route("/course/{course}/tees", name="next_api_society_course_tees", methods={"GET"})
  1043. */
  1044. public function courseTees(string $course, CourseTeesByCourseEndpoint $courseTeesByCourseEndpoint): JsonResponse
  1045. {
  1046. try {
  1047. $response = $courseTeesByCourseEndpoint->__invoke($course);
  1048. } catch (\Throwable $exception) {
  1049. return $this->endpointExceptionResponse($exception);
  1050. }
  1051. return $this->endpointResponse($response, Response::HTTP_OK);
  1052. }
  1053. /**
  1054. * @Route("/player/license-course-tees", name="next_api_society_player_license_course_tees", methods={"POST"})
  1055. */
  1056. public function playerLicenseCourseTees(Request $request, PlayerLicenseCourseTeesEndpoint $playerLicenseCourseTeesEndpoint): JsonResponse|Response
  1057. {
  1058. $payload = $this->parseJsonPayload($request);
  1059. if (null === $payload) {
  1060. return $this->invalidJsonResponse();
  1061. }
  1062. return $this->runSocietyJsonEndpoint(fn(): array => $playerLicenseCourseTeesEndpoint->__invoke(
  1063. $payload,
  1064. (int) $request->attributes->get('resolvedPlayerId', 0)
  1065. ));
  1066. }
  1067. /**
  1068. * @Route("/rfc/competition", name="next_api_society_rfc_competition_create", methods={"POST"})
  1069. */
  1070. public function createRfcCompetition(Request $request, CreateRfcCompetitionEndpoint $createRfcCompetitionEndpoint): JsonResponse|Response
  1071. {
  1072. $payload = $this->parseJsonPayload($request);
  1073. if (null === $payload) {
  1074. return $this->invalidJsonResponse();
  1075. }
  1076. return $this->runSocietyJsonEndpoint(fn(): array => $createRfcCompetitionEndpoint->__invoke(
  1077. $payload,
  1078. (int) $request->attributes->get('resolvedPlayerId', 0)
  1079. ));
  1080. }
  1081. /**
  1082. * @Route("/rfc/competition/{id}/cards", name="next_api_society_rfc_cards_send", methods={"POST"}, requirements={"id"="\d+"})
  1083. */
  1084. public function sendRfcCards(int $id, Request $request, SendRfcCardsEndpoint $sendRfcCardsEndpoint): JsonResponse|Response
  1085. {
  1086. return $this->runSocietyJsonEndpoint(fn(): array => $sendRfcCardsEndpoint->__invoke(
  1087. $id,
  1088. (int) $request->attributes->get('resolvedPlayerId', 0)
  1089. ));
  1090. }
  1091. /**
  1092. * @Route("/competitions/played", name="next_api_society_competitions_played_by_players", methods={"POST"})
  1093. */
  1094. public function nextcaddyPlayedCompetitions(Request $request, NextcaddyPlayedCompetitionsEndpoint $playedCompetitionsEndpoint): JsonResponse
  1095. {
  1096. $payload = $this->parseJsonPayload($request);
  1097. if (null === $payload) {
  1098. return $this->invalidJsonResponse();
  1099. }
  1100. $payload = $this->injectResolvedUserId($request, $payload);
  1101. return $this->runSocietyJsonEndpoint(fn(): array => $playedCompetitionsEndpoint->__invoke($payload));
  1102. }
  1103. /**
  1104. * @Route("/competitions/future-by-player", name="next_api_society_competitions_future_by_player", methods={"POST"})
  1105. */
  1106. public function nextcaddyFutureCompetitions(Request $request, NextcaddyFutureCompetitionsEndpoint $futureCompetitionsEndpoint): JsonResponse
  1107. {
  1108. $payload = $this->parseJsonPayload($request);
  1109. if (null === $payload) {
  1110. return $this->invalidJsonResponse();
  1111. }
  1112. $payload = $this->injectResolvedUserId($request, $payload);
  1113. return $this->runSocietyJsonEndpoint(fn(): array => $futureCompetitionsEndpoint->__invoke($payload));
  1114. }
  1115. /**
  1116. * @Route("/competitions/inscriptions/available", name="next_api_society_competitions_available_inscriptions", methods={"POST"})
  1117. */
  1118. public function availableInscriptions(Request $request, AvailableInscriptionsEndpoint $availableInscriptionsEndpoint): JsonResponse
  1119. {
  1120. $payload = $this->parseJsonPayload($request);
  1121. if (null === $payload) {
  1122. return $this->invalidJsonResponse();
  1123. }
  1124. return $this->runSocietyJsonEndpoint(fn(): array => $availableInscriptionsEndpoint->__invoke($payload));
  1125. }
  1126. /**
  1127. * @Route("/competitions/scorecard", name="next_api_society_competitions_scorecard", methods={"POST"})
  1128. */
  1129. public function competitionScorecard(Request $request, CompetitionScorecardEndpoint $competitionScorecardEndpoint): JsonResponse
  1130. {
  1131. $payload = $this->parseJsonPayload($request);
  1132. if (null === $payload) {
  1133. return $this->invalidJsonResponse();
  1134. }
  1135. $payload = $this->injectResolvedUserId($request, $payload);
  1136. return $this->runSocietyJsonEndpoint(fn(): array => $competitionScorecardEndpoint->__invoke($payload));
  1137. }
  1138. /**
  1139. * @Route("/competitions/show", name="next_api_society_competitions_show", methods={"POST"})
  1140. */
  1141. public function competitionShow(Request $request, CompetitionShowEndpoint $competitionShowEndpoint): JsonResponse
  1142. {
  1143. $payload = $this->parseJsonPayload($request);
  1144. if (null === $payload) {
  1145. return $this->invalidJsonResponse();
  1146. }
  1147. $payload = $this->injectResolvedUserId($request, $payload);
  1148. return $this->runSocietyJsonEndpoint(fn(): array => $competitionShowEndpoint->__invoke(
  1149. $payload,
  1150. (int) $request->attributes->get('resolvedUserId', 0),
  1151. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  1152. ));
  1153. }
  1154. /**
  1155. * @Route("/competitions/{id}/classifications", name="next_api_society_competitions_classifications", methods={"GET"})
  1156. */
  1157. public function nextcaddyClassificationsByCompetition($id, NextcaddyClassificationListEndpoint $classificationListEndpoint): JsonResponse
  1158. {
  1159. return $this->runSocietyJsonEndpoint(fn(): array => $classificationListEndpoint->__invoke($id));
  1160. }
  1161. /**
  1162. * @Route("/info/{type}", name="next_api_society_info", methods={"GET"})
  1163. */
  1164. public function info(string $type, InformationPanelEndpoint $informationPanelEndpoint): JsonResponse
  1165. {
  1166. try {
  1167. $response = $informationPanelEndpoint->__invoke($type);
  1168. } catch (\Throwable $exception) {
  1169. return $this->endpointExceptionResponse($exception);
  1170. }
  1171. return $this->endpointResponse($response, Response::HTTP_OK);
  1172. }
  1173. /**
  1174. * @Route("/ranking", name="next_api_society_ranking_by_data", methods={"GET"})
  1175. */
  1176. public function rankingByData(Request $request, RankingByDataEndpoint $rankingByDataEndpoint): JsonResponse
  1177. {
  1178. try {
  1179. $response = $rankingByDataEndpoint->__invoke(
  1180. $request,
  1181. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1182. );
  1183. } catch (\Throwable $exception) {
  1184. return $this->endpointExceptionResponse($exception);
  1185. }
  1186. return $this->endpointResponse($response, Response::HTTP_OK);
  1187. }
  1188. /**
  1189. * @Route("/ranking/{id}", name="next_api_society_ranking_detail", methods={"GET"})
  1190. */
  1191. public function rankingDetail($id, Request $request, RankingDetailEndpoint $rankingDetailEndpoint): JsonResponse
  1192. {
  1193. try {
  1194. $response = $rankingDetailEndpoint->__invoke(
  1195. $id,
  1196. (int) $request->attributes->get('resolvedSocietyUserId', 0)
  1197. );
  1198. } catch (\Throwable $exception) {
  1199. return $this->endpointExceptionResponse($exception);
  1200. }
  1201. return $this->endpointResponse($response, Response::HTTP_OK);
  1202. }
  1203. /**
  1204. * @Route("/ranking/{rankingId}/user/{id}", name="next_api_society_ranking_user_detail", methods={"GET"})
  1205. */
  1206. public function rankingUserDetail($rankingId, $id, RankingUserDetailEndpoint $rankingUserDetailEndpoint): JsonResponse
  1207. {
  1208. try {
  1209. $response = $rankingUserDetailEndpoint->__invoke((int)$rankingId, (int)$id);
  1210. } catch (\Throwable $exception) {
  1211. return $this->endpointExceptionResponse($exception);
  1212. }
  1213. return $this->endpointResponse($response, Response::HTTP_OK);
  1214. }
  1215. /**
  1216. * @Route("/rankings/visible-by-player", name="next_api_society_rankings_visible_by_player", methods={"POST"})
  1217. */
  1218. public function visibleRankingsByPlayer(Request $request, PlayerVisibleRankingsEndpoint $playerVisibleRankingsEndpoint): JsonResponse
  1219. {
  1220. $payload = $this->parseJsonPayload($request);
  1221. if (null === $payload) {
  1222. return $this->invalidJsonResponse();
  1223. }
  1224. $payload = $this->injectResolvedUserId($request, $payload);
  1225. return $this->runSocietyJsonEndpoint(fn(): array => $playerVisibleRankingsEndpoint->__invoke($payload));
  1226. }
  1227. /**
  1228. * @Route("/rankings/leaderboard", name="next_api_society_rankings_leaderboard", methods={"POST"})
  1229. */
  1230. public function rankingLeaderboard(Request $request, RankingLeaderboardEndpoint $rankingLeaderboardEndpoint): JsonResponse
  1231. {
  1232. $payload = $this->parseJsonPayload($request);
  1233. if (null === $payload) {
  1234. return $this->invalidJsonResponse();
  1235. }
  1236. return $this->runSocietyJsonEndpoint(fn(): array => $rankingLeaderboardEndpoint->__invoke($payload));
  1237. }
  1238. /**
  1239. * @Route("/nextcaddy/ranking/{id}", name="next_api_society_nextcaddy_ranking_detail", methods={"GET"})
  1240. */
  1241. public function nextcaddyRankingDetail($id, Request $request, RankingNxtDetailEndpoint $rankingNxtDetailEndpoint): JsonResponse
  1242. {
  1243. return $this->runSocietyJsonEndpoint(fn(): array => $rankingNxtDetailEndpoint->__invoke(
  1244. (int) $id,
  1245. (int) $request->attributes->get('resolvedUserId', 0)
  1246. ));
  1247. }
  1248. /**
  1249. * @Route("/nextcaddy/ranking/{rankingId}/classified/{id}", name="next_api_society_nextcaddy_ranking_classified_detail", methods={"GET"})
  1250. */
  1251. public function nextcaddyRankingClassifiedDetail($rankingId, $id, RankingClassifiedNxtDetailEndpoint $rankingClassifiedNxtDetailEndpoint): JsonResponse
  1252. {
  1253. return $this->runSocietyJsonEndpoint(fn(): array => $rankingClassifiedNxtDetailEndpoint->__invoke((int) $rankingId, (int) $id));
  1254. }
  1255. /**
  1256. * @Route("/shared/competitions", name="next_api_society_shared_competitions_search", methods={"GET"})
  1257. */
  1258. public function sharedCompetitionsSearch(Request $request, SearchCompetitionsEndpoint $searchCompetitionsEndpoint): JsonResponse
  1259. {
  1260. try {
  1261. $response = $searchCompetitionsEndpoint->__invoke($request->query->all());
  1262. } catch (\Throwable $exception) {
  1263. return $this->endpointExceptionResponse($exception);
  1264. }
  1265. return $this->endpointResponse($response, Response::HTTP_OK);
  1266. }
  1267. /**
  1268. * @Route("/shared/competitions/future", name="next_api_society_shared_competitions_future", methods={"GET"})
  1269. */
  1270. public function sharedCompetitionsFuture(Request $request, FutureCompetitionsEndpoint $futureCompetitionsEndpoint): JsonResponse
  1271. {
  1272. try {
  1273. $response = $futureCompetitionsEndpoint->__invoke(
  1274. (int)$request->attributes->get('resolvedUserId', 0),
  1275. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1276. $request->query->all()
  1277. );
  1278. } catch (\Throwable $exception) {
  1279. return $this->endpointExceptionResponse($exception);
  1280. }
  1281. return $this->endpointResponse($response, Response::HTTP_OK);
  1282. }
  1283. /**
  1284. * @Route("/shared/competitions/played", name="next_api_society_shared_competitions_played", methods={"GET"})
  1285. */
  1286. public function sharedCompetitionsPlayed(Request $request, PlayedCompetitionsEndpoint $playedCompetitionsEndpoint): JsonResponse
  1287. {
  1288. try {
  1289. $response = $playedCompetitionsEndpoint->__invoke(
  1290. (int)$request->attributes->get('resolvedUserId', 0),
  1291. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1292. $request->query->all()
  1293. );
  1294. } catch (\Throwable $exception) {
  1295. return $this->endpointExceptionResponse($exception);
  1296. }
  1297. return $this->endpointResponse($response, Response::HTTP_OK);
  1298. }
  1299. /**
  1300. * @Route("/shared/competitions/open-inscription", name="next_api_society_shared_competitions_open_inscription", methods={"GET"})
  1301. */
  1302. public function sharedCompetitionsOpenInscription(Request $request, OpenInscriptionCompetitionsEndpoint $openInscriptionCompetitionsEndpoint): JsonResponse
  1303. {
  1304. try {
  1305. $response = $openInscriptionCompetitionsEndpoint->__invoke(
  1306. (int)$request->attributes->get('resolvedUserId', 0),
  1307. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1308. $request->query->all()
  1309. );
  1310. } catch (\Throwable $exception) {
  1311. return $this->endpointExceptionResponse($exception);
  1312. }
  1313. return $this->endpointResponse($response, Response::HTTP_OK);
  1314. }
  1315. /**
  1316. * @Route("/user/{id}/competitions", name="next_api_society_user_competitions", methods={"GET"}, requirements={"id"="\d+"})
  1317. */
  1318. public function userCompetitions(int $id, Request $request, UserCompetitionsEndpoint $userCompetitionsEndpoint): JsonResponse
  1319. {
  1320. try {
  1321. $response = $userCompetitionsEndpoint->__invoke($id, $request->query->all());
  1322. } catch (\Throwable $exception) {
  1323. return $this->endpointExceptionResponse($exception);
  1324. }
  1325. return $this->endpointResponse($response, Response::HTTP_OK);
  1326. }
  1327. /**
  1328. * @Route("/user/{id}/rankings", name="next_api_society_user_rankings", methods={"GET"}, requirements={"id"="\d+"})
  1329. */
  1330. public function userRankings(int $id, Request $request, UserRankingsEndpoint $userRankingsEndpoint): JsonResponse
  1331. {
  1332. try {
  1333. $response = $userRankingsEndpoint->__invoke($id, $request->query->all());
  1334. } catch (\Throwable $exception) {
  1335. return $this->endpointExceptionResponse($exception);
  1336. }
  1337. return $this->endpointResponse($response, Response::HTTP_OK);
  1338. }
  1339. /**
  1340. * @Route("/shared/rankings", name="next_api_society_shared_rankings", methods={"GET"})
  1341. */
  1342. public function sharedRankings(Request $request, RankingsSharedEndpoint $rankingsSharedEndpoint): JsonResponse
  1343. {
  1344. try {
  1345. $response = $rankingsSharedEndpoint->__invoke(
  1346. (int)$request->attributes->get('resolvedUserId', 0),
  1347. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1348. $request->query->all()
  1349. );
  1350. } catch (\Throwable $exception) {
  1351. return $this->endpointExceptionResponse($exception);
  1352. }
  1353. return $this->endpointResponse($response, Response::HTTP_OK);
  1354. }
  1355. /**
  1356. * @Route("/participant/{id}", name="next_api_society_participant_delete", methods={"DELETE"}, requirements={"id"="\d+"})
  1357. */
  1358. public function deleteParticipant(int $id, Request $request, DeleteParticipantEndpoint $deleteParticipantEndpoint): JsonResponse
  1359. {
  1360. $replacementParticipantId = (int)$request->request->get('replacementParticipantId', $request->query->get('replacementParticipantId', 0));
  1361. try {
  1362. $response = $deleteParticipantEndpoint->__invoke(
  1363. $id,
  1364. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1365. $replacementParticipantId > 0 ? $replacementParticipantId : null
  1366. );
  1367. } catch (\Throwable $exception) {
  1368. return $this->endpointExceptionResponse($exception);
  1369. }
  1370. return $this->endpointResponse($response, Response::HTTP_OK);
  1371. }
  1372. /**
  1373. * @Route("/contact", name="next_api_society_contact", methods={"POST"})
  1374. */
  1375. public function contact(Request $request, CreateContactMessageEndpoint $createContactMessageEndpoint): JsonResponse
  1376. {
  1377. try {
  1378. $response = $createContactMessageEndpoint->__invoke(
  1379. $request,
  1380. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1381. );
  1382. } catch (\Throwable $exception) {
  1383. return $this->endpointExceptionResponse($exception);
  1384. }
  1385. return $this->endpointResponse($response, Response::HTTP_OK);
  1386. }
  1387. /**
  1388. * @Route("/feed", name="next_api_society_feed_list", methods={"GET"})
  1389. */
  1390. public function feed(Request $request, FeedListEndpoint $feedListEndpoint): JsonResponse
  1391. {
  1392. try {
  1393. $response = $feedListEndpoint->__invoke(
  1394. $request,
  1395. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1396. );
  1397. } catch (\Throwable $exception) {
  1398. return $this->endpointExceptionResponse($exception);
  1399. }
  1400. return $this->endpointResponse($response, Response::HTTP_OK);
  1401. }
  1402. /**
  1403. * @Route("/user/{id}/feed", name="next_api_society_user_feed_list", methods={"GET"}, requirements={"id"="\d+"})
  1404. */
  1405. public function userFeed(int $id, Request $request, UserFeedListEndpoint $userFeedListEndpoint): JsonResponse
  1406. {
  1407. try {
  1408. $response = $userFeedListEndpoint->__invoke(
  1409. $request,
  1410. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  1411. $id
  1412. );
  1413. } catch (\Throwable $exception) {
  1414. return $this->endpointExceptionResponse($exception);
  1415. }
  1416. return $this->endpointResponse($response, Response::HTTP_OK);
  1417. }
  1418. /**
  1419. * @Route("/feed/post", name="next_api_society_feed_post_create", methods={"POST"})
  1420. */
  1421. public function createFeedPost(Request $request, CreateFeedPostEndpoint $createFeedPostEndpoint): JsonResponse
  1422. {
  1423. $payload = $this->parseJsonPayload($request);
  1424. if (null === $payload) {
  1425. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  1426. }
  1427. try {
  1428. $response = $createFeedPostEndpoint->__invoke(
  1429. $payload,
  1430. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1431. );
  1432. } catch (\Throwable $exception) {
  1433. return $this->endpointExceptionResponse($exception);
  1434. }
  1435. return $this->endpointResponse($response, Response::HTTP_CREATED);
  1436. }
  1437. /**
  1438. * @Route("/feed/post/{id}", name="next_api_society_feed_post_detail", methods={"GET"}, requirements={"id"="\d+"})
  1439. */
  1440. public function feedPost(int $id, Request $request, FeedPostDetailEndpoint $feedPostDetailEndpoint): JsonResponse
  1441. {
  1442. try {
  1443. $response = $feedPostDetailEndpoint->__invoke(
  1444. $id,
  1445. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1446. );
  1447. } catch (\Throwable $exception) {
  1448. return $this->endpointExceptionResponse($exception);
  1449. }
  1450. return $this->endpointResponse($response, Response::HTTP_OK);
  1451. }
  1452. /**
  1453. * @Route("/feed/post/{id}", name="next_api_society_feed_post_update", methods={"POST"}, requirements={"id"="\d+"})
  1454. */
  1455. public function updateFeedPost(int $id, Request $request, UpdateFeedPostEndpoint $updateFeedPostEndpoint): JsonResponse
  1456. {
  1457. $payload = $this->parseJsonPayload($request);
  1458. if (null === $payload) {
  1459. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  1460. }
  1461. try {
  1462. $response = $updateFeedPostEndpoint->__invoke(
  1463. $id,
  1464. $payload,
  1465. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1466. );
  1467. } catch (\Throwable $exception) {
  1468. return $this->endpointExceptionResponse($exception);
  1469. }
  1470. return $this->endpointResponse($response, Response::HTTP_OK);
  1471. }
  1472. /**
  1473. * @Route("/feed/post/{id}", name="next_api_society_feed_post_delete", methods={"DELETE"}, requirements={"id"="\d+"})
  1474. */
  1475. public function deleteFeedPost(int $id, Request $request, DeleteFeedPostEndpoint $deleteFeedPostEndpoint): JsonResponse
  1476. {
  1477. try {
  1478. $response = $deleteFeedPostEndpoint->__invoke(
  1479. $id,
  1480. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1481. );
  1482. } catch (\Throwable $exception) {
  1483. return $this->endpointExceptionResponse($exception);
  1484. }
  1485. return $this->endpointResponse($response, Response::HTTP_OK);
  1486. }
  1487. /**
  1488. * @Route("/feed/post/{id}/comments", name="next_api_society_feed_comments_list", methods={"GET"}, requirements={"id"="\d+"})
  1489. */
  1490. public function feedComments(int $id, Request $request, FeedCommentsListEndpoint $feedCommentsListEndpoint): JsonResponse
  1491. {
  1492. try {
  1493. $response = $feedCommentsListEndpoint->__invoke(
  1494. $id,
  1495. $request,
  1496. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1497. );
  1498. } catch (\Throwable $exception) {
  1499. return $this->endpointExceptionResponse($exception);
  1500. }
  1501. return $this->endpointResponse($response, Response::HTTP_OK);
  1502. }
  1503. /**
  1504. * @Route("/feed/comment/{id}/replies", name="next_api_society_feed_comment_replies", methods={"GET"}, requirements={"id"="\d+"})
  1505. */
  1506. public function feedCommentReplies(int $id, Request $request, FeedCommentRepliesEndpoint $feedCommentRepliesEndpoint): JsonResponse
  1507. {
  1508. try {
  1509. $response = $feedCommentRepliesEndpoint->__invoke(
  1510. $id,
  1511. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1512. );
  1513. } catch (\Throwable $exception) {
  1514. return $this->endpointExceptionResponse($exception);
  1515. }
  1516. return $this->endpointResponse($response, Response::HTTP_OK);
  1517. }
  1518. /**
  1519. * @Route("/feed/post/{id}/comments", name="next_api_society_feed_comment_create", methods={"POST"}, requirements={"id"="\d+"})
  1520. */
  1521. public function createFeedComment(int $id, Request $request, CreateFeedCommentEndpoint $createFeedCommentEndpoint): JsonResponse
  1522. {
  1523. $payload = $this->parseJsonPayload($request);
  1524. if (null === $payload) {
  1525. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  1526. }
  1527. try {
  1528. $response = $createFeedCommentEndpoint->__invoke(
  1529. $id,
  1530. $payload,
  1531. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1532. );
  1533. } catch (\Throwable $exception) {
  1534. return $this->endpointExceptionResponse($exception);
  1535. }
  1536. return $this->endpointResponse($response, Response::HTTP_CREATED);
  1537. }
  1538. /**
  1539. * @Route("/feed/comment/{id}", name="next_api_society_feed_comment_update", methods={"POST"}, requirements={"id"="\d+"})
  1540. */
  1541. public function updateFeedComment(int $id, Request $request, UpdateFeedCommentEndpoint $updateFeedCommentEndpoint): JsonResponse
  1542. {
  1543. $payload = $this->parseJsonPayload($request);
  1544. if (null === $payload) {
  1545. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  1546. }
  1547. try {
  1548. $response = $updateFeedCommentEndpoint->__invoke(
  1549. $id,
  1550. $payload,
  1551. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1552. );
  1553. } catch (\Throwable $exception) {
  1554. return $this->endpointExceptionResponse($exception);
  1555. }
  1556. return $this->endpointResponse($response, Response::HTTP_OK);
  1557. }
  1558. /**
  1559. * @Route("/feed/comment/{id}", name="next_api_society_feed_comment_delete", methods={"DELETE"}, requirements={"id"="\d+"})
  1560. */
  1561. public function deleteFeedComment(int $id, Request $request, DeleteFeedCommentEndpoint $deleteFeedCommentEndpoint): JsonResponse
  1562. {
  1563. try {
  1564. $response = $deleteFeedCommentEndpoint->__invoke(
  1565. $id,
  1566. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1567. );
  1568. } catch (\Throwable $exception) {
  1569. return $this->endpointExceptionResponse($exception);
  1570. }
  1571. return $this->endpointResponse($response, Response::HTTP_OK);
  1572. }
  1573. /**
  1574. * @Route("/round/{id}/finalize", name="next_api_society_round_finalize", methods={"POST"}, requirements={"id"="\d+"})
  1575. */
  1576. public function finalizeRound(int $id, Request $request, FinalizeRoundEndpoint $finalizeRoundEndpoint): JsonResponse
  1577. {
  1578. try {
  1579. $response = $finalizeRoundEndpoint->__invoke(
  1580. $id,
  1581. $request,
  1582. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1583. );
  1584. } catch (\Throwable $exception) {
  1585. return $this->endpointExceptionResponse($exception);
  1586. }
  1587. return $this->endpointResponse($response, Response::HTTP_OK);
  1588. }
  1589. /**
  1590. * @Route("/friendly/{id}/livescoring", name="next_api_society_friendly_livescoring", methods={"GET"}, requirements={"id"="\d+"})
  1591. */
  1592. public function friendlyLivescoring(int $id, Request $request, FriendlyLivescoringEndpoint $friendlyLivescoringEndpoint): Response
  1593. {
  1594. try {
  1595. $response = $friendlyLivescoringEndpoint->__invoke(
  1596. $id,
  1597. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1598. );
  1599. } catch (\Throwable $exception) {
  1600. return $this->endpointExceptionResponse($exception);
  1601. }
  1602. return $this->endpointResponse($response, Response::HTTP_OK);
  1603. }
  1604. /**
  1605. * @Route("/friendly/{id}/classifications", name="next_api_society_friendly_classifications", methods={"GET"}, requirements={"id"="\d+"})
  1606. */
  1607. public function friendlyClassifications(int $id, Request $request, ClassificationListEndpoint $classificationListEndpoint): JsonResponse
  1608. {
  1609. try {
  1610. $response = $classificationListEndpoint->__invoke(
  1611. $id,
  1612. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1613. );
  1614. } catch (\Throwable $exception) {
  1615. return $this->endpointExceptionResponse($exception);
  1616. }
  1617. return $this->endpointResponse($response, Response::HTTP_OK);
  1618. }
  1619. /**
  1620. * @Route("/schedule/show", name="next_api_society_schedule_show", methods={"POST"})
  1621. */
  1622. public function scheduleShow(Request $request, ScheduleShowEndpoint $scheduleShowEndpoint): JsonResponse
  1623. {
  1624. $payload = $this->parseJsonPayload($request);
  1625. if (null === $payload) {
  1626. return $this->invalidJsonResponse();
  1627. }
  1628. return $this->runSocietyJsonEndpoint(fn(): array => $scheduleShowEndpoint->__invoke($payload));
  1629. }
  1630. /**
  1631. * @Route("/friendly/{friendlyId}/schedule", name="next_api_society_schedule_create", methods={"POST"}, requirements={"friendlyId"="\d+"})
  1632. */
  1633. public function createSchedule(int $friendlyId, Request $request, CreateScheduleEndpoint $createScheduleEndpoint): JsonResponse
  1634. {
  1635. try {
  1636. $response = $createScheduleEndpoint->__invoke(
  1637. $friendlyId,
  1638. $request,
  1639. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1640. );
  1641. } catch (\Throwable $exception) {
  1642. return $this->endpointExceptionResponse($exception);
  1643. }
  1644. return $this->endpointResponse($response, Response::HTTP_OK);
  1645. }
  1646. /**
  1647. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}", name="next_api_society_schedule_delete", methods={"DELETE"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1648. */
  1649. public function deleteSchedule(int $friendlyId, int $scheduleId, Request $request, DeleteScheduleEndpoint $deleteScheduleEndpoint): JsonResponse
  1650. {
  1651. try {
  1652. $response = $deleteScheduleEndpoint->__invoke(
  1653. $friendlyId,
  1654. $scheduleId,
  1655. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1656. );
  1657. } catch (\Throwable $exception) {
  1658. return $this->endpointExceptionResponse($exception);
  1659. }
  1660. return $this->endpointResponse($response, Response::HTTP_OK);
  1661. }
  1662. /**
  1663. * @Route("/friendly/{friendlyId}/schedule/layout", name="next_api_society_schedule_layout_create", methods={"POST"}, requirements={"friendlyId"="\d+"})
  1664. */
  1665. public function createScheduleLayout(int $friendlyId, Request $request, CreateScheduleLayoutEndpoint $createScheduleLayoutEndpoint): JsonResponse
  1666. {
  1667. try {
  1668. $response = $createScheduleLayoutEndpoint->__invoke(
  1669. $friendlyId,
  1670. $request,
  1671. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1672. );
  1673. } catch (\Throwable $exception) {
  1674. return $this->endpointExceptionResponse($exception);
  1675. }
  1676. return $this->endpointResponse($response, Response::HTTP_OK);
  1677. }
  1678. /**
  1679. * @Route("/friendly/{friendlyId}/schedule", name="next_api_society_schedule_list", methods={"GET"}, requirements={"friendlyId"="\d+"})
  1680. */
  1681. public function listSchedules(int $friendlyId, Request $request, ListSchedulesEndpoint $listSchedulesEndpoint): JsonResponse
  1682. {
  1683. try {
  1684. $response = $listSchedulesEndpoint->__invoke(
  1685. $friendlyId,
  1686. $request,
  1687. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1688. );
  1689. } catch (\Throwable $exception) {
  1690. return $this->endpointExceptionResponse($exception);
  1691. }
  1692. return $this->endpointResponse($response, Response::HTTP_OK);
  1693. }
  1694. /**
  1695. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}/group", name="next_api_society_schedule_group_create", methods={"POST"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1696. */
  1697. public function createScheduleGroup(int $friendlyId, int $scheduleId, Request $request, CreateScheduleGroupEndpoint $createScheduleGroupEndpoint): JsonResponse
  1698. {
  1699. try {
  1700. $response = $createScheduleGroupEndpoint->__invoke(
  1701. $friendlyId,
  1702. $scheduleId,
  1703. $request,
  1704. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1705. );
  1706. } catch (\Throwable $exception) {
  1707. return $this->endpointExceptionResponse($exception);
  1708. }
  1709. return $this->endpointResponse($response, Response::HTTP_OK);
  1710. }
  1711. /**
  1712. * @Route("/friendly/{friendlyId}/schedule/group/{groupId}", name="next_api_society_schedule_group_update", methods={"PUT", "PATCH"}, requirements={"friendlyId"="\d+", "groupId"="\d+"})
  1713. */
  1714. public function updateScheduleGroup(int $friendlyId, int $groupId, Request $request, UpdateScheduleGroupEndpoint $updateScheduleGroupEndpoint): JsonResponse
  1715. {
  1716. try {
  1717. $response = $updateScheduleGroupEndpoint->__invoke(
  1718. $friendlyId,
  1719. $groupId,
  1720. $request,
  1721. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1722. );
  1723. } catch (\Throwable $exception) {
  1724. return $this->endpointExceptionResponse($exception);
  1725. }
  1726. return $this->endpointResponse($response, Response::HTTP_OK);
  1727. }
  1728. /**
  1729. * @Route("/friendly/{friendlyId}/schedule/group/{groupId}/player", name="next_api_society_schedule_group_player_add", methods={"POST"}, requirements={"friendlyId"="\d+", "groupId"="\d+"})
  1730. */
  1731. public function addScheduleGroupPlayer(int $friendlyId, int $groupId, Request $request, AddScheduleGroupPlayerEndpoint $addScheduleGroupPlayerEndpoint): JsonResponse
  1732. {
  1733. try {
  1734. $response = $addScheduleGroupPlayerEndpoint->__invoke(
  1735. $friendlyId,
  1736. $groupId,
  1737. $request,
  1738. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1739. );
  1740. } catch (\Throwable $exception) {
  1741. return $this->endpointExceptionResponse($exception);
  1742. }
  1743. return $this->endpointResponse($response, Response::HTTP_OK);
  1744. }
  1745. /**
  1746. * @Route("/friendly/{friendlyId}/schedule/group/{groupId}", name="next_api_society_schedule_group_delete", methods={"DELETE"}, requirements={"friendlyId"="\d+", "groupId"="\d+"})
  1747. */
  1748. public function deleteScheduleGroup(int $friendlyId, int $groupId, Request $request, DeleteScheduleGroupEndpoint $deleteScheduleGroupEndpoint): JsonResponse
  1749. {
  1750. try {
  1751. $response = $deleteScheduleGroupEndpoint->__invoke(
  1752. $friendlyId,
  1753. $groupId,
  1754. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1755. );
  1756. } catch (\Throwable $exception) {
  1757. return $this->endpointExceptionResponse($exception);
  1758. }
  1759. return $this->endpointResponse($response, Response::HTTP_OK);
  1760. }
  1761. /**
  1762. * @Route("/friendly/{friendlyId}/schedule/group/{groupId}/player/{playerScheduleId}", name="next_api_society_schedule_group_player_delete", methods={"DELETE"}, requirements={"friendlyId"="\d+", "groupId"="\d+", "playerScheduleId"="\d+"})
  1763. */
  1764. public function deleteScheduleGroupPlayer(int $friendlyId, int $groupId, int $playerScheduleId, Request $request, DeleteScheduleGroupPlayerEndpoint $deleteScheduleGroupPlayerEndpoint): JsonResponse
  1765. {
  1766. try {
  1767. $response = $deleteScheduleGroupPlayerEndpoint->__invoke(
  1768. $friendlyId,
  1769. $groupId,
  1770. $playerScheduleId,
  1771. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1772. );
  1773. } catch (\Throwable $exception) {
  1774. return $this->endpointExceptionResponse($exception);
  1775. }
  1776. return $this->endpointResponse($response, Response::HTTP_OK);
  1777. }
  1778. /**
  1779. * @Route("/friendly/{friendlyId}/schedule/player/{playerScheduleId}/move", name="next_api_society_schedule_player_move", methods={"POST"}, requirements={"friendlyId"="\d+", "playerScheduleId"="\d+"})
  1780. */
  1781. public function moveScheduleGroupPlayer(int $friendlyId, int $playerScheduleId, Request $request, MoveScheduleGroupPlayerEndpoint $moveScheduleGroupPlayerEndpoint): JsonResponse
  1782. {
  1783. try {
  1784. $response = $moveScheduleGroupPlayerEndpoint->__invoke(
  1785. $friendlyId,
  1786. $playerScheduleId,
  1787. $request,
  1788. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1789. );
  1790. } catch (\Throwable $exception) {
  1791. return $this->endpointExceptionResponse($exception);
  1792. }
  1793. return $this->endpointResponse($response, Response::HTTP_OK);
  1794. }
  1795. /**
  1796. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}", name="next_api_society_schedule_detail", methods={"GET"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1797. */
  1798. public function scheduleDetail(int $friendlyId, int $scheduleId, Request $request, ScheduleDetailEndpoint $scheduleDetailEndpoint): JsonResponse
  1799. {
  1800. try {
  1801. $response = $scheduleDetailEndpoint->__invoke(
  1802. $friendlyId,
  1803. $scheduleId,
  1804. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1805. );
  1806. } catch (\Throwable $exception) {
  1807. return $this->endpointExceptionResponse($exception);
  1808. }
  1809. return $this->endpointResponse($response, Response::HTTP_OK);
  1810. }
  1811. /**
  1812. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}/layout", name="next_api_society_schedule_layout_save", methods={"PUT"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1813. */
  1814. public function saveScheduleLayout(int $friendlyId, int $scheduleId, Request $request, SaveScheduleLayoutEndpoint $saveScheduleLayoutEndpoint): JsonResponse
  1815. {
  1816. try {
  1817. $response = $saveScheduleLayoutEndpoint->__invoke(
  1818. $friendlyId,
  1819. $scheduleId,
  1820. $request,
  1821. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1822. );
  1823. } catch (\Throwable $exception) {
  1824. return $this->endpointExceptionResponse($exception);
  1825. }
  1826. return $this->endpointResponse($response, Response::HTTP_OK);
  1827. }
  1828. /**
  1829. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}/publish", name="next_api_society_schedule_publish", methods={"POST"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1830. */
  1831. public function publishSchedule(int $friendlyId, int $scheduleId, Request $request, PublishScheduleEndpoint $publishScheduleEndpoint): JsonResponse
  1832. {
  1833. try {
  1834. $response = $publishScheduleEndpoint->__invoke(
  1835. $friendlyId,
  1836. $scheduleId,
  1837. $request,
  1838. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1839. );
  1840. } catch (\Throwable $exception) {
  1841. return $this->endpointExceptionResponse($exception);
  1842. }
  1843. return $this->endpointResponse($response, Response::HTTP_OK);
  1844. }
  1845. /**
  1846. * @Route("/friendly/{friendlyId}/schedule/{scheduleId}/unpublish", name="next_api_society_schedule_unpublish", methods={"POST"}, requirements={"friendlyId"="\d+", "scheduleId"="\d+"})
  1847. */
  1848. public function unpublishSchedule(int $friendlyId, int $scheduleId, Request $request, UnpublishScheduleEndpoint $unpublishScheduleEndpoint): JsonResponse
  1849. {
  1850. try {
  1851. $response = $unpublishScheduleEndpoint->__invoke(
  1852. $friendlyId,
  1853. $scheduleId,
  1854. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1855. );
  1856. } catch (\Throwable $exception) {
  1857. return $this->endpointExceptionResponse($exception);
  1858. }
  1859. return $this->endpointResponse($response, Response::HTTP_OK);
  1860. }
  1861. /**
  1862. * @Route("/follow/{id}", name="next_api_society_follow_user", methods={"POST"}, requirements={"id"="\d+"})
  1863. */
  1864. public function followUser(int $id, Request $request, FollowUserEndpoint $followUserEndpoint): JsonResponse
  1865. {
  1866. try {
  1867. $response = $followUserEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1868. } catch (\Throwable $exception) {
  1869. return $this->endpointExceptionResponse($exception);
  1870. }
  1871. return $this->endpointResponse($response, Response::HTTP_OK);
  1872. }
  1873. /**
  1874. * @Route("/follow/{id}", name="next_api_society_unfollow_user", methods={"DELETE"}, requirements={"id"="\d+"})
  1875. */
  1876. public function unfollowUser(int $id, Request $request, UnfollowUserEndpoint $unfollowUserEndpoint): JsonResponse
  1877. {
  1878. try {
  1879. $response = $unfollowUserEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1880. } catch (\Throwable $exception) {
  1881. return $this->endpointExceptionResponse($exception);
  1882. }
  1883. return $this->endpointResponse($response, Response::HTTP_OK);
  1884. }
  1885. /**
  1886. * @Route("/follow/request/{id}/cancel", name="next_api_society_follow_request_cancel", methods={"POST"}, requirements={"id"="\d+"})
  1887. */
  1888. public function cancelFollowRequest(int $id, Request $request, CancelFollowRequestEndpoint $cancelFollowRequestEndpoint): JsonResponse
  1889. {
  1890. try {
  1891. $response = $cancelFollowRequestEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1892. } catch (\Throwable $exception) {
  1893. return $this->endpointExceptionResponse($exception);
  1894. }
  1895. return $this->endpointResponse($response, Response::HTTP_OK);
  1896. }
  1897. /**
  1898. * @Route("/follow/request/{id}/accept", name="next_api_society_follow_request_accept", methods={"POST"}, requirements={"id"="\d+"})
  1899. */
  1900. public function acceptFollowRequest(int $id, Request $request, AcceptFollowRequestEndpoint $acceptFollowRequestEndpoint): JsonResponse
  1901. {
  1902. try {
  1903. $response = $acceptFollowRequestEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1904. } catch (\Throwable $exception) {
  1905. return $this->endpointExceptionResponse($exception);
  1906. }
  1907. return $this->endpointResponse($response, Response::HTTP_OK);
  1908. }
  1909. /**
  1910. * @Route("/follow/request/{id}/reject", name="next_api_society_follow_request_reject", methods={"POST"}, requirements={"id"="\d+"})
  1911. */
  1912. public function rejectFollowRequest(int $id, Request $request, RejectFollowRequestEndpoint $rejectFollowRequestEndpoint): JsonResponse
  1913. {
  1914. try {
  1915. $response = $rejectFollowRequestEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1916. } catch (\Throwable $exception) {
  1917. return $this->endpointExceptionResponse($exception);
  1918. }
  1919. return $this->endpointResponse($response, Response::HTTP_OK);
  1920. }
  1921. /**
  1922. * @Route("/follow/follower/{id}", name="next_api_society_follow_remove_follower", methods={"DELETE"}, requirements={"id"="\d+"})
  1923. */
  1924. public function removeFollower(int $id, Request $request, RemoveFollowerEndpoint $removeFollowerEndpoint): JsonResponse
  1925. {
  1926. try {
  1927. $response = $removeFollowerEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1928. } catch (\Throwable $exception) {
  1929. return $this->endpointExceptionResponse($exception);
  1930. }
  1931. return $this->endpointResponse($response, Response::HTTP_OK);
  1932. }
  1933. /**
  1934. * @Route("/follow/block/{id}", name="next_api_society_follow_block_user", methods={"POST"}, requirements={"id"="\d+"})
  1935. */
  1936. public function blockFollowUser(int $id, Request $request, BlockFollowUserEndpoint $blockFollowUserEndpoint): JsonResponse
  1937. {
  1938. try {
  1939. $response = $blockFollowUserEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1940. } catch (\Throwable $exception) {
  1941. return $this->endpointExceptionResponse($exception);
  1942. }
  1943. return $this->endpointResponse($response, Response::HTTP_OK);
  1944. }
  1945. /**
  1946. * @Route("/follow/unblock/{id}", name="next_api_society_follow_unblock_user", methods={"POST"}, requirements={"id"="\d+"})
  1947. */
  1948. public function unblockFollowUser(int $id, Request $request, UnblockFollowUserEndpoint $unblockFollowUserEndpoint): JsonResponse
  1949. {
  1950. try {
  1951. $response = $unblockFollowUserEndpoint->__invoke($id, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1952. } catch (\Throwable $exception) {
  1953. return $this->endpointExceptionResponse($exception);
  1954. }
  1955. return $this->endpointResponse($response, Response::HTTP_OK);
  1956. }
  1957. /**
  1958. * @Route("/follow/discover", name="next_api_society_follow_discover", methods={"GET"})
  1959. */
  1960. public function discoverFollowUsers(Request $request, DiscoverFollowUsersEndpoint $discoverFollowUsersEndpoint): JsonResponse
  1961. {
  1962. try {
  1963. $response = $discoverFollowUsersEndpoint->__invoke($request, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1964. } catch (\Throwable $exception) {
  1965. return $this->endpointExceptionResponse($exception);
  1966. }
  1967. return $this->endpointResponse($response, Response::HTTP_OK);
  1968. }
  1969. /**
  1970. * @Route("/follow/blocked", name="next_api_society_follow_blocked_list", methods={"GET"})
  1971. */
  1972. public function blockedUsers(Request $request, BlockedUsersListEndpoint $blockedUsersListEndpoint): JsonResponse
  1973. {
  1974. try {
  1975. $response = $blockedUsersListEndpoint->__invoke($request, (int)$request->attributes->get('resolvedSocietyUserId', 0));
  1976. } catch (\Throwable $exception) {
  1977. return $this->endpointExceptionResponse($exception);
  1978. }
  1979. return $this->endpointResponse($response, Response::HTTP_OK);
  1980. }
  1981. /**
  1982. * @Route("/follow/followers", name="next_api_society_followers_list", methods={"GET"})
  1983. */
  1984. public function followers(Request $request, FollowersListEndpoint $followersListEndpoint): JsonResponse
  1985. {
  1986. return $this->runSocietyJsonEndpoint(fn(): array => $followersListEndpoint->__invoke(
  1987. $request,
  1988. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1989. ));
  1990. }
  1991. /**
  1992. * @Route("/follow/following", name="next_api_society_following_list", methods={"GET"})
  1993. */
  1994. public function following(Request $request, FollowingListEndpoint $followingListEndpoint): JsonResponse
  1995. {
  1996. return $this->runSocietyJsonEndpoint(fn(): array => $followingListEndpoint->__invoke(
  1997. $request,
  1998. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  1999. ));
  2000. }
  2001. /**
  2002. * @Route("/follow/friends", name="next_api_society_friends_list", methods={"GET"})
  2003. */
  2004. public function friends(Request $request, FriendsListEndpoint $friendsListEndpoint): JsonResponse
  2005. {
  2006. return $this->runSocietyJsonEndpoint(fn(): array => $friendsListEndpoint->__invoke(
  2007. $request,
  2008. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2009. ));
  2010. }
  2011. /**
  2012. * @Route("/follow/playing-today", name="next_api_society_following_playing_today", methods={"GET"})
  2013. */
  2014. public function followingPlayingToday(Request $request, FollowingPlayingTodayEndpoint $followingPlayingTodayEndpoint): JsonResponse
  2015. {
  2016. try {
  2017. $response = $followingPlayingTodayEndpoint->__invoke(
  2018. (int) $request->attributes->get('resolvedSocietyUserId', 0),
  2019. (int) $request->attributes->get('resolvedUserId', 0)
  2020. );
  2021. } catch (\Throwable $exception) {
  2022. return $this->endpointExceptionResponse($exception);
  2023. }
  2024. return $this->endpointResponse($response, Response::HTTP_OK);
  2025. }
  2026. /**
  2027. * @Route("/follow/requests/received", name="next_api_society_follow_requests_received", methods={"GET"})
  2028. */
  2029. public function receivedFollowRequests(Request $request, PendingReceivedFollowRequestsEndpoint $pendingReceivedFollowRequestsEndpoint): JsonResponse
  2030. {
  2031. try {
  2032. $response = $pendingReceivedFollowRequestsEndpoint->__invoke((int)$request->attributes->get('resolvedSocietyUserId', 0));
  2033. } catch (\Throwable $exception) {
  2034. return $this->endpointExceptionResponse($exception);
  2035. }
  2036. return $this->endpointResponse($response, Response::HTTP_OK);
  2037. }
  2038. /**
  2039. * @Route("/follow/requests/sent", name="next_api_society_follow_requests_sent", methods={"GET"})
  2040. */
  2041. public function sentFollowRequests(Request $request, PendingSentFollowRequestsEndpoint $pendingSentFollowRequestsEndpoint): JsonResponse
  2042. {
  2043. try {
  2044. $response = $pendingSentFollowRequestsEndpoint->__invoke((int)$request->attributes->get('resolvedSocietyUserId', 0));
  2045. } catch (\Throwable $exception) {
  2046. return $this->endpointExceptionResponse($exception);
  2047. }
  2048. return $this->endpointResponse($response, Response::HTTP_OK);
  2049. }
  2050. /**
  2051. * @Route("/friendlies", name="next_api_society_friendlies_list", methods={"POST"})
  2052. */
  2053. public function friendlies(Request $request, FriendlyListEndpoint $friendlyListEndpoint): JsonResponse
  2054. {
  2055. $payload = $this->parseJsonPayload($request);
  2056. if (null === $payload) {
  2057. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  2058. }
  2059. try {
  2060. $response = $friendlyListEndpoint->__invoke(
  2061. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  2062. $payload
  2063. );
  2064. } catch (\Throwable $exception) {
  2065. return $this->endpointExceptionResponse($exception);
  2066. }
  2067. return $this->endpointResponse($response, Response::HTTP_OK);
  2068. }
  2069. /**
  2070. * @Route("/friendly/create", name="next_api_society_friendly_create", methods={"POST"})
  2071. */
  2072. public function createFriendly(Request $request, FriendlyCreateEndpoint $friendlyCreateEndpoint): JsonResponse
  2073. {
  2074. $payload = $this->parseJsonPayload($request);
  2075. if (null === $payload) {
  2076. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  2077. }
  2078. try {
  2079. $response = $friendlyCreateEndpoint->__invoke(
  2080. $payload,
  2081. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2082. );
  2083. } catch (\Throwable $exception) {
  2084. return $this->endpointExceptionResponse($exception);
  2085. }
  2086. return $this->endpointResponse($response, Response::HTTP_CREATED);
  2087. }
  2088. /**
  2089. * @Route("/friendly/edit/{id}", name="next_api_society_friendly_edit", methods={"POST"}, requirements={"id"="\d+"})
  2090. */
  2091. public function editFriendly(int $id, Request $request, FriendlyEditEndpoint $friendlyEditEndpoint): JsonResponse
  2092. {
  2093. $payload = $this->parseJsonPayload($request);
  2094. if (null === $payload) {
  2095. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  2096. }
  2097. try {
  2098. $response = $friendlyEditEndpoint->__invoke(
  2099. $id,
  2100. $payload,
  2101. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2102. );
  2103. } catch (\Throwable $exception) {
  2104. return $this->endpointExceptionResponse($exception);
  2105. }
  2106. return $this->endpointResponse($response, Response::HTTP_OK);
  2107. }
  2108. /**
  2109. * @Route("/friendly/code", name="next_api_society_friendly_by_code", methods={"POST"})
  2110. */
  2111. public function friendlyByCode(Request $request, FriendlyByCodeEndpoint $friendlyByCodeEndpoint): JsonResponse
  2112. {
  2113. $payload = $this->parseJsonPayload($request);
  2114. if (null === $payload) {
  2115. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  2116. }
  2117. try {
  2118. $response = $friendlyByCodeEndpoint->__invoke(
  2119. $payload,
  2120. $request->query->all()
  2121. );
  2122. } catch (\Throwable $exception) {
  2123. return $this->endpointExceptionResponse($exception);
  2124. }
  2125. return $this->endpointResponse($response, Response::HTTP_OK);
  2126. }
  2127. /**
  2128. * @Route("/friendly/delete/{id}", name="next_api_society_friendly_delete", methods={"POST"}, requirements={"id"="\d+"})
  2129. */
  2130. public function deleteFriendly(int $id, Request $request, FriendlyDeleteEndpoint $friendlyDeleteEndpoint): JsonResponse
  2131. {
  2132. try {
  2133. $response = $friendlyDeleteEndpoint->__invoke(
  2134. $id,
  2135. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2136. );
  2137. } catch (\Throwable $exception) {
  2138. return $this->endpointExceptionResponse($exception);
  2139. }
  2140. return $this->endpointResponse($response, Response::HTTP_OK);
  2141. }
  2142. /**
  2143. * @Route("/friendly/closest", name="next_api_society_friendly_closest", methods={"GET"})
  2144. */
  2145. public function closestFriendlies(Request $request, FriendlyClosestEndpoint $friendlyClosestEndpoint): JsonResponse
  2146. {
  2147. try {
  2148. $response = $friendlyClosestEndpoint->__invoke(
  2149. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  2150. $request->query->all()
  2151. );
  2152. } catch (\Throwable $exception) {
  2153. return $this->endpointExceptionResponse($exception);
  2154. }
  2155. return $this->endpointResponse($response, Response::HTTP_OK);
  2156. }
  2157. /**
  2158. * @Route("/shared/friendly/next", name="next_api_society_shared_next_friendly", methods={"GET"})
  2159. */
  2160. public function sharedNextFriendly(Request $request, SharedNextGameEndpoint $sharedNextFriendlyEndpoint): JsonResponse
  2161. {
  2162. try {
  2163. $response = $sharedNextFriendlyEndpoint->__invoke(
  2164. (int)$request->attributes->get('resolvedUserId', 0),
  2165. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2166. );
  2167. } catch (\Throwable $exception) {
  2168. return $this->endpointExceptionResponse($exception);
  2169. }
  2170. return $this->endpointResponse($response, Response::HTTP_OK);
  2171. }
  2172. /**
  2173. * @Route("/friendly/{id}", name="next_api_society_friendly_detail", methods={"GET"}, requirements={"id"="\d+"})
  2174. */
  2175. public function detailFriendly(int $id, Request $request, FriendlyDetailEndpoint $friendlyDetailEndpoint): JsonResponse
  2176. {
  2177. try {
  2178. $response = $friendlyDetailEndpoint->__invoke(
  2179. $id,
  2180. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  2181. true,
  2182. (int)$request->attributes->get('resolvedUserId', 0)
  2183. );
  2184. } catch (\Throwable $exception) {
  2185. return $this->endpointExceptionResponse($exception);
  2186. }
  2187. return $this->endpointResponse($response, Response::HTTP_OK);
  2188. }
  2189. /**
  2190. * @Route("/friendly/{id}/participants/handicaps", name="next_api_society_friendly_participant_handicaps", methods={"GET", "POST"}, requirements={"id"="\d+"})
  2191. */
  2192. public function friendlyParticipantHandicaps(int $id, Request $request, \App\Controller\Api\Society\Friendly\Service\FriendlyParticipantHandicapsEndpoint $endpoint): JsonResponse
  2193. {
  2194. try {
  2195. $userId = (int) $request->attributes->get('resolvedSocietyUserId', 0);
  2196. if ($request->isMethod('GET')) return $this->endpointResponse($endpoint->editor($id, $userId));
  2197. $payload = $this->parseJsonPayload($request);
  2198. if (null === $payload) return $this->invalidJsonResponse();
  2199. return $this->endpointResponse($endpoint->save($id, $userId, $payload));
  2200. } catch (\Throwable $exception) {
  2201. return $this->endpointExceptionResponse($exception);
  2202. }
  2203. }
  2204. /**
  2205. * @Route("/friendly/{id}/participants/{participantId}/handicaps/history", name="next_api_society_friendly_participant_handicaps_history", methods={"GET"}, requirements={"id"="\d+", "participantId"="\d+"})
  2206. */
  2207. public function friendlyParticipantHandicapsHistory(int $id, int $participantId, Request $request, \App\Controller\Api\Society\Friendly\Service\FriendlyParticipantHandicapsEndpoint $endpoint): JsonResponse
  2208. {
  2209. try {
  2210. return $this->endpointResponse($endpoint->history($id, $participantId, (int) $request->attributes->get('resolvedSocietyUserId', 0)));
  2211. } catch (\Throwable $exception) {
  2212. return $this->endpointExceptionResponse($exception);
  2213. }
  2214. }
  2215. /**
  2216. * @Route("/friendly/{id}/participants/handicaps/refresh", name="next_api_society_friendly_participant_handicaps_refresh", methods={"POST"}, requirements={"id"="\d+"})
  2217. */
  2218. public function refreshFriendlyParticipantHandicaps(
  2219. int $id,
  2220. Request $request,
  2221. FriendlyParticipantHandicapsRefreshEndpoint $endpoint
  2222. ): JsonResponse
  2223. {
  2224. try {
  2225. $response = $endpoint->__invoke(
  2226. $id,
  2227. (int)$request->attributes->get('resolvedSocietyUserId', 0)
  2228. );
  2229. } catch (\Throwable $exception) {
  2230. return $this->endpointExceptionResponse($exception);
  2231. }
  2232. return $this->endpointResponse($response, Response::HTTP_OK);
  2233. }
  2234. /**
  2235. * @Route("/friendly/{id}/slots-availables", name="next_api_society_friendly_slots_available", methods={"GET"}, requirements={"id"="\d+"})
  2236. */
  2237. public function friendlySlotsAvailable(int $id, FriendlySlotsAvailableEndpoint $friendlySlotsAvailableEndpoint): JsonResponse
  2238. {
  2239. try {
  2240. $response = $friendlySlotsAvailableEndpoint->__invoke($id);
  2241. } catch (\Throwable $exception) {
  2242. return $this->endpointExceptionResponse($exception);
  2243. }
  2244. return $this->endpointResponse($response, Response::HTTP_OK);
  2245. }
  2246. /**
  2247. * @Route("/friendly/{id}/available-friends", name="next_api_society_friendly_available_friends", methods={"GET"}, requirements={"id"="\d+"})
  2248. */
  2249. public function friendlyAvailableFriends(int $id, Request $request, FriendlyAvailableFriendsEndpoint $friendlyAvailableFriendsEndpoint): JsonResponse
  2250. {
  2251. try {
  2252. $response = $friendlyAvailableFriendsEndpoint->__invoke(
  2253. $id,
  2254. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  2255. $request->query->all()
  2256. );
  2257. } catch (\Throwable $exception) {
  2258. return $this->endpointExceptionResponse($exception);
  2259. }
  2260. return $this->endpointResponse($response, Response::HTTP_OK);
  2261. }
  2262. /**
  2263. * @Route("/friendly/{id}/inscription", name="next_api_society_friendly_inscription", methods={"POST"}, requirements={"id"="\d+"})
  2264. */
  2265. public function friendlyInscription(int $id, Request $request, FriendlyInscriptionEndpoint $friendlyInscriptionEndpoint): JsonResponse
  2266. {
  2267. $payload = $this->parseJsonPayload($request);
  2268. if (null === $payload) {
  2269. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST);
  2270. }
  2271. if (!array_key_exists('userId', $payload) && $request->query->has('userId')) {
  2272. $payload['userId'] = $request->query->get('userId');
  2273. }
  2274. try {
  2275. $response = $friendlyInscriptionEndpoint->__invoke(
  2276. $id,
  2277. (int)$request->attributes->get('resolvedSocietyUserId', 0),
  2278. $payload
  2279. );
  2280. } catch (\Throwable $exception) {
  2281. return $this->endpointExceptionResponse($exception);
  2282. }
  2283. return $this->endpointResponse($response, Response::HTTP_OK);
  2284. }
  2285. /**
  2286. * @param array<string,mixed> $payload
  2287. * @return array<string,mixed>
  2288. */
  2289. private function injectResolvedUserId(Request $request, array $payload): array
  2290. {
  2291. $resolvedUserId = (int) $request->attributes->get('resolvedUserId', 0);
  2292. if ($resolvedUserId <= 0) {
  2293. return $payload;
  2294. }
  2295. $payload['userId'] = $resolvedUserId;
  2296. $resolvedSocietyUserId = (int) $request->attributes->get('resolvedSocietyUserId', 0);
  2297. if ($resolvedSocietyUserId > 0) {
  2298. $payload['societyUserId'] = $resolvedSocietyUserId;
  2299. }
  2300. return $payload;
  2301. }
  2302. /**
  2303. * @param callable():array<string,mixed>|array<int,mixed>|Response $endpoint
  2304. */
  2305. private function runSocietyJsonEndpoint(callable $endpoint, int $successStatusCode = Response::HTTP_OK): JsonResponse|Response
  2306. {
  2307. try {
  2308. $response = $endpoint();
  2309. } catch (ApiEndpointException $exception) {
  2310. return $this->apiExceptionResponse($exception);
  2311. } catch (NextApiSessionException $exception) {
  2312. return $this->sessionExceptionResponse($exception);
  2313. } catch (FirebaseTokenInvalidException) {
  2314. return $this->societyErrorResponse('firebase-token-invalid', Response::HTTP_UNAUTHORIZED, 'Refresh token is invalid.');
  2315. } catch (\InvalidArgumentException $exception) {
  2316. return $this->societyErrorResponse('invalid-request', Response::HTTP_BAD_REQUEST, $exception->getMessage());
  2317. } catch (\Throwable $exception) {
  2318. $this->societyExceptionLogger->critical($exception);
  2319. return $this->societyErrorResponse('internal-error', Response::HTTP_INTERNAL_SERVER_ERROR, 'Unable to process request.', $exception->getMessage());
  2320. }
  2321. return $this->endpointResponse($response, $successStatusCode);
  2322. }
  2323. private function endpointResponse(mixed $response, int $successStatusCode = Response::HTTP_OK): JsonResponse|Response
  2324. {
  2325. if ($response instanceof Response) {
  2326. return $response;
  2327. }
  2328. if (is_array($response) && isset($response['_statusCode'])) {
  2329. $successStatusCode = (int) $response['_statusCode'];
  2330. unset($response['_statusCode']);
  2331. }
  2332. return $this->json($response, $successStatusCode);
  2333. }
  2334. private function endpointExceptionResponse(\Throwable $exception): JsonResponse
  2335. {
  2336. if ($exception instanceof \App\Controller\Api\Society\Friendly\Data\CustomHandicapModeChangedException) {
  2337. return $this->json(['error' => 'CUSTOM_HANDICAP_MODE_CHANGED', 'message' => $exception->getMessage(), 'customHandicapEnabled' => $exception->friendly->isCustomHandicapEnabled(), 'customHandicapVersion' => $exception->friendly->getCustomHandicapVersion()], 409);
  2338. }
  2339. if ($exception instanceof ApiEndpointException) {
  2340. return $this->apiExceptionResponse($exception);
  2341. }
  2342. if ($exception instanceof \InvalidArgumentException) {
  2343. return $this->societyErrorResponse('invalid-request', Response::HTTP_BAD_REQUEST, $exception->getMessage());
  2344. }
  2345. $this->societyExceptionLogger->critical($exception);
  2346. return $this->societyErrorResponse('internal-error', Response::HTTP_INTERNAL_SERVER_ERROR);
  2347. }
  2348. private function apiExceptionResponse(ApiEndpointException $exception): JsonResponse
  2349. {
  2350. return $this->societyErrorResponse($exception->errorCode(), $exception->statusCode(), $exception->getMessage());
  2351. }
  2352. private function invalidJsonResponse(): JsonResponse
  2353. {
  2354. return $this->societyErrorResponse('invalid-json', Response::HTTP_BAD_REQUEST, 'Invalid JSON payload.');
  2355. }
  2356. private function sessionExceptionResponse(NextApiSessionException $exception): JsonResponse
  2357. {
  2358. $this->societyExceptionLogger->controlledResponse(
  2359. '' !== $exception->errorCode() ? $exception->errorCode() : 'session-error',
  2360. $exception->statusCode(),
  2361. $exception->getMessage()
  2362. );
  2363. $response = [
  2364. 'error' => $exception->getMessage(),
  2365. ];
  2366. if ('' !== $exception->errorCode()) {
  2367. $response['code'] = $exception->errorCode();
  2368. }
  2369. return $this->json($response, $exception->statusCode());
  2370. }
  2371. private function societyErrorResponse(string $errorCode, int $statusCode, string $fallbackMessage = ''): JsonResponse
  2372. {
  2373. $message = $this->societyErrorMessageTranslator->translate($errorCode, '' !== $fallbackMessage ? $fallbackMessage : $errorCode);
  2374. $this->societyExceptionLogger->controlledResponse($errorCode, $statusCode, $message);
  2375. return $this->json([
  2376. 'error' => $errorCode,
  2377. 'message' => $message,
  2378. ], $statusCode);
  2379. }
  2380. /**
  2381. * @return array<string,mixed>|null
  2382. */
  2383. private function parseJsonPayload(Request $request): ?array
  2384. {
  2385. $content = trim((string)$request->getContent());
  2386. if ('' === $content) {
  2387. return [];
  2388. }
  2389. $payload = json_decode($content, true);
  2390. return is_array($payload) ? $payload : null;
  2391. }
  2392. }