Skip to content
This repository has been archived by the owner on Jan 9, 2020. It is now read-only.

Commit

Permalink
Manage custom fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
webda2l committed Aug 3, 2014
1 parent 4c7fbc3 commit aa6c966
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 16 deletions.
6 changes: 6 additions & 0 deletions DependencyInjection/A2lixI18nDoctrineExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('services.xml');

$container->setParameter('a2lix_i18n_doctrine.manager_registry', $config['manager_registry']);

$container->setParameter('a2lix_i18n_doctrine.translatableTrait', $config['translatableTrait']);
$container->setParameter('a2lix_i18n_doctrine.translationTrait', $config['translationTrait']);
$container->setParameter('a2lix_i18n_doctrine.translatableFetchMode', $config['translatableFetchMode']);
$container->setParameter('a2lix_i18n_doctrine.translationFetchMode', $config['translationFetchMode']);
$container->setParameter('a2lix_i18n_doctrine.isRecursive', $config['isRecursive']);

// ORM
if ('doctrine' === $config['manager_registry']) {
Expand Down
20 changes: 18 additions & 2 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,24 @@ public function getConfigTreeBuilder()

$rootNode
->children()
->scalarNode('manager_registry')->defaultValue('doctrine')->end()
// ->booleanNode('enable_filters')->defaultTrue()->end()
->scalarNode('manager_registry')
->defaultValue('doctrine')
->end()
->scalarNode('translatableTrait')
->defaultValue('A2lix\I18nDoctrineBundle\Doctrine\ORM\Util\Translatable')
->end()
->scalarNode('translationTrait')
->defaultValue('A2lix\I18nDoctrineBundle\Doctrine\ORM\Util\Translation')
->end()
->enumNode('translatableFetchMode')
->values(array('EAGER', 'EXTRA_LAZY', 'LAZY'))
->defaultValue('LAZY')
->end()
->enumNode('translationFetchMode')
->values(array('EAGER', 'EXTRA_LAZY', 'LAZY'))
->defaultValue('LAZY')
->end()
->booleanNode('isRecursive')->defaultTrue()->end()
->end()
;

Expand Down
4 changes: 4 additions & 0 deletions Doctrine/Interfaces/ManyLocalesInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace A2lix\I18nDoctrineBundle\Doctrine\Interfaces;

/**
*
* @author David ALLIX
*/
interface ManyLocalesInterface
{
public function getLocales();
Expand Down
4 changes: 4 additions & 0 deletions Doctrine/Interfaces/OneLocaleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace A2lix\I18nDoctrineBundle\Doctrine\Interfaces;

/**
*
* @author David ALLIX
*/
interface OneLocaleInterface
{
public function getLocale();
Expand Down
9 changes: 9 additions & 0 deletions Doctrine/ODM/EventListener/ControllerListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@
Symfony\Component\HttpKernel\Event\FilterControllerEvent,
Doctrine\Common\Util\ClassUtils;

/**
* Controller Listener
*
* @author David ALLIX
*/
class ControllerListener extends BaseControllerListener
{
/**
*
* @param \Symfony\Component\HttpKernel\Event\FilterControllerEvent $event
*/
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
Expand Down
2 changes: 1 addition & 1 deletion Doctrine/ODM/EventListener/DoctrineListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
}

// Translatable object?
if ($this->isTranslatable($classMetadata->reflClass) && !$classMetadata->hasAssociation('translations')) {
if ($this->hasTrait($classMetadata->reflClass, $this->translatableTrait, $this->isRecursive) && !$classMetadata->hasAssociation('translations')) {
$classMetadata->mapManyEmbedded(array(
'fieldName' => 'translations',
'targetDocument' => $classMetadata->name . 'Translation',
Expand Down
12 changes: 11 additions & 1 deletion Doctrine/ORM/EventListener/ControllerListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@
Symfony\Component\HttpKernel\Event\FilterControllerEvent,
Doctrine\Common\Util\ClassUtils;

/**
* Controller Listener
*
* @author David ALLIX
*/
class ControllerListener extends BaseControllerListener
{
/**
*
* @param \Symfony\Component\HttpKernel\Event\FilterControllerEvent $event
* @return type
*/
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
Expand All @@ -26,7 +36,7 @@ public function onKernelController(FilterControllerEvent $event)
$reflectionMethod = $reflectionClass->getMethod($method);
if ($this->annotationReader->getMethodAnnotation($reflectionMethod, 'A2lix\I18nDoctrineBundle\Annotation\I18nDoctrine')) {
$this->om->getFilters()->disable('oneLocale');

} else {
$this->om->getFilters()->enable('oneLocale')->setParameter('locale', $event->getRequest()->getLocale());
}
Expand Down
85 changes: 79 additions & 6 deletions Doctrine/ORM/EventListener/DoctrineListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,47 @@

use A2lix\I18nDoctrineBundle\EventListener\DoctrineListener as BaseDoctrineListener,
Doctrine\ORM\Event\LoadClassMetadataEventArgs,
Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\ORM\Events;

/**
* Doctrine ORM Listener
*
* KnpDoctrineBehaviors (https://github.com/KnpLabs/DoctrineBehaviors/) inspiration
*
* @author David ALLIX
*/
class DoctrineListener extends BaseDoctrineListener
{
private $translatableTrait;
private $translationTrait;
private $translatableFetchMode;
private $translationFetchMode;
private $isRecursive;

/**
*
* @param string $translatableTrait
* @param string $translationTrait
* @param string $translatableFetchMode
* @param string $translationFetchMode
* @param boolean $isRecursive
*/
public function __construct($translatableTrait, $translationTrait, $translatableFetchMode, $translationFetchMode, $isRecursive)
{
$this->translatableTrait = $translatableTrait;
$this->translationTrait = $translationTrait;
$this->translatableFetchMode = $this->convertFetchString($translatableFetchMode);
$this->translationFetchMode = $this->convertFetchString($translationFetchMode);
$this->isRecursive = $isRecursive;
}

/**
*
* @param \Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs
* @return type
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
Expand All @@ -18,21 +54,27 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
}

// Translatable object?
if ($this->isTranslatable($classMetadata->reflClass) && !$classMetadata->hasAssociation('translations')) {
if ($this->hasTrait($classMetadata->reflClass, $this->translatableTrait, $this->isRecursive)
&& !$classMetadata->hasAssociation('translations')) {

$classMetadata->mapOneToMany(array(
'fieldName' => 'translations',
'mappedBy' => 'translatable',
'fetch' => $this->translationFetchMode,
'indexBy' => 'locale',
'cascade' => array('persist', 'merge', 'remove'),
'targetEntity' => $classMetadata->name . 'Translation'
));
}

// Translation object?
if ($classMetadata->reflClass->hasProperty('translatable') && !$classMetadata->hasAssociation('translatable')) {
if ($this->hasTrait($classMetadata->reflClass, $this->translationTrait, $this->isRecursive)
&& !$classMetadata->hasAssociation('translatable')) {

$classMetadata->mapManyToOne(array(
'fieldName' => 'translatable',
'inversedBy' => 'translations',
'fetch' => $this->translationFetchMode,
'joinColumns' => array(array(
'name' => 'translatable_id',
'referencedColumnName' => 'id',
Expand All @@ -42,18 +84,24 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
));

// Unique constraint
$name = $classMetadata->getTableName() . '_unique_translation';
$name = $classMetadata->getTableName() .'_unique_translation';
if (!$this->hasUniqueTranslationConstraint($classMetadata, $name)) {
$classMetadata->setPrimaryTable(array(
'uniqueConstraints' => array(array(
'name' => $name,
'columns' => array('translatable_id', 'locale')
)),
'name' => $name,
'columns' => array('translatable_id', 'locale')
)),
));
}
}
}

/**
*
* @param \Doctrine\ORM\Mapping\ClassMetadata $classMetadata
* @param type $name
* @return boolean
*/
protected function hasUniqueTranslationConstraint(ClassMetadata $classMetadata, $name)
{
if (!isset($classMetadata->table['uniqueConstraints'])) {
Expand All @@ -69,6 +117,31 @@ protected function hasUniqueTranslationConstraint(ClassMetadata $classMetadata,
return false;
}

/**
*
* @param type $fetchMode
* @return int
*/
private function convertFetchString($fetchMode)
{
if (is_int($fetchMode)) {
return $fetchMode;
}

switch ($fetchMode) {
case "EAGER":
return ClassMetadataInfo::FETCH_EAGER;
case "EXTRA_LAZY":
return ClassMetadataInfo::FETCH_EXTRA_LAZY;
default:
return ClassMetadataInfo::FETCH_LAZY;
}
}

/**
*
* @return type
*/
public function getSubscribedEvents()
{
return array(
Expand Down
10 changes: 10 additions & 0 deletions Doctrine/ORM/Filter/ManyLocalesFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
use Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\Filter\SQLFilter;

/**
*
* @author David ALLIX
*/
class ManyLocalesFilter extends SQLFilter
{
/**
*
* @param \Doctrine\ORM\Mapping\ClassMetaData $targetEntity
* @param type $targetTableAlias
* @return string
*/
public function addFilterConstraint(ClassMetaData $targetEntity, $targetTableAlias)
{
// Check if the entity implements the right interface
Expand Down
10 changes: 10 additions & 0 deletions Doctrine/ORM/Filter/OneLocaleFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@
use Doctrine\ORM\Mapping\ClassMetaData,
Doctrine\ORM\Query\Filter\SQLFilter;

/**
*
* @author David ALLIX
*/
class OneLocaleFilter extends SQLFilter
{
/**
*
* @param \Doctrine\ORM\Mapping\ClassMetaData $targetEntity
* @param type $targetTableAlias
* @return string
*/
public function addFilterConstraint(ClassMetaData $targetEntity, $targetTableAlias)
{
// Check if the entity implements the right interface
Expand Down
10 changes: 10 additions & 0 deletions EventListener/ControllerListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@
use Doctrine\Common\Annotations\Reader,
Doctrine\Common\Persistence\ObjectManager;

/**
* Controller Listener
*
* @author David ALLIX
*/
abstract class ControllerListener
{
protected $annotationReader;
protected $om;

/**
*
* @param \Doctrine\Common\Annotations\Reader $annotationReader
* @param \Doctrine\Common\Persistence\ObjectManager $om
*/
public function __construct(Reader $annotationReader, ObjectManager $om)
{
$this->annotationReader = $annotationReader;
Expand Down
27 changes: 21 additions & 6 deletions EventListener/DoctrineListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@

use Doctrine\Common\EventSubscriber;

/**
* Doctrine Listener
*
* @author David ALLIX
*/
abstract class DoctrineListener implements EventSubscriber
{
protected function isTranslatable(\ReflectionClass $reflClass, $isRecursive = false)
/**
*
* @param \ReflectionClass $reflClass
* @param type $traitName
* @param type $isRecursive
* @return boolean
*/
protected function hasTrait(\ReflectionClass $reflClass, $traitName, $isRecursive = false)
{
$isTranslatable = $reflClass->hasProperty('translations');
if (in_array($traitName, $reflClass->getTraitNames())) {
return true;
}

$parentClass = $reflClass->getParentClass();

while ($isRecursive && !$isTranslatable && $reflClass->getParentClass()) {
$reflClass = $reflClass->getParentClass();
$isTranslatable = $this->isTranslatable($reflClass, true);
if ((false === $isRecursive) || (false === $parentClass) || (null === $parentClass)) {
return false;
}

return $isTranslatable;
return $this->hasTrait($parentClass, $traitName, $isRecursive);
}

}
11 changes: 11 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@
<parameters>
<parameter key="a2lix_i18n_doctrine.listener.doctrine.class" />
<parameter key="a2lix_i18n_doctrine.listener.controller.class" />

<parameter key="a2lix_i18n_doctrine.translatableTrait" />
<parameter key="a2lix_i18n_doctrine.translationTrait" />
<parameter key="a2lix_i18n_doctrine.translatableFetchMode" />
<parameter key="a2lix_i18n_doctrine.translationFetchMode" />
<parameter key="a2lix_i18n_doctrine.isRecursive" />
</parameters>

<services>
<service id="a2lix_i18n_doctrine.listener.doctrine" class="%a2lix_i18n_doctrine.listener.doctrine.class%">
<argument>%a2lix_i18n_doctrine.translatableTrait%</argument>
<argument>%a2lix_i18n_doctrine.translationTrait%</argument>
<argument>%a2lix_i18n_doctrine.translatableFetchMode%</argument>
<argument>%a2lix_i18n_doctrine.translationFetchMode%</argument>
<argument>%a2lix_i18n_doctrine.isRecursive%</argument>
<tag name="doctrine.event_subscriber" />
</service>
<service id="a2lix_i18n_doctrine.listener.controller" class="%a2lix_i18n_doctrine.listener.controller.class%">
Expand Down

0 comments on commit aa6c966

Please sign in to comment.