<?php

namespace Doctrine\Tests\ORMJT;

use Doctrine\ORM\Query;
use Doctrine\Common\Collections\ArrayCollection;

require_once __DIR__ . '/../TestInit.php';

/**
 * Functional tests for the Single Table Inheritance mapping strategy.
 *
 * @author robo
 */
class AdvancedAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
    protected function setUp() {
        parent::setUp();
        try {
            $this->_schemaTool->createSchema(array(
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\User'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\MerchantAccount'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Membership'),
                $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Privilege')
            ));
        } catch (\Exception $e) {
            // Swallow all exceptions. We do not test the schema tool here.
        }
    }

    public function testIssue()
    {
        $user = new User;
        $merchantAccount = new MerchantAccount;
        $privilege = new Privilege;
        $membership = new Membership($user, $merchantAccount);
        $membership->addPrivilege($privilege);

        $this->_em->persist($user);
        $this->_em->persist($merchantAccount);
        $this->_em->persist($privilege);

        $this->_em->flush();

        $this->_em->persist($membership);

        $this->_em->flush();


        $membership->getPrivileges()->clear();

        $this->_em->flush();

        $this->assertTrue(true);
    }
}


/**
 * @Entity
 * @Table(name="mch_account")
 */
class MerchantAccount
{
    /**
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var bigint $accountid
     */
    protected $accountid;
}

/**
 * @Entity(repositoryClass="Repository\User\PrivilegeRepository")
 * @Table(name="acl_privilege")
 */
class Privilege
{
    /**
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var integer
     */
    protected $privilegeid;
}

/**
 * @Entity
 * @Table(name="user_account")
 */
class User {
    /**
     * @Id @GeneratedValue
     * @Column(type="bigint")
     * @var integer
     */
    protected $uid;

    /**
     * @OneToMany(targetEntity="Membership", mappedBy="userAccount", cascade={"persist"})
     * @JoinColumn(name="uid", referencedColumnName="uid")
     */
    protected $memberships;

    public function __construct()
    {
        $this->memberships = new ArrayCollection;
    }

    public function getMemberships()
    {
        return $this->memberships;
    }

    public function addMembership(Membership $membership)
    {
        $this->memberships[] = $membership;
    }
}

/**
 * @Entity
 * @Table(name="mch_account_member")
 * @HasLifecycleCallbacks
 */
class Membership
{
    /**
     * @Id
     * @ManyToOne(targetEntity="User", inversedBy="memberships")
     * @JoinColumn(name="uid", referencedColumnName="uid")
     */
    protected $userAccount;

    /**
     * @Id
     * @ManyToOne(targetEntity="MerchantAccount")
     * @JoinColumn(name="mch_accountid", referencedColumnName="accountid")
     */
    protected $merchantAccount;

    /**
     * @ManyToMany(targetEntity="Privilege", indexBy="privilegeid")
     * @JoinTable(name="user_mch_account_privilege",
     *   joinColumns={
     *       @JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
     *       @JoinColumn(name="uid", referencedColumnName="uid")
     *   },
     *   inverseJoinColumns={
     *       @JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
     *   }
     * )
     */
    protected $privileges;

    public function __construct(User $user, MerchantAccount $merchantAccount)
    {
        $this->userAccount = $user;
        $this->merchantAccount = $merchantAccount;
        $this->privileges = new ArrayCollection();
    }

    public function addPrivilege($privilege)
    {
        $this->privileges[] = $privilege;
    }

    public function getPrivileges()
    {
        return $this->privileges;
    }
}