<?php
namespace Cms\LogBundle\Service;
use Cms\CoreBundle\Service\ContextManager;
use Cms\CoreBundle\Util\DateTimeUtils;
use Cms\CoreBundle\Util\Doctrine\EntityManager;
use Cms\LogBundle\Entity\RecentFeed;
use Cms\ModuleBundle\Entity\Draft;
use Cms\ModuleBundle\Entity\ModuleEntity;
use Cms\ModuleBundle\Entity\Proxy;
use DateTime;
use Platform\SecurityBundle\Entity\Identity\Account;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
final class FeedingService implements EventSubscriberInterface
{
/**
* @var array|RecentFeed[]
*/
protected $entries = [];
/**
* @var EntityManager
*/
protected $em;
/**
* @var ContextManager
*/
protected $cm;
/**
* @param EntityManager $em
* @param ContextManager $cm
*/
public function __construct(EntityManager $em, ContextManager $cm)
{
$this->em = $em;
$this->cm = $cm;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array
{
return [
KernelEvents::TERMINATE => ['onKernelTerminate'],
];
}
/**
* @param ModuleEntity $entity
* @param DateTime|null $timestamp
* @param Account|null $account
* @return $this
*/
public function log(ModuleEntity $entity, ?DateTime $timestamp = null, ?Account $account = null): self
{
// get the proxy for the entity that we have
$proxy = null;
switch (true) {
case $entity instanceof Proxy:
$proxy = $entity;
break;
case $entity instanceof Draft:
$proxy = $entity->getProxy();
break;
}
if ( ! $proxy instanceof Proxy) {
throw new \Exception();
}
// get the currently logged in, effective, user if no account was given specifically
if (empty($account)) {
$account = $this->cm->getGlobalContext()->getEffectiveAccount();
}
// if the user is not set, we want to skip this
if ( ! empty($account)) {
// try to find the existing log, create a new one if not
$entry = $this->em->getRepository(RecentFeed::class)->findOneByAccountAndProxy($account, $proxy);
if (empty($entry)) {
$entry = (new RecentFeed())
->setAccount($account)
->setProxy($proxy);
}
// save the name
$entry->setName($proxy->getData()->ui());
// need to force things when given
if ( ! $entry->isCreated()) {
$entry
->autoCreatedBy(false)
->setCreatedBy($account, false);
if ( ! empty($timestamp)) {
$entry
->autoCreatedAt(false)
->setCreatedAt($timestamp, false);
}
} else {
$entry
->autoUpdatedBy(false)
->setUpdatedBy($account, false);
if ( ! empty($timestamp)) {
$entry
->autoUpdatedAt(false)
->setUpdatedAt($timestamp, false);
}
}
// need to touch the entity in some way to force it to update in case all other data is the same
$entry->setChecksum(DateTimeUtils::now()->getTimestamp());
// spool the entry
$this->entries[] = $entry;
}
return $this;
}
/**
*
*/
public function onKernelTerminate(): void
{
if ( ! empty($this->entries)) {
$this->em->saveAll($this->entries);
$this->entries = [];
}
}
}