<?php
namespace Products\NotificationsBundle\Util\ListBuilder;
use App\Model\Query\ConditionQuery\ConditionConfig;
use Cms\CoreBundle\Util\Doctrine\EntityManager;
use Doctrine\ORM\QueryBuilder;
use Products\NotificationsBundle\Entity\AbstractList;
use Products\NotificationsBundle\Entity\AbstractRecipient;
use Products\NotificationsBundle\Entity\AutomationRecord;
use Products\NotificationsBundle\Entity\NotificationsConfig;
use Products\NotificationsBundle\Entity\Profile;
use Products\NotificationsBundle\Entity\ProfileContact;
use Products\NotificationsBundle\Entity\ProfileRelationship;
use Products\NotificationsBundle\Entity\Recipients\AppRecipient;
use Products\NotificationsBundle\Entity\Recipients\EmailRecipient;
use Products\NotificationsBundle\Entity\Recipients\PhoneRecipient;
use Products\NotificationsBundle\Entity\Student;
/**
*
*/
abstract class AbstractListBuilder
{
public const ENTITY_MAPPING = [
Profile::class => self::ENTITIES__PROFILES,
AbstractRecipient::class => self::ENTITIES__RECIPIENTS,
EmailRecipient::class => self::ENTITIES__RECIPIENTS,
PhoneRecipient::class => self::ENTITIES__RECIPIENTS,
AppRecipient::class => self::ENTITIES__RECIPIENTS,
Student::class => self::ENTITIES__STUDENTS,
ProfileContact::class => self::ENTITIES__PROFILE_CONTACTS,
ProfileRelationship::class => self::ENTITIES__PROFILE_RELATIONSHIPS,
AutomationRecord::class => self::ENTITIES__PROFILE_AUTOMATION_RECORDS,
];
public const ENTITIES__PROFILES = 'profiles';
public const ENTITIES__RECIPIENTS = 'contacts';
public const ENTITIES__STUDENTS = 'students';
public const ENTITIES__PROFILE_CONTACTS = 'xrefs';
public const ENTITIES__PROFILE_RELATIONSHIPS = 'relationships';
public const ENTITIES__PROFILE_AUTOMATION_RECORDS = 'automations';
// DI
protected EntityManager $em;
/**
* The specific list for which this ListBuilder is working with.
*
* @var AbstractList|null
*/
private ?AbstractList $list;
/**
* @param EntityManager $em
* @param AbstractList|null $list
*/
public function __construct(
EntityManager $em,
?AbstractList $list = null
)
{
$this->em = $em;
$this->list = $list;
}
/**
* @param AbstractList|string $list
* @return bool
*/
abstract public static function supports($list): bool;
/**
* @return AbstractList
*/
public function getList(): AbstractList
{
if ( ! $this->list) {
throw new \Exception();
}
return $this->list;
}
/**
* @return ConditionConfig
*/
public function getConfig(): ConditionConfig
{
// TODO: need to find a way to cache this or something; maybe use resolvers???
$config = $this->em->getRepository(NotificationsConfig::class)->findOneBy([
'tenant' => $this->getList()->getTenant(),
]);
if ( ! $config instanceof NotificationsConfig) {
return new ConditionConfig();
}
return $config->getConfig();
}
/**
* @return QueryBuilder
*/
abstract public function build(): QueryBuilder;
/**
* @param AbstractList|null $list
* @return array
*/
abstract public function serialize(?AbstractList $list = null): array;
/**
* @param array $serialized
* @return AbstractList
*/
abstract public function unserialize(array $serialized): AbstractList;
/**
* @return QueryBuilder
*/
public function subquery(): QueryBuilder
{
return ($qb = $this->build())
// overwrite the select to just pick the ids
->select($qb->getRootAliases()[0].'.id')
// speed this up by removing the ordering
->resetDQLPart('orderBy');
}
/**
* @return string
*/
protected function identify(): string
{
if ($this->list->getId()) {
return strval($this->list->getId());
}
return spl_object_hash($this->list);
}
/**
* @param string $alias
* @return string
*/
protected function alias(string $alias): string
{
return sprintf(
'%s%s',
$alias,
$this->identify(),
);
}
/**
* @param string $param
* @return string
*/
protected function param(string $param): string
{
return sprintf(
'%s_%s',
$param,
$this->identify(),
);
}
/**
* @param string $alias
* @param string $prop
* @return string
*/
protected function prop(string $alias, string $prop): string
{
return sprintf(
'%s.%s',
$this->alias($alias),
$prop,
);
}
}