<?php
namespace App\Library\Subscribers;
use App\Library\Database;
use App\Library\Event\GrapperEvent;
use App\Library\Event\GrapperProcessEvent;
use App\Library\Event\GrapperQueueEvent;
use App\models\acount;
use App\models\eadr;
use App\models\grapperLizenz;
use App\models\grapperQueue;
use App\models\grapperStatistik;
use DateTime;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Statement;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Process\Process;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class GrapperSubscriber implements EventSubscriberInterface
{
const COMMAND = '%s %s %s/bin/console rce:grapper:send %s %s';
const PHP_BIN = 'php8.2';
const ENV_BIN = '/usr/bin/env';
/**
* Defining required events
* @return \array[][]
*/
public static function getSubscribedEvents()
{
return [
GrapperEvent::EVENT => [
[ 'processCustomers', 1000 ],
],
GrapperQueueEvent::EVENT_FETCH=>[
['initQueueLizenz',900],
['insertQueueSendEmails', 850],
],
GrapperProcessEvent::EVENT_FETCH=>[
['initQueueLizenz',900],
],
GrapperQueueEvent::EVENT_RUN=>[
['grapperExecute', 1000],
],
GrapperEvent::EVENT_PROCESS_CUSTOMER=>[
[ 'initLizenz', 1000 ],
[ 'insertSendEmails', 500 ],
[ 'grapperStore', 100 ],
],
GrapperQueueEvent::EVENT_POST=>[
[
'finishQueueSend', 100,
]
],
];
}
/**
* @param EventDispatcherInterface $eventDispatcher
* @param Database $database
*/
public function __construct(
private readonly EventDispatcherInterface $eventDispatcher,
private readonly Database $database
){
}
public function initLizenz(GrapperEvent $event):void{
if($event->getCustomer() !== null && !$event->getLizenz() instanceof grapperLizenz){
/** @var grapperLizenz|null $lizenz */
$lizenz = $this->database->getData(grapperLizenz::class, grapperLizenz::LIZENZ, [$event->getCustomer()->getLizenzid()]);
if($lizenz===null){
$event->setNoLicense(true);
}else{
$event->setNoLicense(false);
$event->setLizenz($lizenz);
$event->getCustomer()->setLizenz($lizenz);
}
}
}
/**
* @param GrapperQueueEvent $event
* @return void
*/
public function grapperExecute(GrapperQueueEvent $event): void
{
$path = realpath(__DIR__.'/../../../');
$i=0;
foreach($event->getAddresses() as $row){
$event->addVerboseOutput('Remaining Mails: '.$event->getAcount()->getLizenz()->getRemainingMails().' <=> Sending Email '.$i);
dump($i);
if($i < $event->getAcount()->getLizenz()->getRemainingMails()){
$i++;
/** @var eadr $row */
$command = sprintf(self::COMMAND, self::ENV_BIN, self::PHP_BIN, $path, $event->getAcount()->getId(), $row->getId()).' -vvv';
$prozess = Process::fromShellCommandline($command);
$prozess->run();
$event->addVerboseOutput($prozess->getOutput());
if($prozess->isSuccessful()){
$event->addSuccess();
$event->addSuccessAddress($row->getEmail());
}else{
$event->addFailure();
$event->addFailureAddress($row->getEmail());
}
}
}
}
public function initQueueLizenz(GrapperQueueEvent|GrapperProcessEvent $event):void{
if($event->getAcount() !== null){
/** @var grapperLizenz|null $lizenz */
$lizenz = $this->database->getData(grapperLizenz::class, grapperLizenz::LIZENZ, [$event->getAcount()->getLizenzid()]);
if($lizenz===null){
$event->stopPropagation();
}else{
$event->getAcount()->setLizenz($lizenz);
}
}
}
/**
* Query Customers and execute one grepper run per customer
* @param GrapperEvent $event
* @return void
* @throws Exception
*/
public function processCustomers(GrapperEvent $event): void
{
if($event->isIndividualCustomer()){
$event->addVerboseOutput('Processing Specific Customer');
$stmt = $this->database->getConnection()->prepare(acount::GET_SPECIFIC_GRAPPER_CUSTOMERS);
$stmt->bindValue(1, $event->getIndividualCustomer());
}else{
$event->addVerboseOutput('Processing All Customers');
$stmt = $this->database->getConnection()->prepare(acount::GET_ALL_GRAPPER_CUSTOMERS);
}
$resultSet = $stmt->executeQuery();
while($row = $resultSet->fetchAssociative()){
$customer = new acount();
$customer->init($row);
$event->setCustomer($customer);
$this->eventDispatcher->dispatch($event, GrapperEvent::EVENT_PROCESS_CUSTOMER);
}
}
public function insertSendEmails(GrapperEvent $event): void
{
if($event->getCustomer() instanceof acount){
$stmt = $this->database->getConnection()->prepare(grapperStatistik::SELECT_COUNTER);
$stmt->bindValue(1, $event->getCustomer()->getId());
$stmt->bindValue(2, date('Y') . '-' . date('m') . '-01 00:00:00');
$stmt->bindValue(3, date('Y') . '-' . date('m') . '-' . date('t') . '-00:00:00');
$rowResult = $stmt->executeQuery();
if($event->getLizenz()===null){
file_put_contents(__DIR__.'/../../../var/log/error.log', date('d.m.Y H:i:s '). PHP_EOL.var_export($event, true).PHP_EOL.'=============='.PHP_EOL, FILE_APPEND);
$event->stopPropagation();
return;
}
$event->getLizenz()->setRemainingMails($event->getLizenz()->getMailsPerMonth() - $rowResult->rowCount());
$event->getCustomer()->getLizenz()->setRemainingMails($event->getLizenz()->getMailsPerMonth() - $rowResult->rowCount());
$event->addVerboseOutput('Processing Customer '.$event->getCustomer()->getId().' Adding Available Messages of '.$event->getLizenz()->getRemainingMails());
}
}
public function grapperStore(GrapperEvent $event):void{
if($event->getCustomer() instanceof acount){
$now = new \DateTime();
$next = $event->getCustomer()->getLastSend();
if(empty($next)){
$next = new \DateTime();
}
$delta = new \DateInterval($event->getCustomer()->getDatesBetweenSend());
$next->add($delta);
if($next >= $now){
$event->addVerboseOutput('Processing Customer '.$event->getCustomer()->getId().' Job is not up for Prossing unitl: '.$next->format('d.m.Y H:i:s'));
}else{
if($event->getLizenz()->getMailsPerMonth() > 0){
/** @var grapperQueue $jobExists */
$stmt = $this->database->getConnection()->prepare(grapperQueue::CHECK_JOB_EXISTS);
$stmt->bindValue(1, $event->getCustomer()->getId());
$rowResult = $stmt->executeQuery();
$event->addVerboseOutput('Processing Customer '.$event->getCustomer()->getId().' Jobs Exist: '.($rowResult->rowCount() < 1?'no':'yes'));
if($rowResult->rowCount() < 1){
$queue = new grapperQueue(null, (new DateTime()), null, $event->getCustomer()->getId());
$event->addVerboseOutput('Processing Customer '.$event->getCustomer()->getId().' adding Job');
$this->database->insert(grapperQueue::INSERT_QUEUE_STEP, $queue->toArrayInsert());
$this->database->update(acount::UPDATE_GRAPPER_LAST_SEND, [(new \DateTime())->format('Y-m-d H:i:s')],[$event->getCustomer()->getId()]);
}else{
$event->addVerboseOutput('Processing Customer '.$event->getCustomer()->getId().' Job already exists with id: '.$jobExists->getId());
}
}
}
}
}
/**
* @param GrapperQueueEvent $event
* @return void
* @throws Exception
*/
public function insertQueueSendEmails(GrapperQueueEvent $event):void{
if($event->getAcount() instanceof acount && $event->getAcount()->getId() > 0){
$stmt = $this->database->getConnection()->prepare(grapperStatistik::SELECT_COUNTER);
$stmt->bindValue(1, $event->getAcount()->getId());
$stmt->bindValue(2, date('Y') . '-' . date('m') . '-01 00:00:00');
$stmt->bindValue(3, date('Y') . '-' . date('m') . '-' . date('t') . '-00:00:00');
$rowResult = $stmt->executeQuery();
$event->getAcount()->getLizenz()->setRemainingMails($event->getAcount()->getLizenz()->getMailsPerMonth() - $rowResult->rowCount());
if($event->getAcount()->getLizenz()->getRemainingMails() > $event->getAcount()->getMailsPerBatch()){
$event->getAcount()->getLizenz()->setRemainingMails($event->getAcount()->getMailsPerBatch());
}
}
}
/**
* @throws Exception
*/
public function finishQueueSend(GrapperQueueEvent $event):void{
/** @var grapperQueue $item */
$item = $this->database->getData(grapperQueue::class, grapperQueue::CHECK_JOB_EXISTS, [0=>$event->getAcount()->getId()]);
if($event->getSuccess() > 0){
return;
}
//@todo check if all queue items have been processed
$item->setFinished(new DateTime());
$stmt = $this->database->getConnection()->prepare(grapperQueue::UPDATE_QUEUE_STEP);
$stmt->bindValue(2, $event->getQueue()->getId());
$stmt->bindValue(1, $item->getFinished()->format('Y-m-d H:i:s'));
$stmt->executeQuery();
$stmt = $this->database->getConnection()->prepare(acount::UPDATE_LAST_SEND);
$stmt->bindValue(1, $event->getQueue()->getId());
$stmt->executeQuery();
}
}