Completed
Push — master ( 5c0b6f...5c71f2 )
by Oleg
10:16
created

SavePermissionsAction::process()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 66

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 66
ccs 0
cts 63
cp 0
rs 7.8084
c 0
b 0
f 0
cc 7
nc 13
nop 2
crap 56

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DataFlowServer\Authorization\Controller;
5
6
use Doctrine\Common\Collections\Criteria;
7
use Doctrine\Common\Collections\Selectable;
8
use Doctrine\Common\Persistence\ManagerRegistry;
9
use Doctrine\ORM\EntityManagerInterface;
10
use Doctrine\ORM\ORMException;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Psr\Http\Server\MiddlewareInterface;
14
use Psr\Http\Server\RequestHandlerInterface;
15
use Psr\Log\LoggerInterface;
16
use SlayerBirden\DataFlowServer\Authorization\Entities\Permission;
17
use SlayerBirden\DataFlowServer\Authorization\HistoryManagementInterface;
18
use SlayerBirden\DataFlowServer\Doctrine\Middleware\ResourceMiddlewareInterface;
19
use SlayerBirden\DataFlowServer\Domain\Entities\ClaimedResourceInterface;
20
use SlayerBirden\DataFlowServer\Domain\Entities\User;
21
use SlayerBirden\DataFlowServer\Notification\DangerMessage;
22
use SlayerBirden\DataFlowServer\Notification\SuccessMessage;
23
use SlayerBirden\DataFlowServer\Stdlib\Validation\DataValidationResponseFactory;
24
use SlayerBirden\DataFlowServer\Stdlib\Validation\ValidationResponseFactory;
25
use Zend\Diactoros\Response\JsonResponse;
26
use Zend\Hydrator\HydratorInterface;
27
use Zend\InputFilter\InputFilterInterface;
28
29
final class SavePermissionsAction implements MiddlewareInterface
30
{
31
    /**
32
     * @var LoggerInterface
33
     */
34
    private $logger;
35
    /**
36
     * @var InputFilterInterface
37
     */
38
    private $inputFilter;
39
    /**
40
     * @var HistoryManagementInterface
41
     */
42
    private $historyManagement;
43
    /**
44
     * @var HydratorInterface
45
     */
46
    private $hydrator;
47
    /**
48
     * @var ManagerRegistry
49
     */
50
    private $managerRegistry;
51
    /**
52
     * @var Selectable
53
     */
54
    private $permissionRepository;
55
56
    public function __construct(
57
        ManagerRegistry $managerRegistry,
58
        Selectable $permissionRepository,
59
        LoggerInterface $logger,
60
        InputFilterInterface $inputFilter,
61
        HistoryManagementInterface $historyManagement,
62
        HydratorInterface $hydrator
63
    ) {
64
        $this->managerRegistry = $managerRegistry;
65
        $this->permissionRepository = $permissionRepository;
66
        $this->logger = $logger;
67
        $this->inputFilter = $inputFilter;
68
        $this->historyManagement = $historyManagement;
69
        $this->hydrator = $hydrator;
70
    }
71
72
    /**
73
     * @inheritdoc
74
     */
75
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
76
    {
77
        $data = $request->getParsedBody();
78
        if (!is_array($data)) {
79
            return (new DataValidationResponseFactory())('permissions', []);
80
        }
81
        $user = $request->getAttribute(ResourceMiddlewareInterface::DATA_RESOURCE);
82
83
        $this->inputFilter->setData($data);
84
        if (!$this->inputFilter->isValid()) {
85
            return (new ValidationResponseFactory())('permissions', $this->inputFilter, []);
86
        }
87
        $em = $this->managerRegistry->getManagerForClass(Permission::class);
88
        if ($em === null) {
89
            return new JsonResponse([
90
                'msg' => new DangerMessage('Could not retrieve ObjectManager'),
91
                'success' => false,
92
                'data' => [
93
                    'token' => null,
94
                ]
95
            ], 500);
96
        }
97
        if (!($em instanceof EntityManagerInterface)) {
98
            return new JsonResponse([
99
                'msg' => new DangerMessage('Can not use current ObjectManager'),
100
                'success' => false,
101
                'data' => [
102
                    'token' => null,
103
                ]
104
            ], 500);
105
        }
106
        $em->beginTransaction();
107
        try {
108
            $permissions = $this->processResources(
109
                $user,
110
                $data[ClaimedResourceInterface::OWNER_PARAM],
111
                ...$data['resources']
112
            );
113
            if (empty($permissions)) {
114
                $msg = new SuccessMessage('No changes detected. The input is identical to the storage.');
115
            } else {
116
                $em->flush();
117
                $em->commit();
118
                $msg = new SuccessMessage('Successfully set permissions to resources.');
119
            }
120
121
            return new JsonResponse([
122
                'msg' => $msg,
123
                'data' => [
124
                    'permissions' => array_map([$this->hydrator, 'extract'], $permissions),
125
                ],
126
                'success' => true,
127
            ], 200);
128
        } catch (ORMException $exception) {
129
            $this->logger->error((string)$exception);
130
            $em->rollback();
131
132
            return new JsonResponse([
133
                'msg' => new DangerMessage('There was an error while setting the permissions.'),
134
                'data' => [
135
                    'permissions' => [],
136
                ],
137
                'success' => false,
138
            ], 400);
139
        }
140
    }
141
142
    /**
143
     * @param User $user
144
     * @param User $owner
145
     * @param string ...$resources
146
     * @return Permission[]
147
     * @throws ORMException
148
     */
149
    private function processResources(User $user, User $owner, string ...$resources): array
150
    {
151
        $result = [];
152
        $collection = $this->permissionRepository->matching(
153
            Criteria::create()->where(Criteria::expr()->eq('user', $user))
154
        );
155
156
        $currentResources = array_map(function (Permission $permission) {
157
            return $permission->getResource();
158
        }, $collection->toArray());
159
160
        $toRemove = array_diff($currentResources, $resources);
161
        $toAdd = array_diff($resources, $currentResources);
162
163
        if (empty($toAdd) && empty($toRemove)) {
164
            return [];
165
        }
166
167
        $this->processItemsToRemove($collection, $toRemove, $owner, $result);
168
        $this->processItemsToAdd($toAdd, $user, $owner, $result);
169
170
        return $result;
171
    }
172
173
    /**
174
     * @param $collection
175
     * @param $toRemove
176
     * @param $owner
177
     * @param $result
178
     */
179
    private function processItemsToRemove($collection, $toRemove, $owner, &$result): void
180
    {
181
        $em = $this->managerRegistry->getManagerForClass(Permission::class);
182
        if ($em === null) {
183
            throw new \LogicException('Could not obtain ObjectManager');
184
        }
185
        /** @var Permission $permission */
186
        foreach ($collection as $permission) {
187
            if (in_array($permission->getResource(), $toRemove, true)) {
188
                $em->remove($permission);
189
                $history = $this->historyManagement->fromPermission($permission);
190
                $history->setOwner($owner);
191
                $em->persist($history);
192
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
193
            } else {
194
                $result[] = $permission;
195
            }
196
        }
197
    }
198
199
    /**
200
     * @param $toAdd
201
     * @param $user
202
     * @param $owner
203
     * @param $result
204
     * @throws ORMException
205
     */
206
    private function processItemsToAdd($toAdd, $user, $owner, &$result): void
207
    {
208
        $em = $this->managerRegistry->getManagerForClass(Permission::class);
209
        if ($em === null) {
210
            throw new \LogicException('Could not obtain ObjectManager');
211
        }
212
        foreach ($toAdd as $resource) {
213
            $permission = new Permission();
214
            $permission->setResource($resource);
215
            $permission->setUser($user);
216
            $result[] = $permission;
217
            $em->persist($permission);
218
            $history = $this->historyManagement->fromPermission($permission);
219
            $history->setOwner($owner);
220
            $em->persist($history);
221
        }
222
    }
223
}
224