diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 9e0c588532..84731563c2 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1,19 +1,5 @@
-
-
- $extensionMap
-
-
- array<string, array<string, array<string, array<string, array<string, string>>>>>
-
-
-
-
-
- DoctrinePersistentCollection
-
-
array_merge(array_flip($keys), $this->filters)
@@ -25,6 +11,12 @@
array_merge(array_flip($keys), $this->elements)
+
+
+
+ $resource
+
+
@@ -34,10 +26,4 @@
null
-
-
-
- $resource
-
-
diff --git a/src/Admin/AbstractAdmin.php b/src/Admin/AbstractAdmin.php
index c9ac1a50cb..fe26cce3da 100644
--- a/src/Admin/AbstractAdmin.php
+++ b/src/Admin/AbstractAdmin.php
@@ -398,7 +398,10 @@ final public function getDataSourceIterator(): SourceIteratorInterface
final public function initialize(): void
{
if (!$this->classnameLabel) {
- $this->classnameLabel = substr($this->getClass(), strrpos($this->getClass(), '\\') + 1);
+ $namespaceSeparatorPos = strrpos($this->getClass(), '\\');
+ $this->classnameLabel = false !== $namespaceSeparatorPos
+ ? substr($this->getClass(), $namespaceSeparatorPos + 1)
+ : $this->getClass();
}
$this->configure();
@@ -508,8 +511,9 @@ final public function getFilterParameters(): array
$parameters = ParametersManipulator::merge($parameters, $filters);
// always force the parent value
- if ($this->isChild() && null !== $this->getParentAssociationMapping()) {
- $name = str_replace('.', '__', $this->getParentAssociationMapping());
+ $parentAssociationMapping = $this->getParentAssociationMapping();
+ if ($this->isChild() && null !== $parentAssociationMapping) {
+ $name = str_replace('.', '__', $parentAssociationMapping);
$parameters[$name] = ['value' => $this->getRequest()->get($this->getParent()->getIdParameter())];
}
}
@@ -2296,12 +2300,13 @@ private function buildDatagrid(): ?DatagridInterface
$this->configureDatagridFilters($mapper);
// ok, try to limit to add parent filter
+ $parentAssociationMapping = $this->getParentAssociationMapping();
if (
$this->isChild()
- && null !== $this->getParentAssociationMapping()
- && !$mapper->has($this->getParentAssociationMapping())
+ && null !== $parentAssociationMapping
+ && !$mapper->has($parentAssociationMapping)
) {
- $mapper->add($this->getParentAssociationMapping(), null, [
+ $mapper->add($parentAssociationMapping, null, [
'show_filter' => false,
'label' => false,
'field_type' => ModelHiddenType::class,
diff --git a/src/Admin/AdminHelper.php b/src/Admin/AdminHelper.php
index 4d4b8af2ed..c722b1adba 100644
--- a/src/Admin/AdminHelper.php
+++ b/src/Admin/AdminHelper.php
@@ -179,7 +179,7 @@ public function appendFormFieldElement(AdminInterface $admin, object $subject, s
$finalForm->setData($form->getData());
// back up delete field
- if (\count($toDelete) > 0) {
+ if ($childFormBuilder && \count($toDelete) > 0) {
$i = 0;
foreach ($finalForm->get($childFormBuilder->getName()) as $childField) {
if ($childField->has(self::FORM_FIELD_DELETE)) {
diff --git a/src/Admin/Extension/LockExtension.php b/src/Admin/Extension/LockExtension.php
index 818cfa4517..d277f1405e 100644
--- a/src/Admin/Extension/LockExtension.php
+++ b/src/Admin/Extension/LockExtension.php
@@ -42,7 +42,7 @@ public function configureFormFields(FormMapper $form): void
$data = $event->getData();
$form = $event->getForm();
- if (null === $data || $form->getParent()) {
+ if (!\is_object($data) || $form->getParent()) {
return;
}
diff --git a/src/Admin/UrlGeneratorInterface.php b/src/Admin/UrlGeneratorInterface.php
index 0018fed6fb..cf038c1484 100644
--- a/src/Admin/UrlGeneratorInterface.php
+++ b/src/Admin/UrlGeneratorInterface.php
@@ -69,7 +69,7 @@ public function generateUrl(string $name, array $parameters = [], int $reference
* @param array $parameters
*
* @return array
- * @phpstan-return array{route: string, routeParameters: array, routeAbsolute: bool}
+ * @phpstan-return array{route: string, routeParameters: array, routeAbsolute: bool}
*/
public function generateMenuUrl(string $name, array $parameters = [], int $referenceType = RoutingUrlGeneratorInterface::ABSOLUTE_PATH): array;
diff --git a/src/Block/AdminStatsBlockService.php b/src/Block/AdminStatsBlockService.php
index 85e32e2e5d..2b0352ee23 100644
--- a/src/Block/AdminStatsBlockService.php
+++ b/src/Block/AdminStatsBlockService.php
@@ -39,6 +39,9 @@ public function __construct(Environment $twig, Pool $pool)
public function execute(BlockContextInterface $blockContext, ?Response $response = null): Response
{
+ $template = $blockContext->getTemplate();
+ \assert(null !== $template);
+
$admin = $this->pool->getAdminByAdminCode($blockContext->getSetting('code'));
$datagrid = $admin->getDatagrid();
@@ -55,7 +58,7 @@ public function execute(BlockContextInterface $blockContext, ?Response $response
$datagrid->buildPager();
- return $this->renderPrivateResponse($blockContext->getTemplate(), [
+ return $this->renderPrivateResponse($template, [
'block' => $blockContext->getBlock(),
'settings' => $blockContext->getSettings(),
'admin' => $admin,
diff --git a/src/Bridge/Exporter/AdminExporter.php b/src/Bridge/Exporter/AdminExporter.php
index ac76f4a871..3e52807247 100644
--- a/src/Bridge/Exporter/AdminExporter.php
+++ b/src/Bridge/Exporter/AdminExporter.php
@@ -62,10 +62,11 @@ public function getAvailableFormats(AdminInterface $admin): array
public function getExportFilename(AdminInterface $admin, string $format): string
{
$class = $admin->getClass();
+ $namespaceSeparatorPos = strripos($class, '\\');
return sprintf(
'export_%s_%s.%s',
- strtolower(substr($class, strripos($class, '\\') + 1)),
+ strtolower(false !== $namespaceSeparatorPos ? substr($class, $namespaceSeparatorPos + 1) : $class),
date('Y_m_d_H_i_s', strtotime('now')),
$format
);
diff --git a/src/Command/ExplainAdminCommand.php b/src/Command/ExplainAdminCommand.php
index 78fc13ee7a..3b33f7a3a1 100644
--- a/src/Command/ExplainAdminCommand.php
+++ b/src/Command/ExplainAdminCommand.php
@@ -83,8 +83,8 @@ public function execute(InputInterface $input, OutputInterface $output): int
$output->writeln(sprintf(
' - % -25s % -15s % -15s',
$name,
- $fieldDescription->getType(),
- $fieldDescription->getTemplate()
+ $fieldDescription->getType() ?? '',
+ $fieldDescription->getTemplate() ?? ''
));
}
@@ -94,8 +94,8 @@ public function execute(InputInterface $input, OutputInterface $output): int
$output->writeln(sprintf(
' - % -25s % -15s % -15s',
$name,
- $fieldDescription->getType(),
- $fieldDescription->getTemplate()
+ $fieldDescription->getType() ?? '',
+ $fieldDescription->getTemplate() ?? ''
));
}
@@ -111,8 +111,8 @@ public function execute(InputInterface $input, OutputInterface $output): int
$output->writeln(sprintf(
' - % -25s % -15s % -15s',
$name,
- $fieldDescription->getType(),
- $fieldDescription->getTemplate()
+ $fieldDescription->getType() ?? '',
+ $fieldDescription->getTemplate() ?? ''
));
}
diff --git a/src/Command/GenerateObjectAclCommand.php b/src/Command/GenerateObjectAclCommand.php
index 48a25e671d..aced241a55 100644
--- a/src/Command/GenerateObjectAclCommand.php
+++ b/src/Command/GenerateObjectAclCommand.php
@@ -111,8 +111,10 @@ public function execute(InputInterface $input, OutputInterface $output): int
$securityIdentity = new UserSecurityIdentity($username, $this->getUserModelClass($input, $output));
}
- if (!$input->getOption('step') && $input->getOption('object_owner')) {
- $securityIdentity = new UserSecurityIdentity($input->getOption('object_owner'), $this->getUserModelClass($input, $output));
+
+ $objectOwner = $input->getOption('object_owner');
+ if (!$input->getOption('step') && $objectOwner) {
+ $securityIdentity = new UserSecurityIdentity($objectOwner, $this->getUserModelClass($input, $output));
}
$manipulatorId = sprintf('sonata.admin.manipulator.acl.object.%s', $admin->getManagerType());
diff --git a/src/Command/Validators.php b/src/Command/Validators.php
index 68ea5dbe61..1c74ed9b17 100644
--- a/src/Command/Validators.php
+++ b/src/Command/Validators.php
@@ -32,6 +32,8 @@ public static function validateUsername(?string $username): string
/**
* @throws \InvalidArgumentException
+ *
+ * @phpstan-return class-string
*/
public static function validateClass(string $class): string
{
diff --git a/src/DependencyInjection/Compiler/ExtensionCompilerPass.php b/src/DependencyInjection/Compiler/ExtensionCompilerPass.php
index 41ad88480e..f9773949ae 100644
--- a/src/DependencyInjection/Compiler/ExtensionCompilerPass.php
+++ b/src/DependencyInjection/Compiler/ExtensionCompilerPass.php
@@ -91,7 +91,7 @@ public function process(ContainerBuilder $container): void
}
/**
- * @param array>>>> $extensionMap
+ * @param array>>> $extensionMap
*/
private function getExtensionsForAdmin(string $id, Definition $admin, ContainerBuilder $container, array $extensionMap): array
{
@@ -156,19 +156,29 @@ private function getManagedClass(Definition $admin, ContainerBuilder $container)
}
/**
- * @param array|bool>> $config
+ * @param array|int|bool>> $config
*
- * @return array>>>> an array with the following structure.
+ * @return array>>> an array with the following structure
*
- * [
- * 'global' => ['' => ['' => ['priority' => ]]],
- * 'excludes' => ['' => ['' => ['priority' => ]]],
- * 'admins' => ['' => ['' => ['priority' => ]]],
- * 'implements' => ['' => ['' => ['priority' => ]]],
- * 'extends' => ['' => ['' => ['priority' => ]]],
- * 'instanceof' => ['' => ['' => ['priority' => ]]],
- * 'uses' => ['' => ['' => ['priority' => ]]],
- * ]
+ * @phpstan-param array,
+ * admins: array,
+ * implements: array,
+ * extends: array,
+ * instanceof: array,
+ * uses: array,
+ * priority: int,
+ * }> $config
+ * @phpstan-return array{
+ * global: array>,
+ * excludes: array>,
+ * admins: array>,
+ * implements: array>,
+ * extends: array>,
+ * instanceof: array>,
+ * uses: array>,
+ * }
*/
private function flattenExtensionConfiguration(array $config): array
{
@@ -189,6 +199,17 @@ private function flattenExtensionConfiguration(array $config): array
$options['global'] = [];
}
+ /**
+ * @phpstan-var array{
+ * global: array,
+ * excludes: array,
+ * admins: array,
+ * implements: array,
+ * extends: array,
+ * instanceof: array,
+ * uses: array,
+ * } $optionsMap
+ */
$optionsMap = array_intersect_key($options, $extensionMap);
foreach ($optionsMap as $key => $value) {
diff --git a/src/FieldDescription/BaseFieldDescription.php b/src/FieldDescription/BaseFieldDescription.php
index 55e3c5a2dd..3001148d20 100644
--- a/src/FieldDescription/BaseFieldDescription.php
+++ b/src/FieldDescription/BaseFieldDescription.php
@@ -79,7 +79,7 @@ abstract class BaseFieldDescription implements FieldDescriptionInterface
protected $mappingType;
/**
- * @var string|null the field name (of the form)
+ * @var string the field name (of the form)
*/
protected $fieldName;
@@ -105,6 +105,8 @@ abstract class BaseFieldDescription implements FieldDescriptionInterface
/**
* @var array the option collection
+ * @psalm-var FieldDescriptionOptions
+ * @phpstan-var array
*/
protected $options = [];
@@ -158,7 +160,7 @@ public function __construct(
}
}
- public function getFieldName(): ?string
+ public function getFieldName(): string
{
return $this->fieldName;
}
@@ -388,7 +390,7 @@ abstract protected function setParentAssociationMappings(array $parentAssociatio
*
* @return mixed
*/
- protected function getFieldValue(?object $object, ?string $fieldName)
+ protected function getFieldValue(?object $object, string $fieldName)
{
if ($this->isVirtual() || null === $object) {
return null;
diff --git a/src/FieldDescription/FieldDescriptionInterface.php b/src/FieldDescription/FieldDescriptionInterface.php
index 54aeb18016..675aaefd33 100644
--- a/src/FieldDescription/FieldDescriptionInterface.php
+++ b/src/FieldDescription/FieldDescriptionInterface.php
@@ -38,7 +38,7 @@
* identifier?: bool,
* inline?: string,
* label?: bool|string|null,
- * link_parameters?: array,
+ * link_parameters?: array,
* multiple?: bool,
* placeholder?: string,
* required?: bool,
@@ -53,7 +53,7 @@
* translation_domain?: string,
* type?: string,
* virtual_field?: bool
- * }
+ * }&array|array
*/
interface FieldDescriptionInterface
{
@@ -81,10 +81,8 @@ interface FieldDescriptionInterface
/**
* Returns the field name.
- *
- * @return string|null the field name
*/
- public function getFieldName(): ?string;
+ public function getFieldName(): string;
public function setName(string $name): void;
@@ -255,7 +253,8 @@ public function mergeOption(string $name, array $options = []): void;
/**
* Merge options values.
*
- * @param array $options
+ * @psalm-param FieldDescriptionOptions $options
+ * @phpstan-param array $options
*/
public function mergeOptions(array $options = []): void;
diff --git a/src/Form/FormMapper.php b/src/Form/FormMapper.php
index 34b0ca811c..fcecb1b8ab 100644
--- a/src/Form/FormMapper.php
+++ b/src/Form/FormMapper.php
@@ -24,6 +24,8 @@
* This class is use to simulate the Form API.
*
* @author Thomas Rabaix
+ *
+ * @psalm-import-type FieldDescriptionOptions from \Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface
*/
final class FormMapper extends BaseGroupedMapper
{
@@ -67,9 +69,11 @@ public function reorder(array $keys): self
/**
* @param FormBuilderInterface|string $name
* @param array $options
- * @param array $fieldDescriptionOptions
*
* @return static
+ *
+ * @psalm-param FieldDescriptionOptions $fieldDescriptionOptions
+ * @phpstan-param array $fieldDescriptionOptions
*/
public function add($name, ?string $type = null, array $options = [], array $fieldDescriptionOptions = []): self
{
diff --git a/src/Maker/AdminMaker.php b/src/Maker/AdminMaker.php
index 9850245908..e1e26c3b15 100644
--- a/src/Maker/AdminMaker.php
+++ b/src/Maker/AdminMaker.php
@@ -51,6 +51,7 @@ final class AdminMaker extends AbstractMaker
/**
* @var string
+ * @phpstan-var class-string
*/
private $modelClass;
@@ -65,7 +66,7 @@ final class AdminMaker extends AbstractMaker
private $adminClassBasename;
/**
- * @var string
+ * @var string|null
*/
private $controllerClassBasename;
diff --git a/src/Route/DefaultRouteGenerator.php b/src/Route/DefaultRouteGenerator.php
index 2fc214c8be..f836540e64 100644
--- a/src/Route/DefaultRouteGenerator.php
+++ b/src/Route/DefaultRouteGenerator.php
@@ -92,8 +92,10 @@ public function generateMenuUrl(
// if the admin is linked to a parent FieldDescription (ie, embedded widget)
if ($admin->hasParentFieldDescription()) {
+ /** @var array $linkParameters */
+ $linkParameters = $admin->getParentFieldDescription()->getOption('link_parameters', []);
// merge link parameter if any provided by the parent field
- $parameters = array_merge($parameters, $admin->getParentFieldDescription()->getOption('link_parameters', []));
+ $parameters = array_merge($parameters, $linkParameters);
$parameters['uniqid'] = $admin->getUniqid();
$parameters['code'] = $admin->getCode();
diff --git a/src/Route/RouteGeneratorInterface.php b/src/Route/RouteGeneratorInterface.php
index b37422972f..5997661241 100644
--- a/src/Route/RouteGeneratorInterface.php
+++ b/src/Route/RouteGeneratorInterface.php
@@ -33,7 +33,7 @@ public function generateUrl(AdminInterface $admin, string $name, array $paramete
*
* @return array
*
- * @phpstan-return array{route: string, routeParameters: array, routeAbsolute: bool}
+ * @phpstan-return array{route: string, routeParameters: array, routeAbsolute: bool}
*/
public function generateMenuUrl(AdminInterface $admin, string $name, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): array;
diff --git a/src/Security/Handler/AclSecurityHandlerInterface.php b/src/Security/Handler/AclSecurityHandlerInterface.php
index 0e4e7bfdfe..3f66eae763 100644
--- a/src/Security/Handler/AclSecurityHandlerInterface.php
+++ b/src/Security/Handler/AclSecurityHandlerInterface.php
@@ -64,7 +64,7 @@ public function getObjectAcl(ObjectIdentityInterface $objectIdentity): ?MutableA
*
* @throws \Exception
*
- * @return \SplObjectStorage mapping the passed object identities to ACLs
+ * @return \SplObjectStorage mapping the passed object identities to ACLs
*/
public function findObjectAcls(\Traversable $oids, array $sids = []): \SplObjectStorage;
diff --git a/src/Show/ShowMapper.php b/src/Show/ShowMapper.php
index 93a0dd72cf..51794e2d79 100644
--- a/src/Show/ShowMapper.php
+++ b/src/Show/ShowMapper.php
@@ -23,6 +23,8 @@
* This class is used to simulate the Form API.
*
* @author Thomas Rabaix
+ *
+ * @psalm-import-type FieldDescriptionOptions from FieldDescriptionInterface
*/
final class ShowMapper extends BaseGroupedMapper
{
@@ -62,11 +64,13 @@ public function getAdmin(): AdminInterface
/**
* @param FieldDescriptionInterface|string $name
- * @param array $fieldDescriptionOptions
*
* @throws \LogicException
*
* @return static
+ *
+ * @psalm-param FieldDescriptionOptions $fieldDescriptionOptions
+ * @phpstan-param array $fieldDescriptionOptions
*/
public function add($name, ?string $type = null, array $fieldDescriptionOptions = []): self
{
@@ -124,6 +128,9 @@ public function has(string $key): bool
return $this->list->has($key);
}
+ /**
+ * @return static
+ */
public function remove(string $key): self
{
$this->getAdmin()->removeShowFieldDescription($key);
diff --git a/src/Translator/Extractor/AdminExtractor.php b/src/Translator/Extractor/AdminExtractor.php
index 82acb1e25f..58612501d5 100644
--- a/src/Translator/Extractor/AdminExtractor.php
+++ b/src/Translator/Extractor/AdminExtractor.php
@@ -127,6 +127,16 @@ public function setPrefix($prefix): void
public function getLabel(string $label, string $context = '', string $type = ''): string
{
+ if (null === $this->catalogue) {
+ throw new \LogicException('The catalogue is not set.');
+ }
+ if (null === $this->labelStrategy) {
+ throw new \LogicException('The label strategy is not set.');
+ }
+ if (null === $this->domain) {
+ throw new \LogicException('The domain is not set.');
+ }
+
$label = $this->labelStrategy->getLabel($label, $context, $type);
$this->catalogue->set($label, $this->prefix.$label, $this->domain);
diff --git a/src/Twig/Extension/CanonicalizeExtension.php b/src/Twig/Extension/CanonicalizeExtension.php
index 9438f18a43..84227ad88f 100644
--- a/src/Twig/Extension/CanonicalizeExtension.php
+++ b/src/Twig/Extension/CanonicalizeExtension.php
@@ -57,7 +57,7 @@ public function getFunctions(): array
*/
public function getCanonicalizedLocaleForMoment(): ?string
{
- $locale = strtolower(str_replace('_', '-', $this->requestStack->getCurrentRequest()->getLocale()));
+ $locale = $this->getLocale();
// "en" language doesn't require localization.
if (('en' === $lang = substr($locale, 0, 2)) && !\in_array($locale, ['en-au', 'en-ca', 'en-gb', 'en-ie', 'en-nz'], true)) {
@@ -79,7 +79,7 @@ public function getCanonicalizedLocaleForMoment(): ?string
*/
public function getCanonicalizedLocaleForSelect2(): ?string
{
- $locale = str_replace('_', '-', $this->requestStack->getCurrentRequest()->getLocale());
+ $locale = $this->getLocale();
// "en" language doesn't require localization.
if ('en' === $lang = substr($locale, 0, 2)) {
@@ -104,4 +104,14 @@ public function getCanonicalizedLocaleForSelect2(): ?string
return $locale;
}
+
+ private function getLocale(): string
+ {
+ $request = $this->requestStack->getCurrentRequest();
+ if (null === $request) {
+ throw new \LogicException('The request stack is empty.');
+ }
+
+ return str_replace('_', '-', $request->getLocale());
+ }
}
diff --git a/src/Twig/Extension/RenderElementExtension.php b/src/Twig/Extension/RenderElementExtension.php
index 783be67903..a564f81615 100644
--- a/src/Twig/Extension/RenderElementExtension.php
+++ b/src/Twig/Extension/RenderElementExtension.php
@@ -266,7 +266,7 @@ private function render(
return sprintf(
$commentTemplate,
$fieldDescription->getFieldName(),
- $fieldDescription->getTemplate(),
+ $fieldDescription->getTemplate() ?? '',
$template->getSourceContext()->getName(),
$content,
$fieldDescription->getFieldName()
diff --git a/src/Twig/Extension/XEditableExtension.php b/src/Twig/Extension/XEditableExtension.php
index f82ed9579a..5500d86d70 100644
--- a/src/Twig/Extension/XEditableExtension.php
+++ b/src/Twig/Extension/XEditableExtension.php
@@ -99,24 +99,29 @@ public function getXEditableChoices(FieldDescriptionInterface $fieldDescription)
{
$choices = $fieldDescription->getOption('choices', []);
$catalogue = $fieldDescription->getOption('catalogue');
- $xEditableChoices = [];
- if (!empty($choices)) {
- reset($choices);
- $first = current($choices);
- // the choices are already in the right format
- if (\is_array($first) && \array_key_exists('value', $first) && \array_key_exists('text', $first)) {
- $xEditableChoices = $choices;
- } else {
- foreach ($choices as $value => $text) {
- if ($catalogue) {
- $text = $this->translator->trans($text, [], $catalogue);
- }
-
- $xEditableChoices[] = [
- 'value' => $value,
- 'text' => $text,
- ];
+
+ reset($choices);
+ $first = current($choices);
+ if (\is_array($first)) {
+ // the choice are already in the right format
+ $xEditableChoices = $choices;
+ } else {
+ $xEditableChoices = [];
+ foreach ($choices as $value => $text) {
+ if (\is_array($text)) {
+ // the choice is already in the right format
+ $xEditableChoices[] = $text;
+ break;
+ }
+
+ if ($catalogue) {
+ $text = $this->translator->trans($text, [], $catalogue);
}
+
+ $xEditableChoices[] = [
+ 'value' => $value,
+ 'text' => $text,
+ ];
}
}
diff --git a/src/Util/AdminObjectAclManipulator.php b/src/Util/AdminObjectAclManipulator.php
index 19671d8191..bd53e2ee7d 100644
--- a/src/Util/AdminObjectAclManipulator.php
+++ b/src/Util/AdminObjectAclManipulator.php
@@ -84,18 +84,22 @@ public function createAclRolesForm(AdminObjectAclData $data): FormInterface
public function updateAclUsers(AdminObjectAclData $data): void
{
- $aclValues = $data->getAclUsers();
$form = $data->getAclUsersForm();
+ if (null === $form) {
+ throw new \InvalidArgumentException('Cannot update Acl roles if the acl users form is not set.');
+ }
- $this->buildAcl($data, $form, $aclValues);
+ $this->buildAcl($data, $form, $data->getAclUsers());
}
public function updateAclRoles(AdminObjectAclData $data): void
{
- $aclValues = $data->getAclRoles();
$form = $data->getAclRolesForm();
+ if (null === $form) {
+ throw new \InvalidArgumentException('Cannot update Acl roles if the acl roles form is not set.');
+ }
- $this->buildAcl($data, $form, $aclValues);
+ $this->buildAcl($data, $form, $data->getAclRoles());
}
/**
@@ -105,8 +109,12 @@ public function updateAclRoles(AdminObjectAclData $data): void
*/
private function buildAcl(AdminObjectAclData $data, FormInterface $form, \Traversable $aclValues): void
{
- $masks = $data->getMasks();
$acl = $data->getAcl();
+ if (null === $acl) {
+ throw new \InvalidArgumentException('The acl cannot be null.');
+ }
+
+ $masks = $data->getMasks();
$matrices = $form->getData();
foreach ($aclValues as $aclValue) {
@@ -147,17 +155,15 @@ private function buildAcl(AdminObjectAclData $data, FormInterface $form, \Traver
$mask = $maskBuilder->get();
$index = null;
- $ace = null;
foreach ($acl->getObjectAces() as $currentIndex => $currentAce) {
if ($currentAce->getSecurityIdentity()->equals($securityIdentity)) {
$index = $currentIndex;
- $ace = $currentAce;
break;
}
}
- if ($ace) {
+ if (null !== $index) {
$acl->updateObjectAce($index, $mask);
} else {
$acl->insertObjectAce($securityIdentity, $mask);
diff --git a/src/Util/FormBuilderIterator.php b/src/Util/FormBuilderIterator.php
index 3318f0070f..794016c28a 100644
--- a/src/Util/FormBuilderIterator.php
+++ b/src/Util/FormBuilderIterator.php
@@ -31,7 +31,7 @@ final class FormBuilderIterator extends \RecursiveArrayIterator
private $prefix;
/**
- * @var \ArrayIterator
+ * @var \ArrayIterator
*/
private $iterator;
@@ -82,7 +82,7 @@ public function hasChildren(): bool
}
/**
- * @return array
+ * @return array
*/
private static function getKeys(FormBuilderInterface $formBuilder): array
{
diff --git a/src/Util/ObjectAclManipulator.php b/src/Util/ObjectAclManipulator.php
index bd46b8b6c0..1de44b4018 100644
--- a/src/Util/ObjectAclManipulator.php
+++ b/src/Util/ObjectAclManipulator.php
@@ -17,6 +17,7 @@
use Sonata\AdminBundle\Security\Handler\AclSecurityHandlerInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
+use Symfony\Component\Security\Acl\Model\ObjectIdentityInterface;
/**
* @author Thomas Rabaix
@@ -26,8 +27,8 @@ abstract class ObjectAclManipulator implements ObjectAclManipulatorInterface
/**
* Configure the object ACL for the passed object identities.
*
- * @param AdminInterface