Select Git revision
ProcessService.php

Antony Le Courtes authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ProcessService.php 14.28 KiB
<?php
namespace UnicaenSignature\Service;
use DoctrineModule\Persistence\ProvidesObjectManager;
use Exception;
use Laminas\EventManager\EventManager;
use UnicaenSignature\Entity\Db\Process;
use UnicaenSignature\Entity\Db\ProcessStep;
use UnicaenSignature\Entity\Db\Signature;
use UnicaenSignature\Entity\Db\SignatureFlow;
use UnicaenSignature\Entity\Db\SignatureObserver;
use UnicaenSignature\Entity\Db\SignatureRecipient;
use UnicaenSignature\Entity\Repository\ProcessRepository;
use UnicaenSignature\Event\ProcessEvent;
use UnicaenSignature\Exception\SignatureException;
class ProcessService
{
use
LoggerServiceAwareTrait,
ProvidesObjectManager,
SharedEventManagerAwareTrait,
SignatureConfigurationServiceAwareTrait,
SignatureServiceAwareTrait;
/**
* @return ProcessRepository
*/
protected function getProcessRepository(): ProcessRepository
{
return $this->getObjectManager()->getRepository(Process::class);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @return SignatureFlow[]
*/
public function getSignatureFlows(): array
{
return $this->getSignatureService()->getSignatureFlows();
}
public function getSignatureFlow(int $id): SignatureFlow
{
return $this->getSignatureService()->getSignatureFlowById($id);
}
/**
* @return Process[]
*/
public function getProcesses(): array
{
return $this->getObjectManager()->getRepository(Process::class)->findAll();
}
/**
* @param int $processId
*
* @return Process
* @throws SignatureException
*/
public function getProcessById(int $processId): Process
{
try {
return $this->getObjectManager()->getRepository(Process::class)->find($processId);
} catch (Exception $e) {
$this->getLoggerService()->errorLogAndThrow($e, "Impossible de charger le processus '$processId'");
}
}
/**
* @param int $processId
*
* @return void
* @throws SignatureException
*/
public function deleteProcessById(int $processId): void
{
$this->deleteProcess($this->getProcessById($processId));
}
/**
* Suppression d'un processus.
*
* @param Process $process
* @return void
* @throws SignatureException
*/
public function deleteProcess(Process $process): void
{
try {
// Emplacement du document
$document = $this->getSignatureConfigurationService()->getDocumentsLocation()
. DIRECTORY_SEPARATOR
. $process->getDocumentName();
foreach ($process->getSteps() as $step) {
$signature = $step->getSignature();
$this->getSignatureService()->deleteSignature($signature, false, false);
$this->getObjectManager()->remove($step);
}
$this->getObjectManager()->remove($process);
$this->getObjectManager()->flush();
if (!@unlink($document)) {
$err = error_get_last()['message'] ?? "unknown error";
$this->getLoggerService()->warning("Impossible de supprimer le document '$document' : $err");
}
} catch (Exception $e) {
$this->getLoggerService()->errorLogAndThrow($e, "Impossible de supprimer le processus");
}
}
/**
* Retourne les informations du document du processus.
*
* @param Process $process
* @return array
* @throws SignatureException
*/
public function getProcessDocumentDatas(Process $process): array
{
$docDir = $this->getSignatureConfigurationService()->getDocumentsLocation();
$docName = $process->getDocumentName();
$docPath = $docDir . DIRECTORY_SEPARATOR . $docName;
$docMime = mime_content_type($docPath);
$docDatas = file_get_contents($docPath);
return [
'name' => $docName,
'mime' => $docMime,
'path' => $docPath,
'datas' => $docDatas,
];
}
/**
* Création d'un processus vide.
*
* @param string $documentName
* @param int $signatureFlowId
* @return Process
*/
public function createUnconfiguredProcess(string $documentName, int $signatureFlowId): Process
{
$process = new Process();
$this->getObjectManager()->persist($process);
$process->setDocumentName($documentName)
->setStatus(Signature::STATUS_PROCESS_UNCONFIGURED)
->setSignatureFlow($this->getSignatureFlow($signatureFlowId));
$this->getObjectManager()->flush();
return $process;
}
/**
* Configuration du processus
*
* [
* 'steps':[
* 'label': string,
* 'description': string,
* 'allSignToComplete': boolean,
* 'letterfilename': string,
* 'level': string,
* 'order': integer,
* 'recipients': [
* {'firstname': string, 'lastname': string, 'email': string }
* ]
* ]
*
* @param Process $process
* @param array $jsonDatas
* @return void
* @throws SignatureException
*/
public function configureProcess(Process $process, array $jsonDatas): void
{
$signatureFlow = $process->getSignatureFlow();
$process->setDateCreated(new \DateTime())
->setStatus(Signature::STATUS_SIGNATURE_DRAFT);
foreach ($jsonDatas['steps'] as $stepData) {
$signatureFlowStep = $signatureFlow->getStepAtOrder($stepData['order']);
// Création des étapes
$processStep = new ProcessStep();
$this->getObjectManager()->persist($processStep);
$processStep->setSignatureFlowStep($signatureFlowStep);
$processStep->setProcess($process);
$process->getSteps()->add($processStep);
// Création de la signature
$signature = new Signature();
$this->getObjectManager()->persist($signature);
$signature->setDocumentPath($process->getDocumentName())
->setStatus(Signature::STATUS_SIGNATURE_DRAFT)
->setDateCreated(new \DateTime())
->setLabel($process->getLabel() . ' - ' . $stepData['label'])
->setContextShort($stepData['context_subject'] ?? "")
->setContextLong($stepData['context_body'] ?? "")
->setDescription($stepData['description'])
->setAllSignToComplete($stepData['allSignToComplete'])
->setNotificationsRecipients($signatureFlowStep->isNotificationsRecipients())
->setLetterfileKey($stepData['letterfilename'])
->setOrder($signatureFlowStep->getOrder())
->setType($stepData['level']);
$processStep->setSignature($signature);
foreach ($stepData['recipients'] as $recipientData) {
$signatureRecipient = new SignatureRecipient();
$this->getObjectManager()->persist($signatureRecipient);
$signatureRecipient->setSignature($signature)
->setStatus(Signature::STATUS_SIGNATURE_DRAFT)
->setLastname($recipientData['lastname'])
->setFirstname($recipientData['firstname'])
->setEmail($recipientData['email']);
$signature->getRecipients()->add($signatureRecipient);
}
foreach ($stepData['observers'] as $observerData) {
$signatureObserver = new SignatureObserver();
$this->getObjectManager()->persist($signatureObserver);
$signatureObserver->setSignature($signature)
->setLastname($observerData['lastname'])
->setFirstname($observerData['firstname'])
->setEmail($observerData['email']);
$signature->getObservers()->add($signatureObserver);
}
}
try {
$this->getObjectManager()->flush();
} catch (Exception $e) {
$this->getLoggerService()->errorLogAndThrow($e, 'Impossible de configurer la procédure');
}
}
/**
* @param int $idProcess
* @param bool $forceFirstSend
* @return void
* @throws SignatureException
* @see trigger
*/
public function triggerById(int $idProcess, bool $forceFirstSend = false)
{
$this->trigger($this->getProcessById($idProcess), $forceFirstSend);
}
/**
* Déclenchement / recalcule du processus.
*
* @param Process $process
* @param bool $forceFirstSend
* @return void
* @throws SignatureException
*/
public function trigger(Process $process, bool $forceFirstSend = false): void
{
if ($process->isSendable() && $forceFirstSend) {
try {
$process->setCurrentStep(1);
$processStep = $process->getStep();
$process->setStatus(Signature::STATUS_SIGNATURE_WAIT);
$this->getObjectManager()->flush();
$this->getObjectManager()->refresh($process);
$this->getObjectManager()->refresh($processStep);
$this->getSignatureService()->sendSignature($processStep->getSignature());
$this->triggerProcessEvent($process, ProcessEvent::EVENT_TYPE_START);
} catch (Exception $e) {
$this->getLoggerService()->errorLogAndThrow(
$e,
"Impossible d'envoyer le document à signer : " . $e->getMessage()
);
}
return;
}
// Envoi (etape 1)
if ($process->isTriggerable()) {
try {
$processStep = $process->getStep();
if ($processStep->getStatus() == Signature::STATUS_SIGNATURE_DRAFT) {
$this->getSignatureService()->sendSignature($processStep->getSignature());
$this->triggerProcessEvent($process, ProcessEvent::EVENT_TYPE_STEP);
return;
}
$this->getSignatureService()->updateStatusSignature($processStep->getSignature());
if ($processStep->getStatus() == Signature::STATUS_SIGNATURE_REJECT) {
$process->setStatus(Signature::STATUS_SIGNATURE_REJECT);
/** @var SignatureRecipient $recipient */
foreach ($processStep->getSignature()->getRecipients() as $recipient) {
if ($recipient->getStatus() != Signature::STATUS_SIGNATURE_REJECT) {
$recipient->setStatus(Signature::STATUS_SIGNATURE_CANCEL);
}
}
$this->getObjectManager()->flush();
$this->triggerProcessEvent($process, ProcessEvent::EVENT_TYPE_REJECTED);
return;
}
if ($processStep->getStatus() == Signature::STATUS_SIGNATURE_SIGNED) {
$totalSteps = count($process->getSteps());
$currentStep = $processStep->getOrder();
$this->getLoggerService()->info(
" - progression étapes : " . $processStep->getOrder() . '/' . count($process->getSteps())
);
if ($currentStep == $totalSteps) {
// FIN du PROCESSUS
$process->setStatus(Signature::STATUS_SIGNATURE_SIGNED);
$this->getObjectManager()->flush();
$this->triggerProcessEvent($process, ProcessEvent::EVENT_TYPE_SIGNED);
return;
}
else {
// PASSAGE à l'ETAPE SUIVANTE
$process->setCurrentStep($process->getCurrentStep() + 1);
$this->getObjectManager()->flush();
$this->trigger($process);
}
return;
}
} catch (Exception $e) {
$this->getLoggerService()->errorLogAndThrow(
$e,
"Impossible d'actualiser le processus : " . $e->getMessage()
);
}
}
elseif ($process->isFinished()) {
$this->getLoggerService()->info("Processus terminé");
throw new SignatureException("Ce processus est terminé");
}
else {
$this->getLoggerService()->info("Processus " . $process->getStatusText());
}
}
/**
* Méthode qui renvoie une synthèse des infos process de signature pour affichage
*
* @param Process $process
* @return array
*/
public function getInfosProcess(Process $process): array
{
$infosProcess = [];
foreach ($process->getSteps() as $keyStep => $step) {
if ($step->getStatus() == Signature::STATUS_SIGNATURE_SIGNED ||
$step->getStatus() == Signature::STATUS_SIGNATURE_WAIT) {
$infosProcess[$keyStep] = $step->toArray();
if ($step->getStatus() == Signature::STATUS_SIGNATURE_SIGNED) {
$labelInfo = 'signé par ';
$recipient = current($infosProcess[$keyStep]['recipients']);
$dateSignature = new \DateTime($recipient['dateFinished']);
$labelInfo .= $recipient['fullname'] . ' le ' . $dateSignature->format('d/m/Y');
$infosProcess[$keyStep]['labelInfos'] = $labelInfo;
}
if ($step->getStatus() == Signature::STATUS_SIGNATURE_WAIT) {
$labelInfo = 'en attente de signature';
$infosProcess[$keyStep]['labelInfos'] = $labelInfo;
}
}
}
return $infosProcess;
}
/**
* @param Process $process
* @param string $eventType
* @return void
*/
protected function triggerProcessEvent(Process $process, string $eventType): void
{
$this->getLoggerService()->info("[EVENT PROCESS] >>> $eventType : $process");
$em = new EventManager($this->getSharedEventManager());
$em->triggerEvent(new ProcessEvent($eventType, null, ['id' => $process->getId()]));
}
}