diff --git a/config/services.yaml b/config/services.yaml index fea61ad6..858e5ebb 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -38,6 +38,10 @@ parameters: composer_home_dir: '%env(resolve:APP_COMPOSER_HOME)%' mirror_repos_meta_dir: '%composer_home_dir%/proxy-meta' mirror_repos_dist_dir: '%composer_home_dir%/proxy-dist' + + package_name_regex: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+' + package_name_regex_v2: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.~-]+' + package_name_regex_v1: '[A-Za-z0-9_.-]+/[A-Za-z0-9_.$-]+' # package$hash services: # default configuration for services in *this* file diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php index adaaa8d2..78a44a4d 100644 --- a/src/Controller/ApiController.php +++ b/src/Controller/ApiController.php @@ -5,6 +5,7 @@ namespace Packeton\Controller; use Doctrine\Persistence\ManagerRegistry; +use Packeton\Attribute\Vars; use Packeton\Entity\Package; use Packeton\Entity\User; use Packeton\Entity\Webhook; @@ -21,6 +22,7 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Validator\Validator\ValidatorInterface; +#[Route(defaults: ['_format' => 'json'])] class ApiController extends AbstractController { use ControllerTrait; @@ -32,12 +34,8 @@ public function __construct( protected ValidatorInterface $validator, ){} - /** - * @Route("/api/create-package", name="generic_create", defaults={"_format" = "json"}, methods={"POST"}) - * - * {@inheritdoc} - */ - public function createPackageAction(Request $request) + #[Route('/api/create-package', name: 'generic_create', methods: ['POST'])] + public function createPackageAction(Request $request): Response { $payload = $this->getJsonPayload($request); @@ -53,7 +51,7 @@ public function createPackageAction(Request $request) $package->setRepository($url); $this->container->get(PackageManager::class)->updatePackageUrl($package); $errors = $this->validator->validate($package, null, ['Create']); - if (count($errors) > 0) { + if (\count($errors) > 0) { $errorArray = []; foreach ($errors as $error) { $errorArray[$error->getPropertyPath()] = $error->getMessage(); @@ -73,32 +71,31 @@ public function createPackageAction(Request $request) return new JsonResponse(['status' => 'success'], 202); } - /** - * @Route("/api/update-package", name="generic_postreceive", defaults={"_format" = "json"}) - * @Route("/api/github", name="github_postreceive", defaults={"_format" = "json"}) - * @Route("/api/bitbucket", name="bitbucket_postreceive", defaults={"_format" = "json"}) - * - * {@inheritdoc} - */ - public function updatePackageAction(Request $request) + #[Route('/api/github', name: 'github_postreceive')] + #[Route('/api/bitbucket', name: 'bitbucket_postreceive')] + #[Route('/api/update-package', name: 'generic_postreceive')] + #[Route('/api/update-package/{name}', name: 'generic_named_postreceive', requirements: ['name' => '%package_name_regex%'])] + public function updatePackageAction(Request $request, #[Vars] Package $package = null): Response { // parse the payload $payload = $this->getJsonPayload($request); - if (!$payload && !$request->get('composer_package_name')) { + if (!$payload && !$request->get('composer_package_name') && null === $package) { return new JsonResponse(['status' => 'error', 'message' => 'Missing payload parameter'], 406); } - $packages = []; + $packages = [$package]; // Get from query parameter. if ($packageNames = $request->get('composer_package_name')) { - $packageNames = explode(',', $packageNames); + $packageNames = \explode(',', $packageNames); $repo = $this->registry->getRepository(Package::class); foreach ($packageNames as $packageName) { - $packages = array_merge($packages, $repo->findBy(['name' => $packageName])); + $packages = \array_merge($packages, $repo->findBy(['name' => $packageName])); } } + $packages = \array_values(\array_filter($packages)); + if (isset($payload['project']['git_http_url'])) { // gitlab event payload $urlRegex = '{^(?:ssh://git@|https?://|git://|git@)?(?P[a-z0-9.-]+)(?::[0-9]+/|[:/])(?P[\w.-]+(?:/[\w.-]+?)+)(?:\.git|/)?$}i'; $url = $payload['project']['git_http_url']; @@ -108,7 +105,7 @@ public function updatePackageAction(Request $request) } elseif (isset($payload['repository']['url'])) { // github/anything hook $urlRegex = '{^(?:ssh://git@|https?://|git://|git@)?(?P[a-z0-9.-]+)(?::[0-9]+/|[:/])(?P[\w.-]+(?:/[\w.-]+?)+)(?:\.git|/)?$}i'; $url = $payload['repository']['url']; - $url = str_replace('https://api.github.com/repos', 'https://github.com', $url); + $url = \str_replace('https://api.github.com/repos', 'https://github.com', $url); } elseif (isset($payload['repository']['links']['html']['href'])) { // bitbucket push event payload $urlRegex = '{^(?:https?://|git://|git@)?(?:api\.)?(?Pbitbucket\.org)[/:](?P[\w.-]+/[\w.-]+?)(\.git)?/?$}i'; $url = $payload['repository']['links']['html']['href']; @@ -129,7 +126,7 @@ public function updatePackageAction(Request $request) $packageNames = (array) $payload['composer']['package_name']; $repo = $this->registry->getRepository(Package::class); foreach ($packageNames as $packageName) { - $packages = array_merge($packages, $repo->findBy(['name' => $packageName])); + $packages = \array_merge($packages, $repo->findBy(['name' => $packageName])); } } elseif (empty($packages)) { return new JsonResponse(['status' => 'error', 'message' => 'Missing or invalid payload'], 406); @@ -147,17 +144,9 @@ public function updatePackageAction(Request $request) return $this->receivePost($request, $url, $urlRegex); } - /** - * @Route( - * "/api/packages/{package}", - * name="api_edit_package", - * requirements={"package"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"}, - * defaults={"_format" = "json"}, - * methods={"PUT"} - * ) - * {@inheritDoc} - */ - public function editPackageAction(Request $request, Package $package) + + #[Route('/api/packages/{name}', name: 'api_edit_package', requirements: ['name' => '%package_name_regex%'], methods: ['PUT'])] + public function editPackageAction(Request $request, #[Vars] Package $package): Response { $user = $this->getUser(); if (!$package->getMaintainers()->contains($user) && !$this->isGranted('ROLE_EDIT_PACKAGES')) { @@ -169,7 +158,7 @@ public function editPackageAction(Request $request, Package $package) $package->setRepository($payload['repository']); $this->container->get(PackageManager::class)->updatePackageUrl($package); $errors = $this->validator->validate($package, null, ["Update"]); - if (count($errors) > 0) { + if (\count($errors) > 0) { $errorArray = []; foreach ($errors as $error) { $errorArray[$error->getPropertyPath()] = $error->getMessage(); @@ -186,11 +175,9 @@ public function editPackageAction(Request $request, Package $package) return new JsonResponse(['status' => 'success'], 200); } - /** - * @Route("/downloads/{name}", name="track_download", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, defaults={"_format" = "json"}, methods={"POST"}) - * @inheritDoc - */ - public function trackDownloadAction(Request $request, $name) + + #[Route('/downloads/{name}', name: 'track_download', requirements: ['name' => '%package_name_regex%'], methods: ['POST'])] + public function trackDownloadAction(Request $request, $name): Response { $result = $this->getPackageAndVersionId($name, $request->request->get('version_normalized')); @@ -203,11 +190,9 @@ public function trackDownloadAction(Request $request, $name) return new JsonResponse(['status' => 'success'], 201); } - /** - * @Route("/jobs/{id}", name="get_job", requirements={"id"="[a-f0-9]+"}, defaults={"_format" = "json"}, methods={"GET"}) - * @inheritDoc - */ - public function getJobAction(string $id) + + #[Route('/jobs/{id}', name: 'get_job', requirements: ['id' => '[a-f0-9]+'], methods: ['GET'])] + public function getJobAction(string $id): Response { return new JsonResponse($this->container->get(Scheduler::class)->getJobStatus($id), 200); } @@ -223,13 +208,12 @@ public function getJobAction(string $id) * } * * The version must be the normalized one - * - * @Route("/downloads/", name="track_download_batch", defaults={"_format" = "json"}, methods={"POST"}) * @inheritDoc */ - public function trackDownloadsAction(Request $request) + #[Route('/downloads/', name: 'track_download_batch', methods: ['POST'])] + public function trackDownloadsAction(Request $request): Response { - $contents = json_decode($request->getContent(), true); + $contents = \json_decode($request->getContent(), true); if (empty($contents['downloads']) || !is_array($contents['downloads'])) { return new JsonResponse(['status' => 'error', 'message' => 'Invalid request format, must be a json object containing a downloads key filled with an array of name/version objects'], 200); } @@ -257,23 +241,14 @@ public function trackDownloadsAction(Request $request) return new JsonResponse(['status' => 'success'], 201); } - /** - * @Route("/api/webhook-invoke/{name}", name="generic_webhook_invoke", defaults={"_format" = "json", "name" = "default"}) - * - * {@inheritdoc} - */ - public function notifyWebhookAction($name, Request $request) + + #[Route('/api/webhook-invoke/{name}', name: 'generic_webhook_invoke', defaults: ['name' => 'default'], methods: ['POST'])] + public function notifyWebhookAction($name, Request $request): Response { - $payload = array_merge($request->request->all(), $request->query->all()); + $payload = \array_merge($request->request->all(), $request->query->all()); unset($payload['token']); - // Always try to decode json - if ($content = $request->getContent()) { - $content = @json_decode($content, true); - if (is_array($content)) { - $payload = array_merge($payload, $content); - } - } + $payload = $payload + ($this->getJsonPayload($request) ?: []); $context = [ 'event' => Webhook::HOOK_HTTP_REQUEST, @@ -291,7 +266,7 @@ public function notifyWebhookAction($name, Request $request) $jobs[] = $bus->dispatch($context, $webhook)->getId(); } - return new JsonResponse(['status' => 'success', 'jobs' => $jobs], count($jobs) === 0 ? 200 : 202); + return new JsonResponse(['status' => 'success', 'jobs' => $jobs], \count($jobs) === 0 ? 200 : 202); } /** @@ -308,18 +283,18 @@ protected function getPackageAndVersionId($name, $version) WHERE p.name = ? AND v.normalizedVersion = ? LIMIT 1', - array($name, $version) + [$name, $version] ); } - protected function getJsonPayload(Request $request) + protected function getJsonPayload(Request $request): ?array { - $payload = $request->request->get('payload') ? json_decode($request->request->get('payload'), true) : null; + $payload = $request->request->get('payload') ? \json_decode($request->request->get('payload'), true) : null; if (!$payload and $content = $request->getContent()) { - $payload = @json_decode($content, true); + $payload = @\json_decode($content, true); } - return $payload ?: null; + return \is_array($payload) ? $payload : null; } /** @@ -333,8 +308,8 @@ protected function getJsonPayload(Request $request) protected function receivePost(Request $request, $url, $urlRegex) { // try to parse the URL first to avoid the DB lookup on malformed requests - if (!preg_match($urlRegex, $url)) { - return new Response(json_encode(['status' => 'error', 'message' => 'Could not parse payload repository URL']), 406); + if (!\preg_match($urlRegex, $url)) { + return new Response(\json_encode(['status' => 'error', 'message' => 'Could not parse payload repository URL']), 406); } // try to find the all package @@ -350,7 +325,7 @@ protected function receivePost(Request $request, $url, $urlRegex) protected function schedulePostJobs(array $packages) { if (!$packages) { - return new Response(json_encode(['status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)']), 404); + return new Response(\json_encode(['status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)']), 404); } $jobs = []; @@ -375,16 +350,16 @@ protected function schedulePostJobs(array $packages) */ protected function findPackagesByUrl($url, $urlRegex) { - if (!preg_match($urlRegex, $url, $matched)) { + if (!\preg_match($urlRegex, $url, $matched)) { return []; } $packages = []; $repo = $this->registry->getRepository(Package::class); foreach ($repo->findAll() as $package) { - if (preg_match($urlRegex, $package->getRepository(), $candidate) - && strtolower($candidate['host']) === strtolower($matched['host']) - && strtolower($candidate['path']) === strtolower($matched['path']) + if (\preg_match($urlRegex, $package->getRepository(), $candidate) + && \strtolower($candidate['host']) === \strtolower($matched['host']) + && \strtolower($candidate['path']) === \strtolower($matched['path']) ) { $packages[] = $package; } @@ -398,7 +373,7 @@ protected function findPackagesByUrl($url, $urlRegex) */ public static function getSubscribedServices(): array { - return array_merge( + return \array_merge( parent::getSubscribedServices(), [ PackageManager::class, diff --git a/src/Controller/ApiDocController.php b/src/Controller/ApiDocController.php index 03bde549..db9071a8 100644 --- a/src/Controller/ApiDocController.php +++ b/src/Controller/ApiDocController.php @@ -15,6 +15,7 @@ use Doctrine\Persistence\ManagerRegistry; use Packeton\Entity\Version; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; /** @@ -26,10 +27,8 @@ public function __construct( protected ManagerRegistry $registry ){} - /** - * @Route("/apidoc", name="api_doc") - */ - public function indexAction() + #[Route('/apidoc', name: 'api_doc')] + public function indexAction(): Response { $qb = $this->registry->getRepository(Version::class) ->createQueryBuilder('v'); @@ -41,7 +40,7 @@ public function indexAction() try { $examplePackage = $qb->getQuery()->getSingleScalarResult(); - } catch (\Exception $exception) { + } catch (\Exception) { $examplePackage = 'monolog/monolog'; } diff --git a/src/Controller/ControllerTrait.php b/src/Controller/ControllerTrait.php index 86585c6e..9ec5a440 100644 --- a/src/Controller/ControllerTrait.php +++ b/src/Controller/ControllerTrait.php @@ -18,7 +18,7 @@ protected function getEM() protected function getPackagesMetadata($packages) { $ids = []; - if (!count($packages)) { + if (!\count($packages)) { return []; } @@ -28,7 +28,7 @@ protected function getPackagesMetadata($packages) if ($package instanceof Package) { $ids[] = $package->getId(); $favs[$package->getId()] = $this->favoriteManager->getFaverCount($package); - } elseif (is_array($package)) { + } elseif (\is_array($package)) { $solarium = true; $ids[] = $package['id']; } else { diff --git a/src/Controller/ExploreController.php b/src/Controller/ExploreController.php index 63e6d6ab..ca7228a2 100644 --- a/src/Controller/ExploreController.php +++ b/src/Controller/ExploreController.php @@ -22,14 +22,13 @@ use Pagerfanta\Adapter\FixedAdapter; use Pagerfanta\Pagerfanta; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -/** - * @Route("/explore") - */ +#[Route('/explore')] class ExploreController extends AbstractController { use ControllerTrait; @@ -40,10 +39,8 @@ public function __construct( protected FavoriteManager $favoriteManager, ) {} - /** - * @Route("", name="browse") - */ - public function exploreAction(\Redis $redis) + #[Route('', name: 'browse')] + public function exploreAction(\Redis $redis): Response { /** @var PackageRepository $pkgRepo */ $pkgRepo = $this->registry->getRepository(Package::class); @@ -80,10 +77,9 @@ public function exploreAction(\Redis $redis) ]); } - /** - * @Route("/popular.{_format}", name="browse_popular", defaults={"_format"="html"}) - */ - public function popularAction(Request $req, \Redis $redis) + + #[Route('popular.{_format}', name: 'browse_popular', defaults: ['_format' => 'html'])] + public function popularAction(Request $req, \Redis $redis): Response { $perPage = $req->query->getInt('per_page', 15); if ($perPage <= 0 || $perPage > 100) { diff --git a/src/Controller/FeedController.php b/src/Controller/FeedController.php index 34a2e709..b319ef5e 100644 --- a/src/Controller/FeedController.php +++ b/src/Controller/FeedController.php @@ -26,32 +26,22 @@ /** * @author Rafael Dohms - * - * @Route("/feeds") */ +#[Route('/feeds')] class FeedController extends AbstractController { public function __construct( protected ManagerRegistry $registry ){} - /** - * @Route("/", name="feeds") - */ - public function feedsAction() + #[Route('/', name: 'feeds')] + public function feedsAction(): Response { return $this->render('feed/feeds.html.twig'); } - /** - * @Route( - * "/packages.{_format}", - * name="feed_packages", - * methods={"GET"}, - * requirements={"_format"="(rss|atom)"} - * ) - */ - public function packagesAction(Request $req) + #[Route('/packages.{_format}', name: 'feed_packages', requirements: ['_format' => '(rss|atom)'], methods: ['GET'])] + public function packagesAction(Request $req): Response { $repo = $this->registry->getRepository(Package::class); $packages = $this->getLimitedResults( @@ -69,15 +59,8 @@ public function packagesAction(Request $req) return $this->buildResponse($req, $feed); } - /** - * @Route( - * "/releases.{_format}", - * name="feed_releases", - * methods={"GET"}, - * requirements={"_format"="(rss|atom)"} - * ) - */ - public function releasesAction(Request $req) + #[Route('/releases.{_format}', name: 'feed_releases', requirements: ['_format' => '(rss|atom)'], methods: ['GET'])] + public function releasesAction(Request $req): Response { $repo = $this->registry->getRepository(Version::class); $packages = $this->getLimitedResults( @@ -95,14 +78,12 @@ public function releasesAction(Request $req) return $this->buildResponse($req, $feed); } - /** - * @Route( - * "/vendor.{vendor}.{_format}", - * name="feed_vendor", - * methods={"GET"}, - * requirements={"_format"="(rss|atom)", "vendor"="[A-Za-z0-9_.-]+"} - * ) - */ + #[Route( + '/vendor.{vendor}.{_format}', + name: 'feed_vendor', + requirements: ['_format' => '(rss|atom)', 'vendor' => '[A-Za-z0-9_.-]+'], + methods: ['GET'] + )] public function vendorAction(Request $req, $vendor) { $repo = $this->registry->getRepository(Version::class); @@ -121,14 +102,12 @@ public function vendorAction(Request $req, $vendor) return $this->buildResponse($req, $feed); } - /** - * @Route( - * "/package.{package}.{_format}", - * name="feed_package", - * methods={"GET"}, - * requirements={"_format"="(rss|atom)", "package"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"} - * ) - */ + #[Route( + '/package.{package}.{_format}', + name: 'feed_package', + requirements: ['_format' => '(rss|atom)', 'package' => '%package_name_regex%'], + methods: ['GET'] + )] public function packageAction(Request $req, $package) { $repo = $this->registry->getRepository(Version::class); diff --git a/src/Controller/GroupController.php b/src/Controller/GroupController.php index c62b142e..5a161ec4 100644 --- a/src/Controller/GroupController.php +++ b/src/Controller/GroupController.php @@ -20,15 +20,11 @@ class GroupController extends AbstractController { public function __construct( protected ManagerRegistry $registry - ){} - - /** - * @Route("/groups/", name="groups_index") - * - * @param Request $request - * @return mixed - */ - public function indexAction(Request $request) + ){ + } + + #[Route('/groups', name: 'groups_index')] + public function indexAction(Request $request): Response { $page = $request->query->get('page', 1); $qb = $this->registry->getRepository(Group::class) @@ -47,13 +43,8 @@ public function indexAction(Request $request) ]); } - /** - * @Route("/groups/create", name="groups_create") - * - * @param Request $request - * @return mixed - */ - public function createAction(Request $request) + #[Route('/groups/create', name: 'groups_create')] + public function createAction(Request $request): Response { $group = new Group(); $data = $this->handleUpdate($request, $group, 'Group has been saved successfully'); @@ -61,28 +52,16 @@ public function createAction(Request $request) return $data instanceof Response ? $data : $this->render('group/update.html.twig', $data); } - /** - * @Route("/groups/{id}/update", name="groups_update") - * - * @param Group $group - * @param Request $request - * @return mixed - */ - public function updateAction(Request $request, #[Vars] Group $group) + #[Route('/groups/{id}/update', name: 'groups_update')] + public function updateAction(Request $request, #[Vars] Group $group): Response { $data = $this->handleUpdate($request, $group, 'Group has been saved successfully'); return $data instanceof Response ? $data : $this->render('group/update.html.twig', $data); } - /** - * @Route("/groups/{id}/delete", name="groups_delete") - * - * @param Group $group - * @param Request $request - * @return mixed - */ - public function deleteAction(Request $request, #[Vars] Group $group) + #[Route('/groups/{id}/delete', name: 'groups_delete')] + public function deleteAction(Request $request, #[Vars] Group $group): Response { $form = $this->createFormBuilder([])->getForm(); $form->submit($request->get('form')); diff --git a/src/Controller/MirrorController.php b/src/Controller/MirrorController.php index a7339953..a4d48570 100644 --- a/src/Controller/MirrorController.php +++ b/src/Controller/MirrorController.php @@ -35,7 +35,7 @@ public function rootAction(Request $request, string $alias): Response return $this->renderMetadata($metadata, $request); } - #[Route('/{alias}/p2/{package}.json', name: 'mirror_metadata_v2', requirements: ['package' => '[A-Za-z0-9_.-]+/[A-Za-z0-9_.~-]+'], methods: ['GET'])] + #[Route('/{alias}/p2/{package}.json', name: 'mirror_metadata_v2', requirements: ['package' => '%package_name_regex_v2%'], methods: ['GET'])] public function metadataV2Action(string $package, string $alias, Request $request): Response { $devStability = \str_ends_with($package, '~dev'); @@ -48,7 +48,7 @@ public function metadataV2Action(string $package, string $alias, Request $reques return $this->renderMetadata($metadata, $request); } - #[Route('/{alias}/pkg/{package}.json', name: 'mirror_metadata_v1', requirements: ['package' => '[A-Za-z0-9_.-]+/[A-Za-z0-9_.$-]+'], methods: ['GET'])] + #[Route('/{alias}/pkg/{package}.json', name: 'mirror_metadata_v1', requirements: ['package' => '%package_name_regex_v1%'], methods: ['GET'])] public function packageAction(string $package, string $alias, Request $request): Response { $metadata = $this->wrap404Error($alias, fn (PRI $repo) => $repo->findPackageMetadata($package)); diff --git a/src/Controller/PackageController.php b/src/Controller/PackageController.php index 4db29b18..69688d5d 100644 --- a/src/Controller/PackageController.php +++ b/src/Controller/PackageController.php @@ -47,20 +47,17 @@ public function __construct( protected FavoriteManager $favoriteManager, protected ProviderManager $providerManager, protected LoggerInterface $logger, - ){} + ){ + } - /** - * @Route("/packages/", name="all_packages") - */ - public function allAction(Request $req) + #[Route('/packages/', name: 'all_packages')] + public function allAction(Request $req): Response { return new RedirectResponse($this->generateUrl('browse'), Response::HTTP_MOVED_PERMANENTLY); } - /** - * @Route("/packages/list.json", name="list", defaults={"_format"="json"}, methods={"GET"}) - */ - public function listAction(Request $req) + #[Route('/packages/list.json', name: 'list', defaults: ['_format' => 'json'], methods: ['GET'])] + public function listAction(Request $req): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; @@ -107,10 +104,8 @@ public function listAction(Request $req) return new JsonResponse(['packageNames' => $names]); } - /** - * @Route("/packages/submit", name="submit") - */ - public function submitPackageAction(Request $req) + #[Route('/packages/submit', name: 'submit')] + public function submitPackageAction(Request $req): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException(); @@ -149,11 +144,8 @@ public function submitPackageAction(Request $req) ); } - /** - * @Route("/packages/fetch-info", name="submit.fetch_info", defaults={"_format"="json"}) - * {@inheritdoc} - */ - public function fetchInfoAction(Request $req) + #[Route('/packages/fetch-info', name: 'submit.fetch_info', defaults: ['_format' => 'json'])] + public function fetchInfoAction(Request $req): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -210,9 +202,7 @@ public function fetchInfoAction(Request $req) return new JsonResponse(['status' => 'error', 'reason' => 'No data posted.']); } - /** - * @Route("/packages/{vendor}/", name="view_vendor", requirements={"vendor"="[A-Za-z0-9_.-]+"}) - */ + #[Route('/packages/{vendor}/', name: 'view_vendor', requirements: ['vendor' => '[A-Za-z0-9_.-]+'])] public function viewVendorAction($vendor) { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { @@ -237,16 +227,9 @@ public function viewVendorAction($vendor) ]); } - /** - * @Route( - * "/providers/{name}", - * name="view_providers", - * requirements={"name"="[A-Za-z0-9/_.-]+?"}, - * defaults={"_format"="html"}, - * methods={"GET"} - * ) - */ - public function viewProvidersAction($name, \Redis $redis) + + #[Route('/providers/{name}/', name: 'view_providers', requirements: ['name' => '[A-Za-z0-9/_.-]+?'], defaults: ['_format' => 'html'], methods: ['GET'])] + public function viewProvidersAction($name, \Redis $redis): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -284,16 +267,9 @@ public function viewProvidersAction($name, \Redis $redis) ]); } - /** - * @Route( - * "/packages/{name}.{_format}", - * name="view_package", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "_format"="(json)"}, - * defaults={"_format"="html"}, - * methods={"GET"} - * ) - */ - public function viewPackageAction(Request $req, $name, CsrfTokenManagerInterface $csrfTokenManager) + + #[Route('/packages/{name}.{_format}', name: 'view_package', requirements: ['name' => '%package_name_regex%', '_format' => '(json)'], defaults: ['_format' => 'html'], methods: ['GET'])] + public function viewPackageAction(Request $req, $name, CsrfTokenManagerInterface $csrfTokenManager): Response { if (preg_match('{^(?Pext-[a-z0-9_.-]+?)/(?Pdependents|suggesters)$}i', $name, $match)) { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { @@ -396,19 +372,9 @@ public function viewPackageAction(Request $req, $name, CsrfTokenManagerInterface return $this->render('package/viewPackage.html.twig', $data); } - /** - * @Route( - * "/packages/{package}/changelog", - * requirements={"package"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"}, - * name="package_changelog", - * methods={"GET"} - * ) - * - * @param string $package - * @param Request $request - * @return Response - */ - public function changelogAction($package, Request $request) + + #[Route('/packages/{package}/changelog', name: 'package_changelog', requirements: ['name' => '%package_name_regex%'], methods: ['GET'])] + public function changelogAction($package, Request $request): Response { if (!$this->isGranted('ROLE_MAINTAINER', $package)) { return new JsonResponse(['error' => 'Access denied'], 403); @@ -450,15 +416,9 @@ public function changelogAction($package, Request $request) ); } - /** - * @Route( - * "/packages/{name}/downloads.{_format}", - * name="package_downloads_full", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "_format"="(json)"}, - * methods={"GET"} - * ) - */ - public function viewPackageDownloadsAction(Request $req, $name) + + #[Route('/packages/{name}/downloads.{_format}', name: 'package_downloads_full', requirements: ['name' => '%package_name_regex%', '_format' => '(json)'], methods: ['GET'])] + public function viewPackageDownloadsAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedHttpException(); @@ -500,15 +460,9 @@ public function viewPackageDownloadsAction(Request $req, $name) return $response; } - /** - * @Route( - * "/versions/{versionId}.{_format}", - * name="view_version", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "versionId"="[0-9]+", "_format"="(json)"}, - * methods={"GET"} - * ) - */ - public function viewPackageVersionAction(Request $req, $versionId) + + #[Route('/versions/{versionId}.{_format}', name: 'view_version', requirements: ['name' => '%package_name_regex%', 'versionId' => '[0-9]+', '_format' => '(json)'], methods: ['GET'])] + public function viewPackageVersionAction(Request $req, $versionId): Response { /** @var VersionRepository $repo */ $repo = $this->registry->getRepository(Version::class); @@ -524,17 +478,9 @@ public function viewPackageVersionAction(Request $req, $versionId) return new JsonResponse(['content' => $html]); } - /** - * @Route( - * "/versions/{versionId}/delete", - * name="delete_version", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "versionId"="[0-9]+"}, - * methods={"DELETE"} - * ) - * - * {@inheritdoc} - */ - public function deletePackageVersionAction(Request $req, $versionId) + + #[Route('/versions/{versionId}/delete', name: 'delete_version', requirements: ['name' => '%package_name_regex%', 'versionId' => '[0-9]+', '_format' => '(json)'], methods: ['DELETE'])] + public function deletePackageVersionAction(Request $req, $versionId): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -562,11 +508,9 @@ public function deletePackageVersionAction(Request $req, $versionId) return new Response('', 204); } - /** - * @Route("/packages/{name}", name="update_package", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, defaults={"_format" = "json"}, methods={"PUT"}) - * @inheritDoc - */ - public function updatePackageAction(Request $req, $name) + + #[Route('/packages/{name}', name: 'update_package', requirements: ['name' => '%package_name_regex%', '_format' => 'json'], methods: ['PUT'])] + public function updatePackageAction(Request $req, $name): Response { $doctrine = $this->registry; @@ -621,10 +565,9 @@ public function updatePackageAction(Request $req, $name) return new JsonResponse(['status' => 'error', 'message' => 'Could not find a package that matches this request (does user maintain the package?)',], 404); } - /** - * @Route("/packages/{name}", name="delete_package", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, methods={"DELETE"}) - */ - public function deletePackageAction(Request $req, $name) + + #[Route('/packages/{name}', name: 'delete_package', requirements: ['name' => '%package_name_regex%', '_format' => 'json'], methods: ['DELETE'])] + public function deletePackageAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -656,10 +599,8 @@ public function deletePackageAction(Request $req, $name) return new Response('Invalid form input', 400); } - /** - * @Route("/packages/{name}/maintainers", name="add_maintainer", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}) - */ - public function createMaintainerAction(Request $req, $name) + #[Route('/packages/{name}/maintainers', name: 'add_maintainer', requirements: ['name' => '%package_name_regex%'])] + public function createMaintainerAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -716,10 +657,8 @@ public function createMaintainerAction(Request $req, $name) return $this->render('package/viewPackage.html.twig', $data); } - /** - * @Route("/packages/{name}/maintainers/delete", name="remove_maintainer", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}) - */ - public function removeMaintainerAction(Request $req, $name) + #[Route('/packages/{name}/maintainers/delete', name: 'remove_maintainer', requirements: ['name' => '%package_name_regex%'])] + public function removeMaintainerAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_MAINTAINER')) { throw new AccessDeniedException; @@ -774,14 +713,8 @@ public function removeMaintainerAction(Request $req, $name) return $this->render('package/viewPackage.html.twig', $data); } - /** - * @Route( - * "/packages/{name}/edit", - * name="edit_package", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"} - * ) - */ - public function editAction(Request $req, #[Vars('name')] Package $package) + #[Route('/packages/{name}/edit', name: 'edit_package', requirements: ['name' => '%package_name_regex%'])] + public function editAction(Request $req, #[Vars] Package $package): Response { if (!$package->getMaintainers()->contains($this->getUser()) && !$this->isGranted('ROLE_EDIT_PACKAGES')) { throw new AccessDeniedException; @@ -817,14 +750,8 @@ public function editAction(Request $req, #[Vars('name')] Package $package) ); } - /** - * @Route( - * "/packages/{name}/abandon", - * name="abandon_package", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"} - * ) - */ - public function abandonAction(Request $request, #[Vars] Package $package) + #[Route('/packages/{name}/abandon', name: 'abandon_package', requirements: ['name' => '%package_name_regex%'])] + public function abandonAction(Request $request, #[Vars] Package $package): Response { if (!$package->getMaintainers()->contains($this->getUser()) && !$this->isGranted('ROLE_EDIT_PACKAGES')) { throw new AccessDeniedException; @@ -851,14 +778,8 @@ public function abandonAction(Request $request, #[Vars] Package $package) ]); } - /** - * @Route( - * "/packages/{name}/unabandon", - * name="unabandon_package", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"} - * ) - */ - public function unabandonAction(#[Vars] Package $package) + #[Route('/packages/{name}/unabandon', name: 'unabandon_package', requirements: ['name' => '%package_name_regex%'])] + public function unabandonAction(#[Vars] Package $package): Response { if (!$package->getMaintainers()->contains($this->getUser()) && !$this->isGranted('ROLE_EDIT_PACKAGES')) { throw new AccessDeniedException; @@ -876,15 +797,8 @@ public function unabandonAction(#[Vars] Package $package) return $this->redirect($this->generateUrl('view_package', ['name' => $package->getName()])); } - /** - * @Route( - * "/packages/{name}/stats.{_format}", - * name="view_package_stats", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "_format"="(json)"}, - * defaults={"_format"="html"} - * ) - */ - public function statsAction(Request $req, #[Vars('name')] Package $package) + #[Route('/packages/{name}/stats.{_format}', name: 'view_package_stats', requirements: ['name' => '%package_name_regex%', '_format' => '(json)'], defaults: ['_format' => 'html'])] + public function statsAction(Request $req, #[Vars] Package $package): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; @@ -924,14 +838,12 @@ public function statsAction(Request $req, #[Vars('name')] Package $package) return $this->render('package/stats.html.twig', $data); } - /** - * @Route( - * "/packages/{name}/dependents", - * name="view_package_dependents", - * requirements={"name"="([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?|ext-[A-Za-z0-9_.-]+?)"} - * ) - */ - public function dependentsAction(Request $req, $name) + #[Route( + '/packages/{name}/dependents', + name: 'view_package_dependents', + requirements: ['name' => '([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?|ext-[A-Za-z0-9_.-]+?)'], + )] + public function dependentsAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; @@ -957,14 +869,12 @@ public function dependentsAction(Request $req, $name) return $this->render('package/dependents.html.twig', $data); } - /** - * @Route( - * "/packages/{name}/suggesters", - * name="view_package_suggesters", - * requirements={"name"="([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?|ext-[A-Za-z0-9_.-]+?)"} - * ) - */ - public function suggestersAction(Request $req, $name) + #[Route( + '/packages/{name}/suggesters', + name: 'view_package_suggesters', + requirements: ['name' => '([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?|ext-[A-Za-z0-9_.-]+?)'], + )] + public function suggestersAction(Request $req, $name): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; @@ -990,14 +900,8 @@ public function suggestersAction(Request $req, $name) return $this->render('package/suggesters.html.twig', $data); } - /** - * @Route( - * "/packages/{name}/stats/all.json", - * name="package_stats", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"} - * ) - */ - public function overallStatsAction(Request $req, \Redis $redis, #[Vars('name')] Package $package, Version $version = null) + #[Route('/packages/{name}/stats/all.json', name: 'package_stats', requirements: ['name' => '%package_name_regex%'])] + public function overallStatsAction(Request $req, \Redis $redis, #[Vars] Package $package, Version $version = null): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; @@ -1068,14 +972,12 @@ public function overallStatsAction(Request $req, \Redis $redis, #[Vars('name')] return $response; } - /** - * @Route( - * "/packages/{name}/stats/{version}.json", - * name="version_stats", - * requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "version"=".+?"} - * ) - */ - public function versionStatsAction(\Redis $redis, Request $req, #[Vars('name')] Package $package, $version) + #[Route( + '/packages/{name}/stats/{version}.json', + name: 'version_stats', + requirements: ['name' => '%package_name_regex%', 'version' => '.+?']) + ] + public function versionStatsAction(\Redis $redis, Request $req, #[Vars('name')] Package $package, $version): Response { if (!$this->isGranted('ROLE_FULL_CUSTOMER')) { throw new AccessDeniedException; diff --git a/src/Controller/ProviderController.php b/src/Controller/ProviderController.php index 05e65694..01a55e01 100644 --- a/src/Controller/ProviderController.php +++ b/src/Controller/ProviderController.php @@ -1,5 +1,7 @@ 'json'], methods: ['GET'])] + public function packagesAction(): Response { $rootPackages = $this->packageManager->getRootPackagesJson($this->getUser()); - return new JsonResponse($rootPackages); + $response = new JsonResponse($rootPackages); + $response->setEncodingOptions(\JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT); + + return $response; } - /** - * @Route( - * "/p/providers${hash}.json", - * requirements={"hash"="[a-f0-9]+"}, - * name="root_providers", defaults={"_format" = "json"}, - * methods={"GET"} - * ) - * - * @param string $hash - * @return Response - */ - public function providersAction($hash) + #[Route('/p/providers${hash}.json', name: 'root_providers', requirements: ['hash' => '[a-f0-9]+'], defaults: ['_format' => 'json'], methods: ['GET'])] + public function providersAction($hash): Response { $providers = $this->packageManager->getProvidersJson($this->getUser(), $hash); if (!$providers) { @@ -59,10 +53,9 @@ public function providersAction($hash) /** * Copy from Packagist. Can be used for https://workers.cloudflare.com sync mirrors. * Used two unix format: Packagist and RFC-3399 - * - * @Route("/metadata/changes.json", name="metadata_changes", methods={"GET"}) */ - public function metadataChangesAction(Request $request) + #[Route('/metadata/changes.json', name: 'metadata_changes', defaults: ['_format' => 'json'], methods: ['GET'])] + public function metadataChangesAction(Request $request): Response { $now = time() * 10000; $since = $request->query->getInt('since'); @@ -88,18 +81,14 @@ public function metadataChangesAction(Request $request) return new JsonResponse(['actions' => array_merge($updatesDev, $updatesStab), 'timestamp' => $now]); } - /** - * @Route( - * "/p/{package}.json", - * requirements={"package"="[\w+\/\-\$]+"}, - * name="root_package", defaults={"_format" = "json"}, - * methods={"GET"} - * ) - * - * @param string $package - * @return Response - */ - public function packageAction(string $package) + #[Route( + '/p/{package}.json', + name: 'root_package', + requirements: ['package' => '%package_name_regex_v1%'], + defaults: ['_format' => 'json'], + methods: ['GET'] + )] + public function packageAction(string $package): Response { $package = \explode('$', $package); if (\count($package) !== 2) { @@ -118,15 +107,14 @@ public function packageAction(string $package) return new JsonResponse($package); } - /** - * @Route( - * "/p2/{package}.json", - * requirements={"package"="[\w+\/\-\~]+"}, - * name="root_package_v2", defaults={"_format" = "json"}, - * methods={"GET"} - * ) - */ - public function packageV2Action(Request $request, string $package) + #[Route( + '/p2/{package}.json', + name: 'root_package_v2', + requirements: ['package' => '%package_name_regex_v2%'], + defaults: ['_format' => 'json'], + methods: ['GET'] + )] + public function packageV2Action(Request $request, string $package): Response { $isDev = str_ends_with($package, '~dev'); $package = preg_replace('/~dev$/', '', $package); @@ -139,19 +127,18 @@ public function packageV2Action(Request $request, string $package) $response = new JsonResponse($package); $response->setLastModified(new \DateTime($lastModified)); $response->isNotModified($request); + $response->setEncodingOptions(\JSON_UNESCAPED_SLASHES); return $response; } - /** - * @Route( - * "/zipball/{package}/{hash}", - * name="download_dist_package", - * requirements={"package"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "hash"="[a-f0-9]{40}\.[a-z]+?"}, - * methods={"GET"} - * ) - */ - public function zipballAction(#[Vars('name')] Package $package, $hash) + #[Route( + '/zipball/{package}/{hash}', + name: 'download_dist_package', + requirements: ['package' => '%package_name_regex%', 'hash' => '[a-f0-9]{40}\.[a-z]+?'], + methods: ['GET'] + )] + public function zipballAction(#[Vars('name')] Package $package, $hash): Response { $distManager = $this->container->get(DistManager::class); if (false === \preg_match('{[a-f0-9]{40}}i', $hash, $match) or !($reference = $match[0])) { @@ -183,7 +170,7 @@ public function zipballAction(#[Vars('name')] Package $package, $hash) return $this->createNotFound(); } - protected function createNotFound(?string $msg = null) + protected function createNotFound(?string $msg = null): Response { return new JsonResponse(['status' => 'error', 'message' => $msg ?: 'Not Found'], 404); } diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index fcded004..fbf34f6d 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -6,16 +6,15 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; class SecurityController extends AbstractController { - /** - * @Route("/login", name="login") - */ - public function loginAction(AuthenticationUtils $authenticationUtils) + #[Route('/login', name: 'login')] + public function loginAction(AuthenticationUtils $authenticationUtils): Response { $error = $authenticationUtils->getLastAuthenticationError(); $lastUsername = $authenticationUtils->getLastUsername(); @@ -26,17 +25,13 @@ public function loginAction(AuthenticationUtils $authenticationUtils) ]); } - /** - * @Route("/reset-password", name="request_pwd_reset") - */ - public function request(Request $request, MailerInterface $mailer, \Redis $redis) + #[Route('/reset-password', name: 'request_pwd_reset')] + public function request(Request $request, MailerInterface $mailer) { throw new \LogicException('reset-password not supported, please contact to admin'); } - /** - * @Route("/logout", name="logout") - */ + #[Route('/logout', name: 'logout')] public function logout() { throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.'); diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 9cf1beb2..81d0eb6f 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -1,5 +1,7 @@ getUser() instanceof User ? $this->getUserPackages($request, $this->getUser()) : []; @@ -68,11 +68,8 @@ public function showAction(Request $request) ]); } - /** - * Show the user. - * @Route("/profile/edit", name="profile_edit") - */ - public function editAction(Request $request) + #[Route('/profile/edit', name: 'profile_edit')] + public function editAction(Request $request): Response { $user = $this->getUser(); if (!$user instanceof User) { @@ -97,9 +94,9 @@ public function editAction(Request $request) /** * Change pass - * @Route("/change-password", name="change_password", methods={"GET", "POST"}) */ - public function changePasswordAction(Request $request) + #[Route('/change-password', name: 'change_password', methods: ['GET', 'POST'])] + public function changePasswordAction(Request $request): Response { /** @var User $user */ $user = $this->getUser(); @@ -129,10 +126,8 @@ public function changePasswordAction(Request $request) ]); } - /** - * @Route("/users/", name="users_list") - */ - public function listAction(Request $request) + #[Route('/users/', name: 'users_list')] + public function listAction(Request $request): Response { $page = $request->query->get('page', 1); @@ -154,10 +149,8 @@ public function listAction(Request $request) ]); } - /** - * @Route("/users/{name}/update", name="users_update") - */ - public function updateAction(Request $request, #[Vars(['name' => 'username'])] User $user) + #[Route('/users/{name}/update', name: 'users_update')] + public function updateAction(Request $request, #[Vars(['name' => 'username'])] User $user): Response { $currentUser = $this->getUser(); if ($currentUser->getUserIdentifier() !== $user->getUserIdentifier() && !$user->isAdmin()) { @@ -167,13 +160,8 @@ public function updateAction(Request $request, #[Vars(['name' => 'username'])] U throw new AccessDeniedHttpException('You can not update yourself or admin user'); } - /** - * @Route("/users/create", name="users_create") - * - * @param Request $request - * @return mixed - */ - public function createAction(Request $request) + #[Route('/users/create', name: 'users_create')] + public function createAction(Request $request): Response { $user = new User(); $user->generateApiToken(); @@ -212,9 +200,7 @@ protected function handleUpdate(Request $request, User $user, $flashMessage) ]); } - /** - * @Route("/users/{name}/packages", name="user_packages") - */ + #[Route('/users/{name}/packages', name: 'user_packages')] public function packagesAction(Request $req, #[Vars(['name' => 'username'])] User $user) { $packages = $this->getUserPackages($req, $user); @@ -226,12 +212,9 @@ public function packagesAction(Request $req, #[Vars(['name' => 'username'])] Use ]); } - /** - * @Route("/users/sshkey", name="user_add_sshkey", methods={"GET", "POST"}) - * @Route("/users/sshkey/{id}", name="user_edit_sshkey", methods={"GET", "POST"}) - * {@inheritdoc} - */ - public function addSSHKeyAction(Request $request, #[Vars] SshCredentials $key = null) + #[Route('/users/sshkey', name: 'user_add_sshkey', methods: ['GET', 'POST'])] + #[Route('/users/sshkey/{id}', name: 'user_edit_sshkey', methods: ['GET', 'POST'])] + public function addSSHKeyAction(Request $request, #[Vars] SshCredentials $key = null): Response { if ($key && !$this->isGranted('VIEW', $key)) { throw new AccessDeniedException(); @@ -277,10 +260,8 @@ public function addSSHKeyAction(Request $request, #[Vars] SshCredentials $key = ]); } - /** - * @Route("/users/{name}", name="user_profile") - */ - public function profileAction(Request $req, #[Vars(['name' => 'username'])] User $user) + #[Route('/users/{name}', name: 'user_profile')] + public function profileAction(Request $req, #[Vars(['name' => 'username'])] User $user): Response { $deleteForm = $this->createFormBuilder([])->getForm(); $packages = $this->getUserPackages($req, $user); @@ -293,15 +274,12 @@ public function profileAction(Request $req, #[Vars(['name' => 'username'])] User ]); } - /** - * @Route("/users/{name}/delete", name="user_delete") - */ - public function deleteAction(Request $request, #[Vars(['name' => 'username'])] User $user) + #[Route('/users/{name}/delete', name: 'user_delete', methods: ['POST'])] + public function deleteAction(Request $request, #[Vars(['name' => 'username'])] User $user): Response { $form = $this->createFormBuilder([])->getForm(); $form->submit($request->request->get('form')); if ($form->isValid()) { - $request->getSession()->save(); $em = $this->registry->getManager(); $em->remove($user); $em->flush(); @@ -312,10 +290,8 @@ public function deleteAction(Request $request, #[Vars(['name' => 'username'])] U return new Response('Invalid form input', 400); } - /** - * @Route("/users/{name}/favorites", name="user_favorites", methods={"GET"}) - */ - public function favoritesAction(Request $req, #[Vars(['name' => 'username'])] User $user) + #[Route('/users/{name}/favorites', name: 'user_favorites', methods: ['GET'])] + public function favoritesAction(Request $req, #[Vars(['name' => 'username'])] User $user): Response { $paginator = new Pagerfanta( new RedisAdapter($this->favoriteManager, $user, 'getFavorites', 'getFavoriteCount') @@ -330,10 +306,8 @@ public function favoritesAction(Request $req, #[Vars(['name' => 'username'])] Us ]); } - /** - * @Route("/users/{name}/favorites", name="user_add_fav", defaults={"_format" = "json"}, methods={"POST"}) - */ - public function postFavoriteAction(Request $req, #[Vars(['name' => 'username'])] User $user) + #[Route('/users/{name}/favorites', name: 'user_add_fav', defaults: ['_format' => 'json'], methods: ['POST'])] + public function postFavoriteAction(Request $req, #[Vars(['name' => 'username'])] User $user): Response { if ($user->getId() !== $this->getUser()->getId()) { throw new AccessDeniedException('You can only change your own favorites'); @@ -353,16 +327,14 @@ public function postFavoriteAction(Request $req, #[Vars(['name' => 'username'])] return new JsonResponse(['status' => 'success'], 201); } - /** - * @Route( - * "/users/{name}/favorites/{package}", - * name="user_remove_fav", - * defaults={"_format" = "json"}, - * requirements={"package"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?"}, - * methods={"DELETE"} - * ) - */ - public function deleteFavoriteAction(#[Vars(['name' => 'username'])] User $user, #[Vars('name')] Package $package) + #[Route( + '/users/{name}/favorites/{package}', + name: 'user_remove_fav', + requirements: ['package' => '%package_name_regex%'], + defaults: ['_format' => 'json'], + methods: ['DELETE'] + )] + public function deleteFavoriteAction(#[Vars(['name' => 'username'])] User $user, #[Vars('name')] Package $package): Response { if ($user->getId() !== $this->getUser()->getId()) { throw new AccessDeniedException('You can only change your own favorites'); diff --git a/src/Controller/WebController.php b/src/Controller/WebController.php index f32b4975..aba8b0ba 100644 --- a/src/Controller/WebController.php +++ b/src/Controller/WebController.php @@ -24,6 +24,7 @@ use Pagerfanta\Pagerfanta; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; /** @@ -33,12 +34,11 @@ class WebController extends AbstractController { public function __construct( protected ManagerRegistry $registry - ){} + ){ + } - /** - * @Route("/", name="home") - */ - public function indexAction(Request $request) + #[Route('/', name: 'home')] + public function indexAction(Request $request): Response { $page = $request->query->get('page', 1); $paginator = new Pagerfanta($this->createAdapter()); @@ -70,11 +70,9 @@ public function searchFormAction(Request $req) ]); } - /** - * @Route("/search/", name="search.ajax") - * @Route("/search.{_format}", requirements={"_format"="(html|json)"}, name="search", defaults={"_format"="html"}, methods={"GET"}) - */ - public function searchAction(Request $req) + #[Route('/search/', name: 'search.ajax')] + #[Route('/search.{_format}', name: 'search', requirements: ['_format' => '(html|json)'], defaults: ['_format' => 'html'], methods: ['GET'])] + public function searchAction(Request $req): Response { $packages = []; $form = $this->createForm(SearchQueryType::class, new SearchQuery()); @@ -103,10 +101,8 @@ public function searchAction(Request $req) return $this->render('web/search.html.twig', ['packages' => $paginator]); } - /** - * @Route("/statistics", name="stats") - */ - public function statsAction(\Redis $redis) + #[Route('/statistics', name: 'stats')] + public function statsAction(\Redis $redis): Response { $packages = $this->registry->getRepository(Package::class) ->getPackagesStatisticsByMonthAndYear(); diff --git a/src/Controller/WebhookController.php b/src/Controller/WebhookController.php index 80b6959f..3b169822 100644 --- a/src/Controller/WebhookController.php +++ b/src/Controller/WebhookController.php @@ -26,23 +26,18 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -/** - * @Route("/webhooks") - */ +#[Route('/webhooks')] class WebhookController extends AbstractController { public function __construct( protected ManagerRegistry $registry, protected HookTestAction $testAction, protected CsrfTokenManagerInterface $csrfTokenManager, - ){} + ){ + } - /** - * @Route("", name="webhook_index") - * - * {@inheritdoc} - */ - public function indexAction(Request $request) + #[Route('', name: 'webhook_index')] + public function indexAction(): Response { $user = $this->getUser(); $qb = $this->registry @@ -65,12 +60,8 @@ public function indexAction(Request $request) ]); } - /** - * @Route("/create", name="webhook_create") - * - * {@inheritdoc} - */ - public function createAction(Request $request) + #[Route('/create', name: 'webhook_create')] + public function createAction(Request $request): Response { $hook = new Webhook(); $data = $this->handleUpdate($request, $hook, 'Successfully saved.'); @@ -78,12 +69,8 @@ public function createAction(Request $request) return $data instanceof Response ? $data : $this->render('webhook/update.html.twig', $data); } - /** - * @Route("/update/{id}", name="webhook_update", requirements={"id"="\d+"}) - * - * {@inheritdoc} - */ - public function updateAction(Request $request, #[Vars] Webhook $hook) + #[Route('/update/{id}', name: 'webhook_update', requirements: ['id' => '\d+'])] + public function updateAction(Request $request, #[Vars] Webhook $hook): Response { if (!$this->isGranted('VIEW', $hook)) { throw new AccessDeniedException(); @@ -99,11 +86,8 @@ public function updateAction(Request $request, #[Vars] Webhook $hook) return $data instanceof Response ? $data : $this->render('webhook/update.html.twig', $data); } - /** - * @Route("/delete/{id}", name="webhook_delete") - * {@inheritdoc} - */ - public function deleteAction(Request $request, #[Vars] Webhook $hook) + #[Route('/delete/{id}', name: 'webhook_delete', requirements: ['id' => '\d+'], methods: ['DELETE'])] + public function deleteAction(Request $request, #[Vars] Webhook $hook): Response { if (!$this->isGranted('VIEW', $hook)) { throw new AccessDeniedException; @@ -118,12 +102,8 @@ public function deleteAction(Request $request, #[Vars] Webhook $hook) return new Response('', 204); } - /** - * @Route("/job/{id}", name="webhook_job_action") - * - * {@inheritdoc} - */ - public function jobAction(#[Vars] Job $entity) + #[Route('/job/{id}', name: 'webhook_job_action')] + public function jobAction(#[Vars] Job $entity): Response { $hook = $this->registry->getRepository(Webhook::class) ->find($entity->getPackageId()); @@ -144,12 +124,8 @@ public function jobAction(#[Vars] Job $entity) ]); } - /** - * @Route("/test/{id}/send", name="webhook_test_action", requirements={"id"="\d+"}) - * - * {@inheritdoc} - */ - public function testAction(Request $request, #[Vars] Webhook $entity) + #[Route('/test/{id}/send', name: 'webhook_test_action', requirements: ['id' => '\d+'])] + public function testAction(Request $request, #[Vars] Webhook $entity): Response { if (!$this->isGranted('VIEW', $entity)) { throw new AccessDeniedException();