Failed Conditions
Push — metadata ( c6c11e...d7114b )
by Michael
02:19
created

Controller::updateAceProperty()   B

Complexity

Conditions 8
Paths 30

Size

Total Lines 44
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 30
dl 0
loc 44
rs 8.1954
c 0
b 0
f 0
cc 8
nc 30
nop 2
1
<?php
2
3
namespace Doctrine\Tests\Annotations\Fixtures;
4
5
use Doctrine\Tests\Annotations\Fixtures\Annotation\Template;
6
use Doctrine\Tests\Annotations\Fixtures\Annotation\Route;
7
8
/**
9
 * @Route("/someprefix")
10
 * @author Johannes M. Schmitt <[email protected]>
11
 */
12
class Controller
13
{
14
    /**
15
     * @Route("/", name="_demo")
16
     * @Template()
17
     */
18
    public function indexAction()
19
    {
20
        return [];
21
    }
22
23
    /**
24
     * @Route("/hello/{name}", name="_demo_hello")
25
     * @Template()
26
     */
27
    public function helloAction($name)
28
    {
29
        return ['name' => $name];
30
    }
31
32
    /**
33
     * @Route("/contact", name="_demo_contact")
34
     * @Template()
35
     */
36
    public function contactAction()
37
    {
38
        $form = ContactForm::create($this->get('form.context'), 'contact');
39
40
        $form->bind($this->container->get('request'), $form);
41
        if ($form->isValid()) {
42
            $form->send($this->get('mailer'));
43
44
            $this->get('session')->setFlash('notice', 'Message sent!');
45
46
            return new RedirectResponse($this->generateUrl('_demo'));
47
        }
48
49
        return ['form' => $form];
50
    }
51
52
    /**
53
     * Creates the ACL for the passed object identity
54
     *
55
     * @param ObjectIdentityInterface $oid
56
     * @return void
57
     */
58
    private function createObjectIdentity(ObjectIdentityInterface $oid)
59
    {
60
        $classId = $this->createOrRetrieveClassId($oid->getType());
61
62
        $this->connection->executeQuery($this->getInsertObjectIdentitySql($oid->getIdentifier(), $classId, true));
63
    }
64
65
    /**
66
     * Returns the primary key for the passed class type.
67
     *
68
     * If the type does not yet exist in the database, it will be created.
69
     *
70
     * @param string $classType
71
     * @return integer
72
     */
73
    private function createOrRetrieveClassId($classType)
74
    {
75
        if (false !== $id = $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn()) {
76
            return $id;
77
        }
78
79
        $this->connection->executeQuery($this->getInsertClassSql($classType));
80
81
        return $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn();
82
    }
83
84
    /**
85
     * Returns the primary key for the passed security identity.
86
     *
87
     * If the security identity does not yet exist in the database, it will be
88
     * created.
89
     *
90
     * @param SecurityIdentityInterface $sid
91
     * @return integer
92
     */
93
    private function createOrRetrieveSecurityIdentityId(SecurityIdentityInterface $sid)
94
    {
95
        if (false !== $id = $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn()) {
96
            return $id;
97
        }
98
99
        $this->connection->executeQuery($this->getInsertSecurityIdentitySql($sid));
100
101
        return $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn();
102
    }
103
104
    /**
105
     * Deletes all ACEs for the given object identity primary key.
106
     *
107
     * @param integer $oidPK
108
     * @return void
109
     */
110
    private function deleteAccessControlEntries($oidPK)
111
    {
112
        $this->connection->executeQuery($this->getDeleteAccessControlEntriesSql($oidPK));
113
    }
114
115
    /**
116
     * Deletes the object identity from the database.
117
     *
118
     * @param integer $pk
119
     * @return void
120
     */
121
    private function deleteObjectIdentity($pk)
122
    {
123
        $this->connection->executeQuery($this->getDeleteObjectIdentitySql($pk));
124
    }
125
126
    /**
127
     * Deletes all entries from the relations table from the database.
128
     *
129
     * @param integer $pk
130
     * @return void
131
     */
132
    private function deleteObjectIdentityRelations($pk)
133
    {
134
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
135
    }
136
137
    /**
138
     * This regenerates the ancestor table which is used for fast read access.
139
     *
140
     * @param AclInterface $acl
141
     * @return void
142
     */
143
    private function regenerateAncestorRelations(AclInterface $acl)
144
    {
145
        $pk = $acl->getId();
146
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
147
        $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk));
148
149
        $parentAcl = $acl->getParentAcl();
150
        while (null !== $parentAcl) {
151
            $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId()));
152
153
            $parentAcl = $parentAcl->getParentAcl();
154
        }
155
    }
156
157
    /**
158
     * This processes changes on an ACE related property (classFieldAces, or objectFieldAces).
159
     *
160
     * @param string $name
161
     * @param array $changes
162
     * @return void
163
     */
164
    private function updateFieldAceProperty($name, array $changes)
165
    {
166
        $sids = new \SplObjectStorage();
167
        $classIds = new \SplObjectStorage();
168
        $currentIds = [];
169
        foreach ($changes[1] as $field => $new) {
170
            for ($i=0,$c=count($new); $i<$c; $i++) {
171
                $ace = $new[$i];
172
173
                if (null === $ace->getId()) {
174
                    if ($sids->contains($ace->getSecurityIdentity())) {
175
                        $sid = $sids->offsetGet($ace->getSecurityIdentity());
176
                    } else {
177
                        $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
178
                    }
179
180
                    $oid = $ace->getAcl()->getObjectIdentity();
181
                    if ($classIds->contains($oid)) {
182
                        $classId = $classIds->offsetGet($oid);
183
                    } else {
184
                        $classId = $this->createOrRetrieveClassId($oid->getType());
185
                    }
186
187
                    $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId();
188
189
                    $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
190
                    $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn();
191
                    $this->loadedAces[$aceId] = $ace;
192
193
                    $aceIdProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'id');
194
                    $aceIdProperty->setAccessible(true);
195
                    $aceIdProperty->setValue($ace, (int) $aceId);
196
                } else {
197
                    $currentIds[$ace->getId()] = true;
198
                }
199
            }
200
        }
201
202
        foreach ($changes[0] as $old) {
203
            for ($i=0,$c=count($old); $i<$c; $i++) {
204
                $ace = $old[$i];
205
206
                if (!isset($currentIds[$ace->getId()])) {
207
                    $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
208
                    unset($this->loadedAces[$ace->getId()]);
209
                }
210
            }
211
        }
212
    }
213
214
    /**
215
     * This processes changes on an ACE related property (classAces, or objectAces).
216
     *
217
     * @param string $name
218
     * @param array $changes
219
     * @return void
220
     */
221
    private function updateAceProperty($name, array $changes)
222
    {
223
        list($old, $new) = $changes;
224
225
        $sids = new \SplObjectStorage();
226
        $classIds = new \SplObjectStorage();
227
        $currentIds = [];
228
        for ($i=0,$c=count($new); $i<$c; $i++) {
229
            $ace = $new[$i];
230
231
            if (null === $ace->getId()) {
232
                if ($sids->contains($ace->getSecurityIdentity())) {
233
                    $sid = $sids->offsetGet($ace->getSecurityIdentity());
234
                } else {
235
                    $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
236
                }
237
238
                $oid = $ace->getAcl()->getObjectIdentity();
239
                if ($classIds->contains($oid)) {
240
                    $classId = $classIds->offsetGet($oid);
241
                } else {
242
                    $classId = $this->createOrRetrieveClassId($oid->getType());
243
                }
244
245
                $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId();
246
247
                $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
248
                $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn();
249
                $this->loadedAces[$aceId] = $ace;
250
251
                $aceIdProperty = new \ReflectionProperty($ace, 'id');
252
                $aceIdProperty->setAccessible(true);
253
                $aceIdProperty->setValue($ace, (int) $aceId);
254
            } else {
255
                $currentIds[$ace->getId()] = true;
256
            }
257
        }
258
259
        for ($i=0,$c=count($old); $i<$c; $i++) {
260
            $ace = $old[$i];
261
262
            if (!isset($currentIds[$ace->getId()])) {
263
                $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
264
                unset($this->loadedAces[$ace->getId()]);
265
            }
266
        }
267
    }
268
269
    /**
270
     * Persists the changes which were made to ACEs to the database.
271
     *
272
     * @param \SplObjectStorage $aces
273
     * @return void
274
     */
275
    private function updateAces(\SplObjectStorage $aces)
276
    {
277
        foreach ($aces as $ace) {
278
            $propertyChanges = $aces->offsetGet($ace);
279
            $sets = [];
280
281
            if (isset($propertyChanges['mask'])) {
282
                $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]);
283
            }
284
            if (isset($propertyChanges['strategy'])) {
285
                $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy']));
286
            }
287
            if (isset($propertyChanges['aceOrder'])) {
288
                $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]);
289
            }
290
            if (isset($propertyChanges['auditSuccess'])) {
291
                $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1]));
292
            }
293
            if (isset($propertyChanges['auditFailure'])) {
294
                $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1]));
295
            }
296
297
            $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets));
298
        }
299
    }
300
}
301