/
ObjectAclManipulator.php
125 lines (104 loc) · 4.39 KB
/
ObjectAclManipulator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\DoctrineORMAdminBundle\Util;
use Doctrine\ORM\EntityManager;
use Doctrine\Persistence\ManagerRegistry;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Exception\ModelManagerException;
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
use Sonata\AdminBundle\Util\ObjectAclManipulator as BaseObjectAclManipulator;
use Sonata\DoctrineORMAdminBundle\Model\ModelManager;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
/**
* @final since sonata-project/doctrine-orm-admin-bundle 3.24
*/
class ObjectAclManipulator extends BaseObjectAclManipulator
{
/**
* NEXT_MAJOR: Remove null.
*
* @var ManagerRegistry|null
*/
private $registry;
public function __construct(?ManagerRegistry $registry = null)
{
if (null === $registry) {
@trigger_error(sprintf(
'Not passing a "%s" instance as argument 1 for "%s()" is deprecated since'
.' sonata-project/doctrine-orm-admin-bundle 3.31 and will throw a %s error in 4.0.',
ManagerRegistry::class,
__METHOD__,
\TypeError::class
), \E_USER_DEPRECATED);
}
$this->registry = $registry;
}
public function batchConfigureAcls(OutputInterface $output, AdminInterface $admin, ?UserSecurityIdentity $securityIdentity = null)
{
$securityHandler = $admin->getSecurityHandler();
if (!$securityHandler instanceof AclSecurityHandlerInterface) {
$output->writeln('Admin class is not configured to use ACL : <info>ignoring</info>');
return;
}
$output->writeln(sprintf(' > generate ACLs for %s', $admin->getCode()));
$objectOwnersMsg = null === $securityIdentity ? '' : ' and set the object owner';
// NEXT_MAJOR: Completely remove the "else" part and the "if" check.
if (null !== $this->registry) {
$em = $this->registry->getManagerForClass($admin->getClass());
\assert($em instanceof EntityManager);
} else {
$modelManager = $admin->getModelManager();
\assert($modelManager instanceof ModelManager);
$em = $modelManager->getEntityManager($admin->getClass());
}
$qb = $em->createQueryBuilder();
$qb->select('o')->from($admin->getClass(), 'o');
$count = 0;
$countUpdated = 0;
$countAdded = 0;
try {
$batchSize = 20;
$batchSizeOutput = 200;
$objectIds = [];
foreach ($qb->getQuery()->iterate() as $row) {
$objectIds[] = ObjectIdentity::fromDomainObject($row[0]);
// detach from Doctrine, so that it can be Garbage-Collected immediately
$em->detach($row[0]);
++$count;
if (0 === ($count % $batchSize)) {
[$batchAdded, $batchUpdated] = $this->configureAcls($output, $admin, new \ArrayIterator($objectIds), $securityIdentity);
$countAdded += $batchAdded;
$countUpdated += $batchUpdated;
$objectIds = [];
}
if (0 === ($count % $batchSizeOutput)) {
$output->writeln(sprintf(' - generated class ACEs%s for %s objects (added %s, updated %s)', $objectOwnersMsg, $count, $countAdded, $countUpdated));
}
}
if (\count($objectIds) > 0) {
[$batchAdded, $batchUpdated] = $this->configureAcls($output, $admin, new \ArrayIterator($objectIds), $securityIdentity);
$countAdded += $batchAdded;
$countUpdated += $batchUpdated;
}
} catch (\PDOException $e) {
throw new ModelManagerException('', 0, $e);
}
$output->writeln(sprintf(
' - [TOTAL] generated class ACEs%s for %s objects (added %s, updated %s)',
$objectOwnersMsg,
$count,
$countAdded,
$countUpdated
));
}
}