Completed
Pull Request — master (#1)
by one
09:53
created

AbstractController   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
eloc 60
dl 0
loc 207
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getEntityResponseField() 0 5 1
A __construct() 0 3 1
A handleFilterForm() 0 18 2
A createPaginator() 0 11 1
A createGenericErrorResponse() 0 7 1
A getForm() 0 24 3
A createCollectionResponse() 0 11 1
A createSuccessfulApiResponse() 0 5 1
A getRepository() 0 3 1
A setManager() 0 3 1
A createResourceResponse() 0 9 2
A createNotFoundResponse() 0 5 1
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
    public function __construct(string $entity)
60
    {
61
        $this->entity = $entity;
62
    }
63
64
    /**
65
     * @required
66
     */
67
    public function setManager()
68
    {
69
        $this->entityManager = $this->getDoctrine()->getManager();
70
    }
71
72
    /**
73
     * @return ObjectRepository
74
     */
75
    public function getRepository()
76
    {
77
        return $this->entityManager->getRepository($this->entity);
78
    }
79
80
    /**
81
     * @param Pagerfanta $paginator
82
     *
83
     * @return JsonResponse
84
     */
85
    public function createCollectionResponse(PagerFanta $paginator): JsonResponse
86
    {
87
        $this->responseCreator->setCollectionData(
88
            $this->serializer->toArray(
89
                $paginator->getIterator()->getArrayCopy(),
0 ignored issues
show
Bug introduced by
The method getArrayCopy() does not exist on Traversable. It seems like you code against a sub-type of Traversable such as Nette\Utils\Finder or Nette\Utils\Html or Nette\Utils\ArrayList or ArrayObject or Nette\Iterators\CachingIterator or ArrayIterator or Symfony\Component\Proper...ss\PropertyPathIterator or RecursiveArrayIterator or Symfony\Component\Proper...ss\PropertyPathIterator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
                $paginator->getIterator()->/** @scrutinizer ignore-call */ getArrayCopy(),
Loading history...
90
                $this->serializationService->createBaseOnRequest()
91
            ),
92
            (new PaginationResource())->createFromPagerfanta($paginator)
93
        );
94
95
        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
    public function createResourceResponse($resource, $status = Response::HTTP_OK, SerializationContext $context = null): JsonResponse
106
    {
107
        if (!$context) {
108
            $context = $this->serializationService->createBaseOnRequest();
109
        }
110
111
        $this->responseCreator->setData($this->serializer->toArray($resource, $context));
112
113
        return $this->responseCreator->getResponse($status);
114
    }
115
116
    /**
117
     * @param array $data
118
     * @param int $status
119
     *
120
     * @return JsonResponse
121
     */
122
    public function createSuccessfulApiResponse(array $data = [], $status = Response::HTTP_OK): JsonResponse
123
    {
124
        $this->responseCreator->setData($data);
125
126
        return $this->responseCreator->getResponse($status, $this->getEntityResponseField());
127
    }
128
129
    /**
130
     * @return JsonResponse
131
     */
132
    public function createNotFoundResponse(): JsonResponse
133
    {
134
        $this->responseCreator->setData(self::NOT_FOUND);
135
136
        return $this->responseCreator->getResponse(Response::HTTP_NOT_FOUND, $this->getEntityResponseField());
137
    }
138
139
    /**
140
     * @return JsonResponse
141
     */
142
    public function createGenericErrorResponse(): JsonResponse
143
    {
144
        $this->responseCreator->setData(self::GENERAL_ERROR);
145
146
        return $this->responseCreator->getResponse(
147
            Response::HTTP_INTERNAL_SERVER_ERROR,
148
            $this->getEntityResponseField()
149
        );
150
    }
151
152
    /**
153
     * @param Request $request
154
     * @param Query $query
155
     *
156
     * @return Pagerfanta
157
     */
158
    public function createPaginator(Request $request, Query $query): Pagerfanta
159
    {
160
        //  Construct the doctrine adapter using the query.
161
        $adapter = new DoctrineORMAdapter($query);
162
        $paginator = new Pagerfanta($adapter);
163
164
        //  Set pages based on the request parameters.
165
        $paginator->setMaxPerPage($request->query->get('limit', 10));
166
        $paginator->setCurrentPage($request->query->get('page', 1));
167
168
        return $paginator;
169
    }
170
171
    /**
172
     * @param Request $request
173
     * @param string $filterForm
174
     *
175
     * @return Pagerfanta
176
     */
177
    public function handleFilterForm(Request $request, string $filterForm): Pagerfanta
178
    {
179
        /** @var RepositoryInterface $repository */
180
        $repository = $this->getRepository();
181
        $queryBuilder = $repository->getQueryBuilder();
182
183
        $form = $this->getForm($filterForm);
184
185
        if ($request->query->has($form->getName())) {
186
            $form->submit($request->query->get($form->getName()));
187
188
            $queryBuilder = $this->get('lexik_form_filter.query_builder_updater')
189
                ->addFilterConditions($form, $queryBuilder);
190
        }
191
192
        $paginagor = $this->createPaginator($request, $queryBuilder->getQuery());
193
194
        return $paginagor;
195
    }
196
197
    /**
198
     * @return string
199
     */
200
    public function getEntityResponseField()
201
    {
202
        $path = explode('\\', $this->entity);
203
204
        return $this->inflector::pluralize(strtolower(array_pop($path)));
205
    }
206
207
    /**
208
     * @param string $type
209
     * @param $data
210
     * @param array $options
211
     *
212
     * @return FormInterface
213
     */
214
    public function getForm(string $type, $data = null, array $options = []): FormInterface
215
    {
216
        $session = $this->get('session');
217
        $inflector = new Inflector();
218
219
        try {
220
            $reflectionClass = new \ReflectionClass($type);
221
        } catch (\ReflectionException $e) {
222
            throw new \RuntimeException($e->getMessage());
223
        }
224
225
        $name = $reflectionClass->getShortName();
226
        $options = array_merge($options, ['csrf_protection' => false, 'allow_extra_fields' => true]);
227
228
        if ($formData = $session->get($type, null)) {
229
            $data = $this->serializer
230
                ->deserialize($formData->getJson(), $formData->getClassName(), 'json');
231
        }
232
233
        $form = $this->formFactory
234
            ->createNamedBuilder($inflector->tableize($name), $type, $data, $options)
235
            ->getForm();
236
237
        return $form;
238
    }
239
}
240