<?php
/**
* Channel Provider
*
* @author Vincent van Waasbergen <v.vanwaasbergen@visualmedia.nl>
*/
namespace VisualMedia\TranslationBundle\Service;
use Exception;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use VisualMedia\LisaBundle\Helper\Helper;
use VisualMedia\LisaBundle\Component\Interfaces\EntityInterface;
use VisualMedia\LisaBundle\Component\ManagerData;
use VisualMedia\TranslationBundle\Manager\BaseChannelManager;
use VisualMedia\TranslationBundle\Manager\BaseDomainManager;
use VisualMedia\TranslationBundle\Manager\BaseLocaleManager;
use VisualMedia\TranslationBundle\Entity\BaseChannel;
use VisualMedia\TranslationBundle\Entity\BaseDomain;
use VisualMedia\TranslationBundle\Entity\BaseLocale;
use VisualMedia\TranslationBundle\Form\Subscriber\SimpleContentsSubscriber;
use VisualMedia\TranslationBundle\Form\Subscriber\LocaleContentsSubscriber;
use VisualMedia\TranslationBundle\Form\Subscriber\ChannelLocaleContentsSubscriber;
/**
* Switch Link
*/
class SwitchLink
{
public $domain;
public $locale;
/**
* Constructor
*
* @param BaseDomain $domain
* @param BaseLocale $locale
*/
public function __construct(BaseDomain $domain, BaseLocale $locale)
{
$this->domain = $domain;
$this->locale = $locale;
}
}
/**
* Channel Provider
*/
class ChannelProvider
{
public const MODE_SIMPLE = 'simple';
public const MODE_LOCALE = 'locale';
public const MODE_CHANNEL_LOCALE = 'channel_locale';
/**
* @var BaseChannelManager
*/
protected $channelManager;
/**
* @var BaseDomainManager
*/
protected $domainManager;
/**
* @var BaseLocaleManager
*/
protected $localeManager;
/**
* @var RequestStack
*/
protected $requestStack;
/**
* @var ParameterBagInterface
*/
protected $params;
/**
* @var array
*/
protected $channels;
/**
* @var BaseChannel
*/
protected $currentChannel;
/**
* @var BaseDomain
*/
protected $currentDomain;
/**
* @var BaseLocale
*/
protected $currentLocale;
/**
* @var string
*/
protected $mode;
/**
* @param BaseChannelManager $channelManager
* @param BaseDomainManager $domainManager
* @param BaseLocaleManager $localeManager
* @param RequestStack $requestStack
* @param ParameterBagInterface $params
*/
public function __construct(BaseChannelManager $channelManager, BaseDomainManager $domainManager, BaseLocaleManager $localeManager, RequestStack $requestStack, ParameterBagInterface $params)
{
$this->channelManager = $channelManager;
$this->domainManager = $domainManager;
$this->localeManager = $localeManager;
$this->requestStack = $requestStack;
$this->params = $params;
}
/**
* @param string $mode
* @return void
*/
public function initialize(string $mode): void
{
$this->mode = $mode;
}
/**
* @return string
*/
public function getMode(): string
{
return $this->mode;
}
/**
* @return bool
*/
public function hasMultiple(): bool
{
return count($this->getChannels()) > 1;
}
/**
* @return BaseLocale|null
*/
public function getCurrentLocale(): ?BaseLocale
{
if ($this->currentLocale) {
return $this->currentLocale;
}
// no request, fallback default locale from config as param.
$locale = $this->params->get('locale') ?? 'nl_NL';
if (null !== $request = $this->requestStack->getMasterRequest()) {
$locale = strlen($request->getLocale()) > 2 ? $request->getLocale() : $request->getDefaultLocale();
}
if (null === $this->currentLocale = $this->currentLocale ?: $this->localeManager->getByLocale($locale)) {
$this->validate();
return $this->getCurrentLocale();
// if (!$request->hasSession()) {
// return new BaseLocale($locale);
// }
// throw new Exception(sprintf('Locale \'%s\' is not yet configured in the database.', $locale));
}
return $this->currentLocale;
}
/**
* @return BaseDomain|null
*/
public function getCurrentDomain(): ?BaseDomain
{
if ($this->currentDomain) {
return $this->currentDomain;
}
if (null === $request = $this->requestStack->getMasterRequest()) {
return null;
}
if (null === $this->currentDomain = $this->currentDomain ?: $this->getDomainByHost($request->getHost())) {
$this->validate();
return $this->getCurrentDomain();
// throw new Exception(sprintf('Domain with host \'%s\' is not yet configured in the database.', $request->getHost()));
}
return $this->currentDomain;
}
/**
* @return BaseChannel|null
*/
public function getCurrentChannel(): ?BaseChannel
{
if ($this->currentChannel) {
return $this->currentChannel;
}
if (null === $request = $this->requestStack->getMasterRequest()) {
return null;
}
$domain = $this->getCurrentDomain();
if (null === $this->currentChannel = $this->currentChannel ?: $domain->channel ?? null) {
$this->validate();
return $this->getCurrentChannel();
}
return $this->currentChannel;
}
/**
* @param string $host
* @return BaseDomain
*/
public function getDomainByHost(string $host): ?BaseDomain
{
return $this->domainManager->getByHost($host);
}
/**
* @return array
*/
public function getChannels(): array
{
return $this->channels = $this->channels ?: $this->channelManager->getIndex();
}
/**
* @param BaseChannel $channel
* @return array
*/
public function getSwitch(BaseChannel $channel): array
{
$switch = [];
foreach ($channel->domains as $domain) {
if (count($domain->locales) > 1) {
foreach ($domain->locales as $locale) {
$switch[] = $new = new SwitchLink($domain, $locale);
}
}
elseif ($channel->defaultLocale) {
$switch[] = $new = new SwitchLink($domain, $channel->defaultLocale);
}
}
return $switch;
}
/**
* @return array
*/
public function getLocalesForEntity(EntityInterface $entity): array
{
$locales = [];
foreach ($entity->channels as $channel) {
foreach ($channel->domains as $domain) {
if ($channel->defaultLocale) {
$locales[$channel->defaultLocale->code] = $channel->defaultLocale;
}
foreach ($domain->locales as $locale) {
$locales[$locale->code] = $locale;
}
}
}
return $locales;
}
/**
* @return void
*/
public function addContentsSubscriber(FormBuilderInterface $builder, array $options): void
{
switch ($this->getMode()) {
case static::MODE_SIMPLE: $builder->addEventSubscriber(new SimpleContentsSubscriber($this)); break;
case static::MODE_LOCALE: $builder->addEventSubscriber(new LocaleContentsSubscriber($this)); break;
case static::MODE_CHANNEL_LOCALE: $builder->addEventSubscriber(new ChannelLocaleContentsSubscriber($this)); break;
}
}
/**
* @return void
*/
public function validate(): void
{
$request = $this->requestStack->getMasterRequest();
$channels = $this->channelManager->getIndex();
$domains = $this->domainManager->getIndex();
$locales = $this->localeManager->getIndex();
if (!$locale = reset($locales)) {
$locales[] = $locale = new BaseLocale('nl_NL');
$this->localeManager->persist($locale);
}
if (!$channel = reset($channels)) {
$channels[] = $channel = new BaseChannel($request->getHost());
$channel->main = true;
$channel->defaultLocale = $locale;
$this->channelManager->persist($channel);
}
if (!$domain = reset($domains)) {
$domains[] = $domain = new BaseDomain($request->getHost());
$domain->channel = $channel;
$domain->identifier = 'main';
$domain->locales->add($locale);
$this->domainManager->persist($domain);
}
$this->currentChannel = $channel;
$this->currentDomain = $domain;
$this->currentLocale = $locale;
$this->channelManager->flush();
}
}