sonata-project / SonataAdminBundle

The missing Symfony Admin Generator
https://docs.sonata-project.org/projects/SonataAdminBundle
MIT License
2.11k stars 1.26k forks source link

Can't generate Acl with version > 3.49.1 #6063

Closed olivier-rey closed 4 years ago

olivier-rey commented 4 years ago

I can't generate acl from command anymore with new sonata-admin versions (~3.5)

bin/console sonata:admin:generate-object-acl

with version 3.50 i get bunch of:

The interface "ObjectAclManipulatorInterface" is not implemented for Sonata\AdminBundle\Command\GenerateObjectAclCommand: ignoring

with version 3.57:

No manipulators are implemented : ignoring

Works well with:

sonata-project/admin-bundle              3.49.1

Sonata packages

Other Sonata packages

sonata-project/block-bundle              3.18.4 3.18.4 Symfony SonataBlockBundle
sonata-project/cache                     2.0.1  2.0.1  Cache library
sonata-project/classification-bundle     3.11.1 3.11.1 Symfony SonataClassificationBundle
sonata-project/core-bundle               3.17.2 3.17.2 Symfony SonataCoreBundle (abandoned)
sonata-project/datagrid-bundle           2.5.0  2.5.0  Symfony SonataDatagridBundle
sonata-project/doctrine-extensions       1.6.0  1.6.0  Doctrine2 behavioral extensions
sonata-project/doctrine-orm-admin-bundle 3.13.0 3.15.0 Symfony Sonata / Integrate Doctrine ORM into the SonataAdminBundle
sonata-project/easy-extends-bundle       2.5.0  2.5.0  Symfony SonataEasyExtendsBundle
sonata-project/exporter                  1.11.1 1.11.1 Lightweight Exporter library
sonata-project/intl-bundle               2.7.0  2.7.0  Symfony SonataIntlBundle
sonata-project/media-bundle              3.23.1 3.24.0 Symfony SonataMediaBundle
sonata-project/user-bundle               4.5.1  4.5.2  Symfony SonataUserBundle

Symfony packages

$ composer show --latest 'symfony/*'
symfony/http-client           v4.4.7  v4.4.7  Symfony HttpClient component
symfony/http-client-contracts v1.1.8  v1.1.8  Generic abstractions related to HTTP clients
symfony/maker-bundle          v1.15.1 v1.15.1 Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.
symfony/mime                  v4.4.7  v4.4.7  A library to manipulate MIME messages
symfony/monolog-bundle        v3.5.0  v3.5.0  Symfony MonologBundle
symfony/phpunit-bridge        v3.4.39 v5.0.7  Symfony PHPUnit Bridge
symfony/polyfill-apcu         v1.15.0 v1.15.0 Symfony polyfill backporting apcu_* functions to lower PHP versions
symfony/polyfill-ctype        v1.15.0 v1.15.0 Symfony polyfill for ctype functions
symfony/polyfill-intl-icu     v1.15.0 v1.15.0 Symfony polyfill for intl's ICU-related data and classes
symfony/polyfill-intl-idn     v1.15.0 v1.15.0 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions
symfony/polyfill-mbstring     v1.15.0 v1.15.0 Symfony polyfill for the Mbstring extension
symfony/polyfill-php56        v1.15.0 v1.15.0 Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions
symfony/polyfill-php70        v1.15.0 v1.15.0 Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions
symfony/polyfill-php72        v1.15.0 v1.15.0 Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/polyfill-php73        v1.15.0 v1.15.0 Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions
symfony/polyfill-util         v1.15.0 v1.15.0 Symfony utilities for portability of PHP codes
symfony/security-acl          v3.0.4  v3.0.4  Symfony Security Component - ACL (Access Control List)
symfony/service-contracts     v1.1.8  v1.1.8  Generic abstractions related to writing services
symfony/swiftmailer-bundle    v2.6.7  v3.4.0  Symfony SwiftmailerBundle
symfony/symfony               v3.4.39 v4.4.7  The Symfony PHP framework
symfony/webpack-encore-bundle v1.7.3  v1.7.3  Integration with your Symfony app & Webpack Encore!

PHP version

$ php -v
PHP 7.1.33-15+0~20200419.36+debian9~1.gbp2384b3 (cli) (built: Apr 19 2020 08:44:42) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.1.33-15+0~20200419.36+debian9~1.gbp2384b3, Copyright (c) 1999-2018, by Zend Technologies
chico@seldon:~/sites/SNAM/randoPortail$ 

Thanks in advance for your help :)

VincentLanglet commented 4 years ago

Diff here https://github.com/sonata-project/SonataAdminBundle/compare/3.49.1...3.50.0

Commit https://github.com/sonata-project/SonataAdminBundle/commit/b0350529ef428108632ffa342f998b7243064ff8

Was it a BC-break @phansys ?

Maybe related to https://github.com/sonata-project/SonataAdminBundle/pull/5696

phansys commented 4 years ago

Was it a BC-break @phansys ?

Yes. See https://github.com/sonata-project/SonataAdminBundle/pull/5579#discussion_r291804779.

VincentLanglet commented 4 years ago

Seems like there is another.

$this->getContainer()->has($manipulatorId)

was returning something, but

public function __construct(Pool $pool, array $aclObjectManipulators, RegistryInterface $registry = null)

is certainly injecting an empty array in @olivier-rey situation.

This seems to be injected by the ObjectAclManipulatorCompilerPass.

How are declared your objectAclManipulators @olivier-rey ?

olivier-rey commented 4 years ago

@VincentLanglet Yes empty array on $aclObjectManipulators...

by checking objectAclManipulatorCompilerPass, i get an empty $availableManagers array as well.

the condition is_subclass_of is always false: For $id "sonata.admin.manipulator.acl.object.orm" $container->getDefinition($id)->getClass() returns "%sonata.admin.manipulator.acl.object.orm.class%"

The command works if i remove the !is_subclass_of part of the condition.

phansys commented 4 years ago

Could you please check with something like this?

$class = $container->getDefinition($id)->getClass();

if (!class_exists($class, false) && $container->hasParameter($class)) {
    $class = $container->getParameter($class);
}

if (0 !== strpos($id, 'sonata.admin.manipulator.acl.object.') || !is_subclass_of($class, ObjectAclManipulatorInterface::class)) {
    continue;
}
phansys commented 4 years ago

the condition is_subclass_of is always false: For $id "sonata.admin.manipulator.acl.object.orm" $container->getDefinition($id)->getClass() returns "%sonata.admin.manipulator.acl.object.orm.class%"

That's weird because the call to is_subclass() should be never executed if the service id is "sonata.admin.manipulator.acl.object.orm", since the condition 0 !== strpos($id, 'sonata.admin.manipulator.acl.object.') should be met first.

EDIT: Nevermind, I just realized that these conditions are around an OR operator.

olivier-rey commented 4 years ago

EDIT: Nevermind, I just realized that these conditions are around an OR operator.

You made me confused with your last comment, and i didn't see your EDIT message immediatly ;)

Declaring the $class first does't work as there is some null getDefinition().

The problem seems to be caused by the containerBuilder returning the parameter (%sonata.admin.manipulator.acl.object.orm.class%) and not the parameter value for some services...

1 - If i modify objectAclManipulatorCompilerPass with:

        foreach ($container->getDefinitions() as $definition) {
            dump($definition->getClass());
        }
        die;

bin/console ca:cl |grep manip

returns

"%sonata.admin.manipulator.acl.object.orm.class%"
"%sonata.admin.manipulator.acl.admin.class%"
"%sonata.admin.object.manipulator.acl.admin.class%"

I then compared with the debug:container command (with same kind of modification), and it's ok:

bin/console debug:container |grep -i manip

returns

"Sonata\DoctrineORMAdminBundle\Util\ObjectAclManipulator"
"Sonata\AdminBundle\Util\AdminAclManipulator"
"Sonata\AdminBundle\Util\AdminObjectAclManipulator"

2 - If i modify sonata-project/doctrine-orm-admin-bundle/src/Resources/config/security.xml <service id="sonata.admin.manipulator.acl.object.orm" class="%sonata.admin.manipulator.acl.object.orm.class%" public="true"/> for <service id="sonata.admin.manipulator.acl.object.orm" class="Sonata\DoctrineORMAdminBundle\Util\ObjectAclManipulator" public="true"/>

The Acl command works fine.

phansys commented 4 years ago

We can't modify the definition for "sonata.admin.manipulator.acl.object.orm" since it would be a BC break (even if currently using a class parameter as extension point is discouraged). Please, check with this snippet and let me know the result.

if (0 !== strpos($id, 'sonata.admin.manipulator.acl.object.') || null === $class = $container->getDefinition($id)->getClass()) {
    continue;
}

if (!class_exists($class, false) && $container->hasParameter($class) {
    $class = $container->getParameter($class);
}

if (!is_subclass_of($class, ObjectAclManipulatorInterface::class)) {
    continue;
}
olivier-rey commented 4 years ago

We can't modify the definition for "sonata.admin.manipulator.acl.object.orm" since it would be a BC break (even if currently using a class parameter as extension point is discouraged).

Yep sure...

Well this works:

 if (0 !== strpos($id, 'sonata.admin.manipulator.acl.object.') || null === $class = $container->getDefinition($id)->getClass()) {
     continue;
 }

 $class = str_replace("%","",$class);

 if (!class_exists($class, false) && $container->hasParameter($class)) {
     $class = $container->getParameter($class);
 }

 if (!is_subclass_of($class, ObjectAclManipulatorInterface::class)) {
     continue;
 }
phansys commented 4 years ago

Excellent @olivier-rey. I'd replace the call to str_replace() with trim():

if (0 !== strpos($id, 'sonata.admin.manipulator.acl.object.') || null === $class = $container->getDefinition($id)->getClass()) {
    continue;
}

// We trim the possible "%" characters around the class definition since it could be using "%parameter%" syntax.
$class = trim($class, '%');

if (!class_exists($class, false) && $container->hasParameter($class)) {
    $class = $container->getParameter($class);
}

if (!is_subclass_of($class, ObjectAclManipulatorInterface::class)) {
    continue;
}

Could you please submit a PR with the fix?

olivier-rey commented 4 years ago

This is my first PR on github... Mistake with #6075... Hope #6077 is fine :)