symfony2admingenerator / GeneratorBundle

Admingenerator for Symfony. Parse YAML files to build customized backend.
MIT License
67 stars 29 forks source link

FOS User Generator and link for edit/show in list row #169

Open pjam opened 9 years ago

pjam commented 9 years ago

Hi guys.

I'm trying to add a generator to my app to manage users, but i get exception "No mapping found for field 'roles' on class...". I can't find anyone complaining about this problem for this version of the AdminGenerator, so I guess it could be some misconfiguration on my side? I've been using FOSUserBundle with symfony2admingenerator/userBundle without any problems.

Apart from that, there's nothing like we had in sf1.4 generator when we used the = sign in the list builder to create a link to the edit page right?

sescandell commented 9 years ago

Hi @pjam

Could you pleae show us:

Apart from that, there's nothing like we had in sf1.4 generator when we used the = sign in the list builder to create a link to the edit page right?

No, not for now... but PR are welcome.. that would be a great one waiting by many people I think (including me :yum: )

pjam commented 9 years ago

Hi @sescandell

Here is the generator.yml file, untouched from the generate-admin command:

generator: admingenerator.generator.doctrine
params:
    model: opencode\UtilizadorBundle\Entity\Utilizador
    namespace_prefix: opencode
    concurrency_lock: ~
    bundle_name: UtilizadorBundle
    pk_requirement: ~
    fields: ~
    object_actions:
        delete: ~
    batch_actions:
        delete: ~
builders:
    list:
        params:
            title: List for UtilizadorBundle
            display: ~
            actions:
                new: ~
            object_actions:
                edit: ~
                delete: ~
    excel:
        params: ~
        filename: ~
        filetype: ~
    new:
        params:
            title: New object for UtilizadorBundle
            display: ~
            actions:
                save: ~
                list: ~
    edit:
        params:
            title: "You're editing the object \"%object%\"|{ %object%: Utilizador.title }|"
            display: ~
            actions:
                save: ~
                list: ~
    show:
        params:
            title: "You're viewing the object \"%object%\"|{ %object%: Utilizador.title }|"
            display: ~
            actions:
                list: ~
                new: ~
    actions:
        params:
            object_actions:
                delete: ~
            batch_actions:
                delete: ~

and the entity class, plain and simple

<?php

namespace opencode\UtilizadorBundle\Entity;

use FOS\UserBundle\Model\User as BaseUtilizador;
use Doctrine\ORM\Mapping as ORM;

/**
 * Cliente
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Utilizador extends BaseUtilizador
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();
        // your own logic
    }
}

I would to help and make some PR when needed, but I'm still a Subversion user that still hadn't the time and willpower to learn how git works...

rpostolov commented 9 years ago

up

bobvandevijver commented 9 years ago

I'm not sure why you would get the exception you've stated, as the entity/config you posted do not indicate any error, and certainly not why it should search for a roles field. Are you sure that this is indeed the correct entity/config?

pjam commented 9 years ago

@bobvandevijver My entity extends FOS\UserBundle\Model\User, which has the field roles defined with type array.

Do you or anyone ( @sescandell , @ksn135 , @loostro ) has a working app with the generator for the users from FOS?

bobvandevijver commented 9 years ago

Ah, that would make sense. I do not use FOSUserBundle, so I would not know where to look now.

However, when I take a quick look at the FOS User class, I can only spot a non-mapped version of the roles attribute. Maybe you can try to add the following to the generator, see if that helpes:

params:
    fields:
        roles: 
            formOptions:
                mapped: false
sescandell commented 9 years ago

Hi @pjam

You have two ways to deal with roles:

Here is a fully working sample in one of my application:

<?php
namespace Sescandell\UserBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchy;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Form\FormBuilderInterface;
use Sescandell\UserBundle\Form\DataTransformer\RoleToValueTransformer;

class RolesType extends AbstractType
{
    /**
     * @var SecurityContext $securityContext
     */
    private $securityContext;
    /**
     * @var RoleHierarchy $roleHierarchy
     */
    private $roleHierarchy;
    /**
     * @var Translator $translator
     */
    private $translator;

    /**
     * Constructor
     *
     * @param RoleHierarchy   $roleHierarchy
     * @param SecurityContext $context
     */
    public function __construct(RoleHierarchy $roleHierarchy, SecurityContext $context, Translator $translator)
    {
        $this->roleHierarchy = $roleHierarchy;
        $this->securityContext = $context;
        $this->translator = $translator;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (!$options['multiple']) {
            $builder->addModelTransformer(new RoleToValueTransformer());
        }
    }

    /**
     * (non-PHPdoc)
     * @see \Symfony\Component\Form\AbstractType::setDefaultOptions()
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        /*
         * Ensure that a user is connected... This is dedicated to my application, you might not need it
         */
        if (!is_object($token = $this->securityContext->getToken())) {
            throw new AuthenticationException("You must be logged to access this feature !");
        }
        /*
         * Get settable roles by connected user
         */
        $reachableRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());
        $roles = array();
        foreach ($reachableRoles as $role) {
            $roles[$role->getRole()] = $this->translator->trans('admin.user.roles.'.strtolower($role->getRole()), array(), 'app');
        }

        /*
         * Set available roles to combobox
         */
        $resolver->setDefaults(array(
            'choices' => $roles,
            'required' => true,
            'multiple' => false,
        ));
    }

    /**
     * (non-PHPdoc)
     * @see \Symfony\Component\Form\AbstractType::getParent()
     */
    public function getParent()
    {
        return 'choice';
    }

    /**
     * (non-PHPdoc)
     * @see \Symfony\Component\Form\FormTypeInterface::getName()
     */

    public function getName()
    {
        return 'roles';
    }
}
<?php
namespace Sescandell\UserBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use FOS\UserBundle\Model\UserInterface;

class RoleToValueTransformer implements DataTransformerInterface
{
    /**
     * (non-PHPdoc)
     * @see \Symfony\Component\Form\DataTransformerInterface::transform()
     */
    public function transform($value)
    {
        if (!is_array($value) || empty($value)) {
            return null;
        }

        if (1 == count($value)) {
            return $value[0];
        }

        foreach ($value as $role) {
            if ($role != UserInterface::ROLE_DEFAULT) {
                return $role;
            }
        }

        return UserInterface::ROLE_DEFAULT;
    }

    /**
     * (non-PHPdoc)
     * @see \Symfony\Component\Form\DataTransformerInterface::reverseTransform()
     */
    public function reverseTransform($value)
    {
        return array($value);
    }

}

and the generator:

params:
    i18n_catalog: app
    model: Sescandell\UserBundle\Entity\User
    namespace_prefix: Sescandell
    entity_manager: default
    bundle_name: AppBundle
    fields:
        ...
        roles:
            label: admin.user.label.roles
            sortable: false
            dbType: string
            formType: roles
            getter: higherRole
            addFormOptions:
                required: true