<?php
namespace Oro\Bundle\AddressBundle\Form\EventListener;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Oro\Bundle\AddressBundle\Entity\Country;
use Oro\Bundle\AddressBundle\Entity\Repository\RegionRepository;
class AddressCountryAndRegionSubscriber implements EventSubscriberInterface
{
private $om;
/**
* Form factory.
*
* @var FormFactoryInterface
*/
private $factory;
/**
* Constructor.
*
* @param ObjectManager $om
* @param FormFactoryInterface $factory
*/
public function __construct(ObjectManager $om, FormFactoryInterface $factory)
{
$this->om = $om;
$this->factory = $factory;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit'
);
}
/**
* Removes or adds a region field based on the country set.
*
* @param FormEvent $event
*/
public function preSetData(FormEvent $event)
{
$address = $event->getData();
$form = $event->getForm();
if (null === $address) {
return;
}
/** @var $country \Oro\Bundle\AddressBundle\Entity\Country */
$country = $this->om->getRepository('OroAddressBundle:Country')->find('US');
if (null === $country) {
return;
}
if ($country->hasRegions()) {
if ($form->has('region')) {
$regionTypeConfig = $form->get('region')->getConfig();
$config = $regionTypeConfig->getOptions();
unset($config['choice_list']);
unset($config['choices']);
$formType = $regionTypeConfig->getType()->getName();
} else {
$config = array();
$formType = 'oro_region';
}
$config['country'] = $country;
$config['query_builder'] = $this->getRegionClosure($country);
if (array_key_exists('auto_initialize', $config)) {
$config['auto_initialize'] = false;
}
$form->add(
$this->factory->createNamed(
'region',
$formType,
null, //add here saved region
$config
)
);
}
}
/**
* Removes or adds a region field based on the country set on submitted form.
*
* @param FormEvent $event
*/
public function preSubmit(FormEvent $event)
{
$data = $event->getData();
/** @var $country \Oro\Bundle\AddressBundle\Entity\Country */
$country = $this->om->getRepository('OroAddressBundle:Country')
->find(isset($data['country']) ? $data['country'] : false);
if ($country && $country->hasRegions()) {
$form = $event->getForm();
$config = $form->get('region')->getConfig()->getOptions();
unset($config['choice_list']);
unset($config['choices']);
$config['country'] = $country;
$config['query_builder'] = $this->getRegionClosure($country);
if (array_key_exists('auto_initialize', $config)) {
$config['auto_initialize'] = false;
}
$form->add(
$this->factory->createNamed(
'region',
$form->get('region')->getConfig()->getType()->getName(),
null,
$config
)
);
} else {
// do not allow saving region select in case when region was filled as text
unset($data['region']);
}
$event->setData($data);
}
/**
* @param Country $country
* @return callable
*/
protected function getRegionClosure(Country $country)
{
return function (RegionRepository $regionRepository) use ($country) {
return $regionRepository->getCountryRegionsQueryBuilder($country);
};
}
}