<?php
namespace Products\NotificationsBundle\Entity;
use App\Util\Locales;
use Cms\TenantBundle\Entity\TenantedEntity;
use Doctrine\ORM\Mapping as ORM;
use App\Model\Query\ConditionQuery\ConditionConfig;
use Symfony\Component\Yaml\Yaml;
/**
* Class NotificationsConfig
* @package Products\NotificationsBundle\Entity
*
* @ORM\Entity(
* repositoryClass = "Products\NotificationsBundle\Doctrine\Repository\Notifications\NotificationsConfigRepository",
* )
* @ORM\Table(
* name = "notis__notification_config",
* )
*/
class NotificationsConfig extends TenantedEntity
{
/**
* @var string|null
*
* @ORM\Column(
* type = "text",
* nullable = true,
* )
*/
protected ?string $yaml = null;
/**
* This is the customer-editable configuration that is avaible in the UIs to manage.
*
* @var ConditionConfig|null
*
* @ORM\Column(
* type = "condition_config",
* nullable = true,
* )
*/
protected ?ConditionConfig $customConfig = null;
/**
* This is the system-generated config that is only managed through code and is not able to be modified by any UI.
*
* @var ConditionConfig|null
*
* @ORM\Column(
* type = "condition_config",
* nullable = true,
* )
*/
protected ?ConditionConfig $baseConfig = null;
/**
* @var array $translationLocales
*
* @ORM\Column(
* type = "simple_array",
* nullable = true,
* )
*/
protected array $translationLocales = [];
/**
* @return ConditionConfig
*/
protected ?ConditionConfig $config = null;
/**
* @return string|null
*/
public function getYaml(): ?string
{
return $this->yaml;
}
/**
* @param string|null $yaml
* @return $this
*/
public function setYaml(?string $yaml): self
{
// set the yaml property
$this->yaml = $yaml ?: null;
// generate the config for the yaml if it is set to something
$this->customConfig = $yaml ? ConditionConfig::factory(Yaml::parse($yaml)) : null;
// need to clear the base config as it has been changed
$this->config = null;
return $this;
}
/**
* @return ConditionConfig|null
*/
public function getCustomConfig(): ?ConditionConfig
{
return $this->customConfig;
}
/**
* @return string
*/
public function getCustomConfigYaml(): string
{
return $this->getYaml() ?: '';
}
/**
* @return ConditionConfig|null
*/
public function getBaseConfig(): ?ConditionConfig
{
return $this->baseConfig;
}
/**
* @return string
*/
public function getBaseConfigYaml(): string
{
return $this->getBaseConfig() ? Yaml::dump(
$this->getBaseConfig()->jsonSerialize(),
10,
4,
) : '';
}
/**
* @param ConditionConfig|null $baseConfig
* @return $this
*/
public function setBaseConfig(?ConditionConfig $baseConfig): self
{
// set the property
$this->baseConfig = $baseConfig;
// need to clear the base config as it has been changed
$this->config = null;
return $this;
}
/**
* This will generate the "effective" or "final" configuration for a customer.
* Basically takes the custom and the base config and merges them together.
* The items defined in the base config will override any matching items (like a schema or dictionary) in the custom config.
*
* Note that when overriding, for example a dictionary, the merge will not merge the contents of two conflicting dictionaries together.
* The merge will simply replace the conflicting dictionary entirely with the one being merged in.
*
* NOTE: This is generally the method that you want to use when actually needing to utilize a ConditionConfig model to influence a UI, running a query, etc.
*
* @return ConditionConfig
*/
public function getConfig(): ConditionConfig
{
if ( ! $this->config) {
$this->config = new ConditionConfig();
if ($this->getCustomConfig()) {
$this->config->merge($this->getCustomConfig());
}
if ($this->getBaseConfig()) {
$this->config->merge($this->getBaseConfig());
}
}
return $this->config;
}
/**
* @return string
*/
public function getConfigYaml(): string
{
return Yaml::dump(
$this->getConfig()->jsonSerialize(),
10,
4,
);
}
/**
* @return array<string>
*/
public function getTranslationLocales(): array
{
return array_filter($this->translationLocales);
}
/**
* @return array
*/
public function getTranslationLanguages(): array
{
$languages = [];
foreach ($this->getTranslationLocales() as $translationLocale) {
$languages[] = Locales::CONVERSIONS[$translationLocale];
}
return $languages;
}
/**
* @return array
*/
public function getTranslationLanguagesHumanReadable(): array
{
$languages = [];
foreach ($this->getTranslationLanguages() as $translationLanguage) {
$languages[$translationLanguage] = Locales::ISO6391_HUMAN_READABLE[$translationLanguage];
}
return $languages;
}
/**
* @return array
*/
public function getTranslationLocalesHumanReadable(): array
{
$locales = [];
foreach ($this->getTranslationLocales() as $translationLocale) {
$locales[$translationLocale] = Locales::RFC4646_HUMAN_READABLE[$translationLocale];
}
return $locales;
}
/**
* @param array<string> $locales
* @return $this
*/
public function setTranslationLocales(array $locales): self
{
$this->translationLocales = [];
foreach ($locales as $locale) {
$this->addTranslationLocale($locale, false);
}
sort($this->translationLocales);
return $this;
}
/**
* @param string $locale
* @param bool $sort
* @return $this
*/
public function addTranslationLocale(string $locale, bool $sort = true): self
{
// make sure we have a legit locale
if ( ! Locales::isLocale($locale)) {
throw new \RuntimeException(
sprintf(
'Locale "%s" is not supported, must be one of: %s',
$locale,
implode(', ', Locales::RFC4646),
),
);
}
// only add it if it is not english (our default/base locale)
// and if it is not already in our set
if ($locale !== Locales::RFC4646_DEFAULT && ! in_array($locale, $this->translationLocales, true)) {
$this->translationLocales[] = $locale;
}
// handle sorting
if ($sort) {
sort($this->translationLocales);
}
return $this;
}
/**
* @param string $locale
* @param bool $sort
* @return $this
*/
public function removeTranslationLocale(string $locale, bool $sort = true): self
{
$index = array_search($locale, $this->translationLocales, true);
if ($index !== false) {
unset($this->translationLocales[$index]);
if ( ! $sort) {
$this->translationLocales = array_values($this->translationLocales);
}
}
if ($sort) {
sort($this->translationLocales);
}
return $this;
}
}