| 1 | <?php |
||
| 2 | |||
| 3 | /* |
||
| 4 | * (c) Lukasz D. Tulikowski <[email protected]> |
||
| 5 | * |
||
| 6 | * For the full copyright and license information, please view the LICENSE |
||
| 7 | * file that was distributed with this source code. |
||
| 8 | */ |
||
| 9 | |||
| 10 | declare(strict_types=1); |
||
| 11 | |||
| 12 | namespace App\Controller; |
||
| 13 | |||
| 14 | use App\Interfaces\RepositoryInterface; |
||
| 15 | use App\Repository\AbstractRepository; |
||
| 16 | use App\Resource\PaginationResource; |
||
| 17 | use App\Traits\ControllerTrait; |
||
| 18 | use Doctrine\Common\Inflector\Inflector; |
||
| 19 | use Doctrine\Common\Persistence\ObjectRepository; |
||
| 20 | use Doctrine\ORM\EntityManagerInterface; |
||
| 21 | use Doctrine\ORM\Query; |
||
| 22 | use JMS\Serializer\SerializationContext; |
||
| 23 | use Pagerfanta\Adapter\DoctrineORMAdapter; |
||
| 24 | use Pagerfanta\Pagerfanta; |
||
| 25 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
||
| 26 | use Symfony\Component\Form\FormInterface; |
||
| 27 | use Symfony\Component\HttpFoundation\JsonResponse; |
||
| 28 | use Symfony\Component\HttpFoundation\Request; |
||
| 29 | use Symfony\Component\HttpFoundation\Response; |
||
| 30 | |||
| 31 | abstract class AbstractController extends Controller |
||
| 32 | { |
||
| 33 | use ControllerTrait; |
||
| 34 | |||
| 35 | public const DELETED = ['success' => 'Deleted.']; |
||
| 36 | public const NOT_FOUND = ['error' => 'Resource not found.']; |
||
| 37 | public const GENERAL_ERROR = ['error' => 'Something went wrong.']; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @var string |
||
| 41 | */ |
||
| 42 | protected $entity; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * @var EntityManagerInterface |
||
| 46 | */ |
||
| 47 | protected $entityManager; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * @var AbstractRepository |
||
| 51 | */ |
||
| 52 | protected $repository; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * BaseController constructor. |
||
| 56 | * |
||
| 57 | * @param string $entity |
||
| 58 | */ |
||
| 59 | 51 | public function __construct(string $entity) |
|
| 60 | { |
||
| 61 | 51 | $this->entity = $entity; |
|
| 62 | 51 | } |
|
| 63 | |||
| 64 | /** |
||
| 65 | * @required |
||
| 66 | */ |
||
| 67 | 51 | public function setManager() |
|
| 68 | { |
||
| 69 | 51 | $this->entityManager = $this->getDoctrine()->getManager(); |
|
| 70 | 51 | } |
|
| 71 | |||
| 72 | /** |
||
| 73 | * @return ObjectRepository |
||
| 74 | */ |
||
| 75 | 8 | public function getRepository() |
|
| 76 | { |
||
| 77 | 8 | return $this->entityManager->getRepository($this->entity); |
|
| 78 | } |
||
| 79 | |||
| 80 | /** |
||
| 81 | * @param Pagerfanta $paginator |
||
| 82 | * |
||
| 83 | * @return JsonResponse |
||
| 84 | */ |
||
| 85 | 8 | public function createCollectionResponse(PagerFanta $paginator): JsonResponse |
|
| 86 | { |
||
| 87 | 8 | $this->responseCreator->setCollectionData( |
|
| 88 | 8 | $this->serializer->toArray( |
|
| 89 | 8 | $paginator->getIterator()->getArrayCopy(), |
|
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 90 | 8 | $this->serializationService->createBaseOnRequest() |
|
| 91 | ), |
||
| 92 | 8 | (new PaginationResource())->createFromPagerfanta($paginator) |
|
| 93 | ); |
||
| 94 | |||
| 95 | 8 | return $this->responseCreator->getResponse(Response::HTTP_OK, $this->getEntityResponseField()); |
|
| 96 | } |
||
| 97 | |||
| 98 | /** |
||
| 99 | * @param $resource |
||
| 100 | * @param int $status |
||
| 101 | * @param SerializationContext|null $context |
||
| 102 | * |
||
| 103 | * @return JsonResponse |
||
| 104 | */ |
||
| 105 | 12 | public function createResourceResponse($resource, $status = Response::HTTP_OK, SerializationContext $context = null): JsonResponse |
|
| 106 | { |
||
| 107 | 12 | if (!$context) { |
|
| 108 | 12 | $context = $this->serializationService->createBaseOnRequest(); |
|
| 109 | } |
||
| 110 | |||
| 111 | 12 | $this->responseCreator->setData($this->serializer->toArray($resource, $context)); |
|
| 112 | |||
| 113 | 12 | return $this->responseCreator->getResponse($status); |
|
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * @param array $data |
||
| 118 | * @param int $status |
||
| 119 | * |
||
| 120 | * @return JsonResponse |
||
| 121 | */ |
||
| 122 | 4 | public function createSuccessfulApiResponse(array $data = [], $status = Response::HTTP_OK): JsonResponse |
|
| 123 | { |
||
| 124 | 4 | $this->responseCreator->setData($data); |
|
| 125 | |||
| 126 | 4 | return $this->responseCreator->getResponse($status, $this->getEntityResponseField()); |
|
| 127 | } |
||
| 128 | |||
| 129 | /** |
||
| 130 | * @return JsonResponse |
||
| 131 | */ |
||
| 132 | 12 | public function createNotFoundResponse(): JsonResponse |
|
| 133 | { |
||
| 134 | 12 | $this->responseCreator->setData(self::NOT_FOUND); |
|
| 135 | |||
| 136 | 12 | return $this->responseCreator->getResponse(Response::HTTP_NOT_FOUND, $this->getEntityResponseField()); |
|
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * @param \Exception $exception |
||
| 141 | * |
||
| 142 | * @return JsonResponse |
||
| 143 | */ |
||
| 144 | public function createGenericErrorResponse(\Exception $exception): JsonResponse |
||
| 145 | { |
||
| 146 | $this->responseCreator->setData( |
||
| 147 | array_merge(self::GENERAL_ERROR, ['details' => $exception->getMessage()]) |
||
| 148 | ); |
||
| 149 | |||
| 150 | return $this->responseCreator->getResponse( |
||
| 151 | Response::HTTP_INTERNAL_SERVER_ERROR, |
||
| 152 | $this->getEntityResponseField() |
||
| 153 | ); |
||
| 154 | } |
||
| 155 | |||
| 156 | /** |
||
| 157 | * @param Request $request |
||
| 158 | * @param Query $query |
||
| 159 | * |
||
| 160 | * @return Pagerfanta |
||
| 161 | */ |
||
| 162 | 8 | public function createPaginator(Request $request, Query $query): Pagerfanta |
|
| 163 | { |
||
| 164 | // Construct the doctrine adapter using the query. |
||
| 165 | 8 | $adapter = new DoctrineORMAdapter($query); |
|
| 166 | 8 | $paginator = new Pagerfanta($adapter); |
|
| 167 | |||
| 168 | 8 | $limit = $request->attributes->get('limit'); |
|
| 169 | 8 | $limit = (1 <= $limit) && ($limit <= 100) ?: 10; |
|
| 170 | |||
| 171 | // Set pages based on the request parameters. |
||
| 172 | 8 | $paginator->setMaxPerPage($request->query->get('limit', $limit)); |
|
| 173 | 8 | $paginator->setCurrentPage($request->query->get('page', 1)); |
|
| 174 | |||
| 175 | 8 | return $paginator; |
|
| 176 | } |
||
| 177 | |||
| 178 | /** |
||
| 179 | * @param Request $request |
||
| 180 | * @param string $filterForm |
||
| 181 | * |
||
| 182 | * @return Pagerfanta |
||
| 183 | */ |
||
| 184 | 8 | public function handleFilterForm(Request $request, string $filterForm): Pagerfanta |
|
| 185 | { |
||
| 186 | /** @var RepositoryInterface $repository */ |
||
| 187 | 8 | $repository = $this->getRepository(); |
|
| 188 | 8 | $queryBuilder = $repository->getQueryBuilder(); |
|
| 189 | |||
| 190 | 8 | $form = $this->getForm($filterForm); |
|
| 191 | |||
| 192 | 8 | if ($request->query->has($form->getName())) { |
|
| 193 | 4 | $form->submit($request->query->get($form->getName())); |
|
| 194 | |||
| 195 | 4 | $queryBuilder = $this->get('lexik_form_filter.query_builder_updater') |
|
| 196 | 4 | ->addFilterConditions($form, $queryBuilder); |
|
| 197 | } |
||
| 198 | |||
| 199 | 8 | $paginagor = $this->createPaginator($request, $queryBuilder->getQuery()); |
|
| 200 | |||
| 201 | 8 | return $paginagor; |
|
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * @return string |
||
| 206 | */ |
||
| 207 | 24 | public function getEntityResponseField() |
|
| 208 | { |
||
| 209 | 24 | $path = explode('\\', $this->entity); |
|
| 210 | |||
| 211 | 24 | return $this->inflector::pluralize(strtolower(array_pop($path))); |
|
| 212 | } |
||
| 213 | |||
| 214 | /** |
||
| 215 | * @param string $type |
||
| 216 | * @param $data |
||
| 217 | * @param array $options |
||
| 218 | * |
||
| 219 | * @return FormInterface |
||
| 220 | */ |
||
| 221 | 20 | public function getForm(string $type, $data = null, array $options = []): FormInterface |
|
| 222 | { |
||
| 223 | 20 | $session = $this->get('session'); |
|
| 224 | 20 | $inflector = new Inflector(); |
|
| 225 | |||
| 226 | try { |
||
| 227 | 20 | $reflectionClass = new \ReflectionClass($type); |
|
| 228 | } catch (\ReflectionException $e) { |
||
| 229 | throw new \RuntimeException($e->getMessage()); |
||
| 230 | } |
||
| 231 | |||
| 232 | 20 | $name = $reflectionClass->getShortName(); |
|
| 233 | 20 | $options = array_merge($options, ['csrf_protection' => false, 'allow_extra_fields' => true]); |
|
| 234 | |||
| 235 | 20 | if ($formData = $session->get($type, null)) { |
|
| 236 | $data = $this->serializer |
||
| 237 | ->deserialize($formData->getJson(), $formData->getClassName(), 'json'); |
||
| 238 | } |
||
| 239 | |||
| 240 | 20 | $form = $this->formFactory |
|
| 241 | 20 | ->createNamedBuilder($inflector->tableize($name), $type, $data, $options) |
|
| 242 | 20 | ->getForm(); |
|
| 243 | |||
| 244 | 20 | return $form; |
|
| 245 | } |
||
| 246 | } |
||
| 247 |