Sylius / SyliusResourceBundle

Simpler CRUD for Symfony applications
https://sylius.com
MIT License
219 stars 155 forks source link

Issue using Sonata User #50

Closed bodrak closed 11 years ago

bodrak commented 11 years ago

Hi guys, I'm building an app with Sylius, everything was working fine before recent updates. My problem now comes from the events you implemented in the resource bundle. In the file LoadMetaDataSubscriber.php, on line 70:

        $eventArgs->getEntityManager()->getConfiguration()->getMetadataDriverImpl()->loadMetadataForClass($parent, $parentMetadata);

It gaves me an error on SonataUserBundle:

[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Sonata\UserBundle\Model\User' was not found in the chain configured namespaces FOS\UserBundle\Entity, Sonata\MediaBundle\Entity, Application\Sonata\MediaBundle\Entity, Sonata\UserBundle\Entity, Application\Sonata\UserBundle\Entity, blanked\SiteBundle\Entity, Sylius\Bundle\CartBundle\Entity, Sylius\Bundle\MoneyBundle\Model, Sylius\Bundle\SalesBundle\Model, Sylius\Bundle\CartBundle\Model, Sylius\Bundle\InventoryBundle\Model

Apparently sylius is searching for Sonata\UserBundle\Model\User and I am extending Sonata\UserBundle\Entity\User. Do I did something wrong? maybe on configuring sylius?

Thanks for help

molchanoviv commented 11 years ago

Looks like you should add the following to config.yml

doctrine:
    orm:
        entity_managers:
            default:
                mappings:
                    SonataUserBundle: ~
bodrak commented 11 years ago

Thanks for your reply, but this is of course already done. Sylius was working before update with sonata user, my config.yml

orm:
    auto_generate_proxy_classes: %kernel.debug%
    entity_managers:
        default:
            auto_mapping: true
            mappings:
                FOSUserBundle: ~
                SonataMediaBundle: ~
                ApplicationSonataMediaBundle: ~
                SonataUserBundle: ~
                ApplicationSonataUserBundle: ~

We can see in the error message that Sonata\UserBundle\Entity is registred! The problem comes from Sonata\UserBundle\Model, which is check now with the event listener of sylius resource.

molchanoviv commented 11 years ago

Ok. I'll take a look at you problem after i finish a PR for my main job. Can you describe your configuration in details?

bodrak commented 11 years ago

Thanks a lot for your help. Here is my configuration in the composer.json:

"require": {
    "php": ">=5.3.3",
    "symfony/symfony": "2.3.*",
    "doctrine/orm": ">=2.2.3,<2.4-dev",
    "doctrine/doctrine-bundle": "1.2.*",
    "twig/extensions": "1.0.*",
    "symfony/assetic-bundle": "2.3.*",
    "symfony/swiftmailer-bundle": "2.3.*",
    "symfony/monolog-bundle": "2.3.*",
    "sensio/distribution-bundle": "2.3.*",
    "sensio/framework-extra-bundle": "2.3.*",
    "sensio/generator-bundle": "2.3.*",
    "incenteev/composer-parameter-handler": "~2.0",
    "stof/doctrine-extensions-bundle": "dev-master",
    "friendsofsymfony/user-bundle": "1.3.*",
    "sonata-project/admin-bundle": "2.2.*@dev",
    "sonata-project/cache-bundle": "2.1.*@dev",
    "sonata-project/doctrine-orm-admin-bundle": "2.2.*@dev",
    "sonata-project/easy-extends-bundle": "2.1.*@dev",
    "sonata-project/intl-bundle": "2.2.*@dev",
    "sonata-project/user-bundle": "2.2.x-dev",
    "sonata-project/media-bundle": "2.2.*@dev",
    "winzou/console-bundle": "dev-master",
    "friendsofsymfony/facebook-bundle": "1.2.*",
    "jms/serializer-bundle": "0.12.*@dev",
    "friendsofsymfony/rest-bundle": "0.13.*@dev",
    "white-october/pagerfanta-bundle": "dev-master",
    "sylius/resource-bundle": "0.3.*@dev",
    "sylius/sales-bundle": "0.2.*@dev",
    "mathiasverraes/money": "dev-master",
    "sylius/money-bundle": "0.2.*@dev",
    "sylius/cart-bundle": "0.5.*@dev",
    "sylius/flow-bundle": "0.1.*@dev",
    "sylius/inventory-bundle": "0.3.*@dev"
},

So basically, I am using sonata admin, fosuser, sonata user, sonatamedia, fosfacebook.

Here is my AppKernel.php file:

    $bundles = array(
    new FOS\RestBundle\FOSRestBundle(),
    new JMS\SerializerBundle\JMSSerializerBundle($this),
    new Sylius\Bundle\ResourceBundle\SyliusResourceBundle(),
    new Sylius\Bundle\MoneyBundle\SyliusMoneyBundle(),
    new Sylius\Bundle\SalesBundle\SyliusSalesBundle(),
    new Sylius\Bundle\CartBundle\SyliusCartBundle(),
    new Sylius\Bundle\FlowBundle\SyliusFlowBundle(),
    new Sylius\Bundle\InventoryBundle\SyliusInventoryBundle(),
    new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
    new Symfony\Bundle\SecurityBundle\SecurityBundle(),
    new Symfony\Bundle\TwigBundle\TwigBundle(),
    new Symfony\Bundle\MonologBundle\MonologBundle(),
    new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
    new Symfony\Bundle\AsseticBundle\AsseticBundle(),
    new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
    new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
    new blanked\SiteBundle\blankedSiteBundle(),
    new FOS\UserBundle\FOSUserBundle(),
    new Sonata\BlockBundle\SonataBlockBundle(),
    new Sonata\CacheBundle\SonataCacheBundle(),
    new Sonata\jQueryBundle\SonatajQueryBundle(),
    new Sonata\EasyExtendsBundle\SonataEasyExtendsBundle(),
    new Sonata\AdminBundle\SonataAdminBundle(),
    new Sonata\IntlBundle\SonataIntlBundle(),
    new Knp\Bundle\MenuBundle\KnpMenuBundle(),
    new Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle(),
    new Sonata\UserBundle\SonataUserBundle('FOSUserBundle'),
    new Application\Sonata\UserBundle\ApplicationSonataUserBundle(),
    new Sonata\MediaBundle\SonataMediaBundle(),
    new Application\Sonata\MediaBundle\ApplicationSonataMediaBundle(),
    new FOS\FacebookBundle\FOSFacebookBundle(),
    new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
    );

(I just "blanked" the name of my main bundle)

Do you need something more? my entire config.yml file?

molchanoviv commented 11 years ago

Yes I'd like to see your config.yml and an entity which extends Sonata\UserBundle\Entity\User

bodrak commented 11 years ago

ok, here is my full config.yml file, the sylius part may be wrong, as it is what I used before the update of sylius:

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: facebookParameters.ini }
    - { resource: @ApplicationSonataUserBundle/Resources/config/services.yml }
    - { resource: @blankedSiteBundle/Resources/config/services.xml }
    - { resource: @blankedSiteBundle/Resources/config/services.yml }
    - { resource: @blankedSiteBundle/Resources/config/admin.xml }

framework:
    #esi:             ~
    translator:      { fallback: %locale% }
    secret:          %secret%
    router:
        resource: "%kernel.root_dir%/config/routing.yml"
        strict_requirements: ~
    form:            ~
    csrf_protection: ~
    validation:      { enable_annotations: true }
    templating:
        engines: ['twig']
        #assets_version: SomeVersionScheme
    default_locale:  "%locale%"
    trusted_proxies: ~
    session:         ~
    fragments:       ~

# Twig Configuration
twig:
    debug:            %kernel.debug%
    strict_variables: %kernel.debug%
    globals:
        facebookLocale:          %facebookLocale%

# Assetic Configuration
assetic:
    debug:          %kernel.debug%
    use_controller: false
    bundles:        [ ]
    #java: /usr/bin/java
    filters:
        cssrewrite: ~
        yui_js:
            jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.8pre.jar
        yui_css:
            jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.8pre.jar

# Doctrine Configuration
doctrine:
    dbal:
        driver:   %database_driver%
        host:     %database_host%
        port:     %database_port%
        dbname:   %database_name%
        user:     %database_user%
        password: %database_password%
        charset:  UTF8
        types:
            json: Sonata\Doctrine\Types\JsonType
    # if using pdo_sqlite as your database driver, add the path in parameters.yml
    # e.g. database_path: %kernel.root_dir%/data/data.db3
    # path:     %database_path%

    orm:
        auto_generate_proxy_classes: %kernel.debug%
        entity_managers:
            default:
                auto_mapping: true
                mappings:
                    FOSUserBundle: ~
                    SonataMediaBundle: ~
                    ApplicationSonataMediaBundle: ~
                    SonataUserBundle: ~
                    ApplicationSonataUserBundle: ~

# Swiftmailer Configuration
swiftmailer:
    transport: %mailer_transport%
    host:      %mailer_host%
    username:  %mailer_user%
    password:  %mailer_password%
    spool:     { type: memory }

# Stof Doctrine Configuration
stof_doctrine_extensions:
    default_locale: fr
    translation_fallback: true
    orm:
        default:
            #translatable: true
            timestampable: true
            sluggable: true

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: Application\Sonata\UserBundle\Entity\User
    group:
        group_class: Application\Sonata\UserBundle\Entity\Group
    profile:  # Authentication Form
        form:
            type:               blanked_user_profile
            handler:            fos_user.profile.form.handler.default
            name:               fos_user_profile_form
            validation_groups:  [Authentication] # Please note : this is not the default value
    registration:
        form:
            type: blanked_user_registration

sonata_admin:
    title: Admin Panel
    templates:
        ## default global templates
        layout:  SonataAdminBundle::standard_layout.html.twig
        ajax:    SonataAdminBundle::ajax_layout.html.twig

        ## default actions templates, should extend a global templates
        list:    SonataAdminBundle:CRUD:list.html.twig
        show:    SonataAdminBundle:CRUD:show.html.twig
        edit:    SonataAdminBundle:CRUD:edit.html.twig
        history: SonataAdminBundle:CRUD:history.html.twig
        preview: SonataAdminBundle:CRUD:preview.html.twig
        delete:  SonataAdminBundle:CRUD:delete.html.twig

sonata_block:
    default_contexts: [cms]
    blocks:
        sonata.admin.block.admin_list:
            contexts:   [admin]

        sonata.block.service.text:
        sonata.block.service.action:
        sonata.block.service.rss:

sonata_user:
    security_acl:     false
    class:
        user:         Application\Sonata\UserBundle\Entity\User
        group:        Application\Sonata\UserBundle\Entity\Group
    admin:                  # Admin Classes
        user:
            class:          Application\Sonata\UserBundle\Admin\UserAdmin
            controller:     SonataAdminBundle:CRUD
            translation:    SonataUserBundle

        group:
            class:          Application\Sonata\UserBundle\Admin\GroupAdmin
            controller:     SonataAdminBundle:CRUD
            translation:    SonataUserBundle
    profile:  # Profile Form (firstname, lastname, etc ...)
        form:
            type:               blanked_user_profile
            handler:            sonata.user.profile.form.handler.default
            name:               sonata_user_profile_form
            validation_groups:  [Profile] 

sonata_media:
    default_context: default
    class:
        media:              Application\Sonata\MediaBundle\Entity\Media
        gallery:            Application\Sonata\MediaBundle\Entity\Gallery
        gallery_has_media:  Application\Sonata\MediaBundle\Entity\GalleryHasMedia
    db_driver: doctrine_orm # or doctrine_mongodb
    contexts:
        default:  # the default context is mandatory
            providers:
                - sonata.media.provider.dailymotion
                - sonata.media.provider.youtube
                - sonata.media.provider.image
                - sonata.media.provider.file

            formats:
                small: { width: 100 , quality: 70}
                big:   { width: 500 , quality: 70}

    cdn:
        server:
            path: /blanked/web/uploads/media # http://media.sonata-project.org/

    filesystem:
        local:
            directory:  %kernel.root_dir%/../web/uploads/media
            create:     false
    providers:
        image:
            resizer: sonata.media.resizer.simple

knp_menu:
    twig:
        template: blankedSiteBundle:Menu:knp_menu.html.twig

#localizeddate
services:
    twig.extension.text:
       class: Twig_Extensions_Extension_Text
       tags:
           - { name: twig.extension }

    twig.extension.intl:
       class: Twig_Extensions_Extension_Intl
       tags:
           - { name: twig.extension }

    debug.twig.extension:
        class: Twig_Extensions_Extension_Debug
        tags: [{ name: 'twig.extension' }]

    my.facebook.user:
        class: Application\Sonata\UserBundle\Security\User\Provider\FacebookProvider
        arguments:
            facebook: "@fos_facebook.api"
            userManager: "@fos_user.user_manager"
            validator: "@validator"
            container: "@service_container"

fos_facebook:
  alias:  facebook
  app_id: %facebookAppId%
  secret: %facebookAppSecret%
  cookie: true
  permissions: [email, user_birthday]

sylius_sales:
    driver: doctrine/orm # Configure the doctrine orm driver used in documentation.
    classes:
        #sellable:
        #    model: blanked\SiteBundle\Entity\Product
        order:
            model: blanked\SiteBundle\Entity\ProductOrder

sylius_cart:
    #driver: doctrine/orm
    resolver: app.cart_item_resolver
    classes:
        cart:
            #model: blanked\SiteBundle\Entity\Cart
        item:
            #model: blanked\SiteBundle\Entity\CartItem
            form: blanked\SiteBundle\Form\Type\CartItemType
            #controller: blanked\SiteBundle\Controller\CartItemController

sylius_money:
    driver: doctrine/orm
    currency: CHF
    locale: fr

sylius_flow:
    storage: sylius.process_storage.session

sylius_inventory:
    driver: doctrine/orm
    backorders: false
    classes:
        unit:
            model: blanked\SiteBundle\Entity\InventoryUnit
        stockable:
            model: blanked\SiteBundle\Entity\Product

and the entity extending sonata user: the user.orm.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                  http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="Application\Sonata\UserBundle\Entity\User" table="fos_user_user" repository-class="Application\Sonata\UserBundle\Entity\UserRepository">

        <id name="id" column="id" type="integer">
            <generator strategy="AUTO" />
        </id>
        <one-to-many field="address" target-entity="Application\Sonata\UserBundle\Entity\Address" mapped-by="user">
            <cascade>
                <cascade-persist/>
            </cascade>
        </one-to-many>

        <one-to-many field="orders" target-entity="blanked\SiteBundle\Entity\ProductOrder" mapped-by="user">
        </one-to-many>

    </entity>

</doctrine-mapping>

or the Entity/User.php:

<?php
namespace Application\Sonata\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
use Sonata\UserBundle\Model\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
use blanked\SiteBundle\Entity\ProductOrder;
/**
 * @ORM\Table(name="fos_user_user")
 * @ORM\Entity(repositoryClass="Application\SonataUserBundle\Entity\UserRepository")
 */
class User extends BaseUser
{
/**
 * @var integer $id
 */
protected $id;
/**
 * @var string
 *
 * @ORM\Column(type="string", length=64, nullable=false)
 *
 * @Assert\NotBlank(message="Please enter your first name.", groups={"Registration", "Profile"})
 * @Assert\Length(
 *      min = "2",
 *      max = "64",
 *      minMessage = "Your first name must be at least {{ limit }} characters length",
 *      maxMessage = "Your first name cannot be longer than {{ limit }} characters length"
 * )
 */
protected $firstname;

/**
 * @var string
 *
 * @ORM\Column(type="string", length=64, nullable=false)
 *
 * @Assert\NotBlank(message="Please enter your last name.", groups={"Registration", "Profile"})
 * @Assert\Length(
 *      min = "2",
 *      max = "64",
 *      minMessage = "Your last name must be at least {{ limit }} characters length",
 *      maxMessage = "Your last name cannot be longer than {{ limit }} characters length"
 * )
 */
protected $lastname;

/**
 * @var string
 * @ORM\Column(type="string", length=1, nullable=false)
 * @Assert\NotBlank(message="Please enter your gender", groups={"Registration", "Profile"})
 */
protected $gender = UserInterface::GENDER_UNKNOWN;

/**
 * @var \DateTime
 *
 * @ORM\Column(type="date", nullable=false)
 * @Assert\DateTime(groups={"Registration", "Profile"})
 */
protected $dateOfBirth;

/**
 * @ORM\OneToMany(targetEntity="Application\Sonata\UserBundle\Entity\Address", mappedBy="user")
 * @ORM\JoinColumn()
 */
private $address;

/**
 * @ORM\OneToMany(targetEntity="blanked\SiteBundle\Entity\ProductOrder", mappedBy="user")
 * @ORM\JoinColumn()
 */
private $orders;

public function __construct()
{
    parent::__construct();
    $this->address = new ArrayCollection();
    $this->orders = new ArrayCollection();
}

public function serialize()
{
    return serialize(array($this->facebookUid, parent::serialize()));
}

public function unserialize($data)
{
    list($this->facebookUid, $parentData) = unserialize($data);
    parent::unserialize($parentData);
}

/**
 * Get id
 *
 * @return integer $id
 */
public function getId()
{
    return $this->id;
}
/**
 * Sets the email.
 *
 * @param string $email
 * @return User
 */
public function setEmail($email)
{
    $this->setUsername($email);

    return parent::setEmail($email);
}

public function addAddres(\Application\Sonata\UserBundle\Entity\Address $address)
{
  $this->address[] = $address;
  $address->setUser($this);
  return $this;
}

public function removeAddres(\Application\Sonata\UserBundle\Entity\Address $address)
{
  $this->address->removeElement($address);
}

public function getAddress()
{
  return $this->address;
}

public function addOrder(\blanked\SiteBundle\Entity\ProductOrder $order)
{
  $this->orders[] = $order;
  return $this;
}

public function removeOrder(\blanked\SiteBundle\Entity\ProductOrder $order)
{
  $this->orders->removeElement($order);
}

public function getOrders()
{
  return $this->orders;
}

/**
 * Get the full name of the user (first + last name)
 * @return string
 */
public function getFullName()
{
    return $this->getFirstname() . ' ' . $this->getLastname();
}

/**
 * @param Array
 */
public function setFBData($fbdata)
{
    if (isset($fbdata['id'])) {
        $this->setFacebookUid($fbdata['id']);
        $this->addRole('ROLE_FACEBOOK');
    }
    if (isset($fbdata['username'])) {
        $this->setFacebookName($fbdata['username']);
    }
    if (isset($fbdata['first_name'])) {
        $this->setFirstname($fbdata['first_name']);
    }
    if (isset($fbdata['last_name'])) {
        $this->setLastname($fbdata['last_name']);
    }
    if (isset($fbdata['email'])) {
        $this->setEmail($fbdata['email']);
    }
    if (isset($fbdata['birthday'])) {
        $this->setDateOfBirth(new \DateTime($fbdata['birthday']));
    }
    if (isset($fbdata['gender'])) {
        if($fbdata['gender']=='male') $this->setGender('m');
        else if($fbdata['gender']=='female') $this->setGender('f');
        else $this->setGender('u');

    }
    $this->setFacebookData($fbdata);
}
}
molchanoviv commented 11 years ago

Ok. I found a problem. We should check if mapping exists for loaded parent or not. I'll fix it ASAP.

bodrak commented 11 years ago

thank you, tell me when it's done.

molchanoviv commented 11 years ago

@bodrak Done. And already merged. Please check it in your configuration.

bodrak commented 11 years ago

thanks @molchanoviv , it seems to work correctly now.