src/Logging/DatabaseActivitySubscriber.php line 176

Open in your IDE?
  1. <?php
  2. //----------------------------------------------------------------------
  3. // src/Logging/DatabaseActivitySubscriber.php
  4. // Plan.io Task #3922
  5. //----------------------------------------------------------------------
  6. namespace App\Logging;
  7. use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Doctrine\ORM\Events;
  10. use Doctrine\Persistence\Event\LifecycleEventArgs;
  11. use Doctrine\Persistence\Proxy;
  12. use App\Entity\Access;
  13. use App\Entity\LoggableInterface;
  14. use App\Entity\Product\Product;
  15. use App\Logging\DeletionContextLogger;
  16. use App\Logging\Activity\AccessAPILog;
  17. use App\Logging\Activity\AccessClientLog;
  18. use App\Logging\Activity\AccessLog;
  19. use App\Logging\Activity\AddressLog;
  20. use App\Logging\Activity\AdvancedNotificationLog;
  21. use App\Logging\Activity\AttachmentLog;
  22. use App\Logging\Activity\ChargeLog;
  23. use App\Logging\Activity\ClientLog;
  24. use App\Logging\Activity\CommandLog;
  25. use App\Logging\Activity\CostLog;
  26. use App\Logging\Activity\CostNoteLog;
  27. use App\Logging\Activity\EInvoicingInboundInvoiceLog;
  28. use App\Logging\Activity\EInvoicingInboundInvoiceNoteLog;
  29. use App\Logging\Activity\DemandLog;
  30. use App\Logging\Activity\DevisLog;
  31. use App\Logging\Activity\DocumentLog;
  32. use App\Logging\Activity\ExternalMessageLog;
  33. use App\Logging\Activity\FinancialLog;
  34. use App\Logging\Activity\GhostDevisLog;
  35. use App\Logging\Activity\IkeaServiceOrderLog;
  36. use App\Logging\Activity\IkeaServiceOrderUpdateLog;
  37. use App\Logging\Activity\IndividualLog;
  38. use App\Logging\Activity\InstallmentLog;
  39. use App\Logging\Activity\InvoiceLog;
  40. use App\Logging\Activity\MissionLog;
  41. use App\Logging\Activity\NoteLog;
  42. use App\Logging\Activity\PhoneLog;
  43. use App\Logging\Activity\PlanningResourceLog;
  44. use App\Logging\Activity\ProjectNotebookLog;
  45. use App\Logging\Activity\ProjectNotebookItemLog;
  46. use App\Logging\Activity\ProductLog;
  47. use App\Logging\Activity\SocietyLog;
  48. use App\Logging\Activity\SocietyGroupLog;
  49. use App\Logging\Activity\StoreLog;
  50. use App\Logging\Activity\StoreGroupLog;
  51. use App\Logging\Activity\SupplierLog;
  52. use App\Logging\Activity\TaskLog;
  53. use App\Logging\Activity\TemplateLog;
  54. use App\Logging\Activity\Prospect\ContactLog as ProspectContactLog;
  55. use App\Logging\Activity\Prospect\ReportLog as ProspectReportLog;
  56. use App\Logging\Activity\Prospect\SurveyLog as ProspectSurveyLog;
  57. use App\Logging\Activity\Prospect\SurveyQuestionLog as ProspectSurveyQuestionLog;
  58. use App\Logging\HR\AccessFunctionLog;
  59. use App\Logging\HR\ApplicationLog;
  60. use App\Logging\HR\HRVarLog;
  61. use App\Logging\HR\HumanResourceLog;
  62. use App\Logging\HR\NoteLog as HRNoteLog;
  63. use App\Logging\HR\OPVarLog;
  64. use App\Logging\HR\Equipment\DamageLog;
  65. use App\Logging\HR\Equipment\EquipmentLog;
  66. use App\Logging\HR\Equipment\FineLog;
  67. use App\Logging\HR\Equipment\MileageLog;
  68. use App\Logging\HR\Equipment\NoteLog as EquipmentNoteLog;
  69. use App\Logging\HR\Equipment\VehicleLog;
  70. use App\Logging\HR\Equipment\VehicleMaintenanceLog;
  71. use App\Logging\HR\Equipment\VehicleMaintenanceDeadlineLog;
  72. use App\Logging\HR\RHForm\AccidentLog as RHFormAccidentLogLog;
  73. use App\Logging\HR\RHForm\LeaveLog as RHFormLeaveLog;
  74. use App\Logging\HR\RHForm\RHFormLog;
  75. use App\Logging\Media\ArticleLog;
  76. use App\Logging\Media\CloudAclInodeLog;
  77. use App\Logging\Media\CloudInodeLog;
  78. use App\Logging\Media\CommentLog as ArticleCommentLog;
  79. use App\Logging\Security\AclLog;
  80. use App\Logging\Security\AclPlanningLog;
  81. use App\Services\Logging;
  82. use App\Services\LogTools;
  83. class DatabaseActivitySubscriber implements EventSubscriberInterface
  84. {
  85.     private array $pendingLogs = [];
  86.     private array $avoidDuplicates = [];
  87.     public function __construct(EntityManagerInterface $em, Logging $logger, LogTools $logTools, DeletionContextLogger $contextLogger,
  88.         AccessAPILog $accessApiLog, AccessClientLog $accessClientLog, AccessLog $accessLog, AccessFunctionLog $accessFunctionLog,
  89.         AclLog $aclLog, AclPlanningLog $aclPlanningLog,
  90.         AddressLog $addressLog, AdvancedNotificationLog $advancedNotificationLog, ApplicationLog $applicationLog,
  91.         ArticleLog $articleLog, ArticleCommentLog $articleCommentLog,
  92.         AttachmentLog $attachmentLog,
  93.         ChargeLog $chargeLog, ClientLog $clientLog,
  94.         CloudAclInodeLog $cloudAclInodeLog, CloudInodeLog $cloudInodeLog,
  95.         CommandLog $commandLog, CostLog $costLog, CostNoteLog $costNoteLog,
  96.         EInvoicingInboundInvoiceLog $eInvoicingInboundInvoiceLog,
  97.         EInvoicingInboundInvoiceNoteLog $eInvoicingInboundInvoiceNoteLog,
  98.         DamageLog $damageLog, DevisLog $devisLog, DemandLog $demandLog, DocumentLog $documentLog,
  99.         EquipmentLog $equipmentLog, EquipmentNoteLog $equipmentNoteLog, ExternalMessageLog $externalMessageLog,
  100.         FinancialLog $financialLog, FineLog $fineLog, GhostDevisLog $ghostDevisLog,
  101.         IkeaServiceOrderLog $ikeaServiceOrderLog, IkeaServiceOrderUpdateLog $ikeaServiceOrderUpdateLog,
  102.         IndividualLog $individualLog, InstallmentLog $installmentLog, InvoiceLog $invoiceLog,
  103.         HumanResourceLog $humanResourceLog, HRNoteLog $hrNoteLog, HRVarLog $hrVarLog,
  104.         MileageLog $mileageLog, MissionLog $missionLog,    NoteLog $noteLog, OPVarLog $opVarLog,
  105.         PhoneLog $phoneLog, PlanningResourceLog $planningResourceLog, 
  106.         ProjectNotebookLog $projectNotebookLog, ProjectNotebookItemLog $projectNotebookItemLog,
  107.         ProductLog $productLog,        
  108.         ProspectContactLog $prospectContactLog, ProspectReportLog $prospectReportLog, ProspectSurveyLog $prospectSurveyLog, ProspectSurveyQuestionLog $prospectSurveyQuestionLog,
  109.         RHFormLog $rhFormLog, RHFormAccidentLogLog $rhFormAccidentLog, RHFormLeaveLog $rhFormLeaveLog,
  110.         SocietyLog $societyLog, SocietyGroupLog $societyGroupLog, StoreLog $storeLog, StoreGroupLog $storeGroupLog, SupplierLog $supplierLog,
  111.         TaskLog $taskLog, TemplateLog $templateLog,
  112.         VehicleLog $vehicleLog, VehicleMaintenanceLog $vehicleMaintenanceLog, VehicleMaintenanceDeadlineLog $vmdLog)
  113.     {
  114.         $this->em = $em;
  115.         $this->contextLogger = $contextLogger;
  116.         $this->logger = $logger;
  117.         $this->logTools = $logTools;
  118.         $this->accessApiLog = $accessApiLog;
  119.         $this->accessClientLog = $accessClientLog;
  120.         $this->accessLog = $accessLog;
  121.         $this->accessFunctionLog = $accessFunctionLog;
  122.         $this->aclLog = $aclLog;
  123.         $this->aclPlanningLog = $aclPlanningLog;
  124.         $this->addressLog = $addressLog;
  125.         $this->advancedNotificationLog = $advancedNotificationLog;
  126.         $this->applicationLog = $applicationLog;
  127.         $this->articleLog = $articleLog;
  128.         $this->articleCommentLog = $articleCommentLog;
  129.         $this->attachmentLog = $attachmentLog;
  130.         $this->chargeLog = $chargeLog;
  131.         $this->clientLog = $clientLog;
  132.         $this->cloudAclInodeLog = $cloudAclInodeLog;
  133.         $this->cloudInodeLog = $cloudInodeLog;
  134.         $this->commandLog = $commandLog;
  135.         $this->costLog = $costLog;
  136.         $this->costNoteLog = $costNoteLog;
  137.         $this->eInvoicingInboundInvoiceLog = $eInvoicingInboundInvoiceLog;
  138.         $this->eInvoicingInboundInvoiceNoteLog = $eInvoicingInboundInvoiceNoteLog;
  139.         $this->demandLog = $demandLog;
  140.         $this->damageLog = $damageLog;
  141.         $this->devisLog = $devisLog;
  142.         $this->documentLog = $documentLog;
  143.         $this->equipmentLog = $equipmentLog;
  144.         $this->equipmentNoteLog = $equipmentNoteLog;
  145.         $this->externalMessageLog = $externalMessageLog;
  146.         $this->financialLog = $financialLog;
  147.         $this->ghostDevisLog = $ghostDevisLog;
  148.         $this->fineLog = $fineLog;
  149.         $this->ikeaServiceOrderLog = $ikeaServiceOrderLog;
  150.         $this->ikeaServiceOrderUpdateLog = $ikeaServiceOrderUpdateLog;
  151.         $this->individualLog = $individualLog;
  152.         $this->installmentLog = $installmentLog;
  153.         $this->invoiceLog = $invoiceLog;
  154.         $this->humanResourceLog = $humanResourceLog;
  155.         $this->hrNoteLog = $hrNoteLog;
  156.         $this->hrVarLog = $hrVarLog;
  157.         $this->mileageLog = $mileageLog;
  158.         $this->missionLog = $missionLog;
  159.         $this->noteLog = $noteLog;
  160.         $this->opVarLog = $opVarLog;
  161.         $this->phoneLog = $phoneLog;
  162.         $this->planningResourceLog = $planningResourceLog;
  163.         $this->projectNotebookLog = $projectNotebookLog;
  164.         $this->projectNotebookItemLog = $projectNotebookItemLog;
  165.         $this->productLog = $productLog;
  166.         $this->prospectContactLog = $prospectContactLog;
  167.         $this->prospectReportLog = $prospectReportLog;
  168.         $this->prospectSurveyLog = $prospectSurveyLog;
  169.         $this->prospectSurveyQuestionLog = $prospectSurveyQuestionLog;
  170.         $this->rhFormLog = $rhFormLog;
  171.         $this->rhFormAccidentLog = $rhFormAccidentLog;
  172.         $this->rhFormLeaveLog = $rhFormLeaveLog;
  173.         $this->societyLog = $societyLog;
  174.         $this->societyGroupLog = $societyGroupLog;
  175.         $this->storeLog = $storeLog;
  176.         $this->storeGroupLog = $storeGroupLog;
  177.         $this->supplierLog = $supplierLog;
  178.         $this->taskLog = $taskLog;
  179.         $this->templateLog = $templateLog;
  180.         $this->vehicleLog = $vehicleLog;
  181.         $this->vehicleMaintenanceLog = $vehicleMaintenanceLog;
  182.         $this->vmdLog = $vmdLog;
  183.         $today = new \DateTime();
  184.         $this->timestamp = "[".$today->format("Y/m/d H:i:s")."] ";
  185.         $this->logServices = [
  186.             "App\Entity\Access"                                            =>    $this->accessLog,
  187.             "App\Entity\AccessClient\AccessClient"                        =>    $this->accessClientLog,
  188.             "App\Entity\APIRest\AccessAPI"                                =>    $this->accessApiLog,
  189.             "App\Entity\Common\Attachment"                                =>    $this->attachmentLog,
  190.             "App\Entity\Client\Client"                                    =>    $this->clientLog,
  191.             "App\Entity\Client\Contact"                                    =>    $this->prospectContactLog,
  192.             "App\Entity\Client\Financial"                                =>    $this->financialLog,
  193.             "App\Entity\Client\Individual"                                =>    $this->individualLog,
  194.             "App\Entity\Client\Store"                                    =>    $this->storeLog,
  195.             "App\Entity\Client\StoreGroup"                                =>    $this->storeGroupLog,
  196.             "App\Entity\Cloud\AclInode"                                    =>    $this->cloudAclInodeLog,
  197.             "App\Entity\Cloud\Inode"                                    =>    $this->cloudInodeLog,
  198.             "App\Entity\Ding\AdvancedNotification"                        =>    $this->advancedNotificationLog,
  199.             "App\Entity\EInvoicing\EInvoicingInboundInvoice"                =>    $this->eInvoicingInboundInvoiceLog,
  200.             "App\Entity\EInvoicing\EInvoicingInboundInvoiceNote"            =>    $this->eInvoicingInboundInvoiceNoteLog,
  201.             "App\Entity\Equipment\Damage"                                =>    $this->damageLog,
  202.             "App\Entity\Equipment\Fine"                                    =>    $this->fineLog,
  203.             "App\Entity\Equipment\Equipment"                            =>    $this->equipmentLog,
  204.             "App\Entity\Equipment\Mileage"                                =>    $this->mileageLog,
  205.             "App\Entity\Equipment\Note"                                    =>    $this->equipmentNoteLog,
  206.             "App\Entity\Equipment\Vehicle"                                =>    $this->vehicleLog,
  207.             "App\Entity\Equipment\VehicleMaintenance"                    =>    $this->vehicleMaintenanceLog,
  208.             "App\Entity\Equipment\VehicleMaintenanceDeadline"            =>    $this->vmdLog,
  209.             "App\Entity\HR\AccessFunction"                                =>    $this->accessFunctionLog,
  210.             "App\Entity\HR\Application\Application"                        =>    $this->applicationLog,
  211.             "App\Entity\HR\HumanResource"                                =>    $this->humanResourceLog,
  212.             "App\Entity\HR\Note"                                        =>    $this->hrNoteLog,
  213.             "App\Entity\HR\RHForm\Accident"                                =>    $this->rhFormAccidentLog,
  214.             "App\Entity\HR\RHForm\Leave"                                =>    $this->rhFormLeaveLog,
  215.             "App\Entity\HR\RHForm\RHForm"                                =>    $this->rhFormLog,
  216.             "App\Entity\HR\Salary\HRVariable"                            =>    $this->hrVarLog,
  217.             "App\Entity\HR\Salary\OPVariable"                            =>    $this->opVarLog,
  218.             "App\Entity\Ikea\ServiceOrder"                                =>    $this->ikeaServiceOrderLog,
  219.             "App\Entity\Ikea\ServiceOrderUpdate"                        =>    $this->ikeaServiceOrderUpdateLog,
  220.             "App\Entity\Location\Address"                                =>    $this->addressLog,
  221.             "App\Entity\Mission\Mission"                                =>    $this->missionLog,
  222.             "App\Entity\Media\Article"                                    =>    $this->articleLog,
  223.             "App\Entity\Media\Comment"                                    =>    $this->articleCommentLog,
  224.             "App\Entity\Planning\PlanningResource"                        =>    $this->planningResourceLog,
  225.             "App\Entity\Planning\Task"                                    =>    $this->taskLog,
  226.             "App\Entity\Platform\Command\Command"                        =>    $this->commandLog,
  227.             "App\Entity\Platform\Cost\Cost"                                =>    $this->costLog,
  228.             "App\Entity\Platform\Cost\CostNote"                            =>    $this->costNoteLog,
  229.             "App\Entity\Platform\Demand\Demand"                            =>    $this->demandLog,
  230.             "App\Entity\Platform\Devis\Devis"                            =>    $this->devisLog,
  231.             "App\Entity\Platform\Devis\GhostDevis"                        =>    $this->ghostDevisLog,
  232.             "App\Entity\Platform\ExternalMessage\ExternalMessage"        =>    $this->externalMessageLog,
  233.             "App\Entity\Platform\Installment"                            =>    $this->installmentLog,
  234.             "App\Entity\Platform\Invoice\Invoice"                        =>    $this->invoiceLog,
  235.             "App\Entity\Platform\Note"                                    =>    $this->noteLog,
  236.             "App\Entity\Platform\Phone"                                    =>    $this->phoneLog,
  237.             "App\Entity\Platform\Report"                                =>    $this->prospectReportLog,
  238.             "App\Entity\Platform\Society"                                =>    $this->societyLog,
  239.             "App\Entity\Platform\Supplier"                                =>    $this->supplierLog,
  240.             "App\Entity\Platform\Survey\Survey"                            =>    $this->prospectSurveyLog,
  241.             "App\Entity\Platform\Survey\SurveyQuestion"                    =>    $this->prospectSurveyQuestionLog,
  242.             "App\Entity\ProjectManager\ProjectNotebook"                    =>    $this->projectNotebookLog,
  243.             "App\Entity\ProjectManager\ProjectNotebookItem"                =>    $this->projectNotebookItemLog,
  244.             "App\Entity\Product\Charge"                                    =>    $this->chargeLog,
  245.             "App\Entity\Product\Product"                                =>    $this->productLog,
  246.             "App\Entity\Product\Template"                                =>    $this->templateLog,
  247.             "App\Entity\Security\Acl"                                    =>    $this->aclLog,
  248.             "App\Entity\Security\AclPlanning"                            =>    $this->aclPlanningLog,
  249.             "App\Entity\SocietyGroup"                                    =>    $this->societyGroupLog,
  250.             "App\Entity\Webapp\Document"                                =>    $this->documentLog,
  251.         ];
  252.     }
  253.     // this method can only return the event names; you cannot define a
  254.     // custom method name to execute when each event triggers
  255.     public function getSubscribedEvents(): array
  256.     {
  257.         // Comment this to activate subscriber
  258.         // return [];
  259.         return [
  260.             Events::prePersist,
  261.             Events::preUpdate,
  262.             Events::preRemove,
  263.             Events::postFlush,
  264.         ];
  265.     }
  266.     // Do not return in this method, it breaks Doctrine cycles
  267.     // Called when an object is created
  268.     public function prePersist(LifecycleEventArgs $args): void
  269.     {
  270.         $data = $this->handleData("prePersist", $args);
  271.         if ($data !== null)
  272.         {
  273.             $entity = $data['entity'];
  274.             $entityClass = $data['entityClass'];
  275.             $logService = $data['logService'];
  276.             // Create logging args for object creation
  277.             $logArgs = $logService->logCreation($entity);
  278.             // Save log args for postFlush
  279.             $this->handleLogs("prePersist", $logArgs, $entity);
  280.         }
  281.     }
  282.     // Do not return in this method, it breaks Doctrine cycles
  283.     public function preUpdate(LifecycleEventArgs $args): void
  284.     {
  285.         $data = $this->handleData("preUpdate", $args);
  286.         if ($data !== null)
  287.         {
  288.             $entity = $data['entity'];
  289.             $entityClass = $data['entityClass'];
  290.             $logService = $data['logService'];
  291.             // Get the changes from the Unit of Work
  292.             $changes = $args->getEntityChangeSet();
  293.             // Create logging args for object modification
  294.             $logArgs = $logService->logChanges($entity, $changes);
  295.             // Save log args for postFlush
  296.             $this->handleLogs("prePersist", $logArgs, $entity);
  297.         }
  298.     }
  299.     // Do not return in this method, it breaks Doctrine cycles
  300.     public function preRemove(LifecycleEventArgs $args): void
  301.     {
  302.         $data = $this->handleData("preRemove", $args);
  303.         if ($data !== null)
  304.         {
  305.             $entity = $data['entity'];
  306.             $entityClass = $data['entityClass'];
  307.             $logService = $data['logService'];
  308.             // Create logging args for object removal
  309.             $logArgs = $logService->logRemoval($entity);
  310.             // Save log args for postFlush
  311.             $this->handleLogs("preRemove", $logArgs, $entity);
  312.         }
  313.     }
  314.     // Specific Installment case (and also Attachment, Address etc ...)
  315.     // Some entities are logged not as an object, but attached to another object
  316.     // An Installment related to an Invoice will have log.objectId = installment.invoice.id
  317.     // However, in those cases, log.objectId is not null even in prePersist
  318.     // since we are prePersisting the newly created installment,
  319.     // but actually logging for an Invoice that is already created.
  320.     // So the main condition if (empty($log->getObjectId()))
  321.     // is never true for such cases.
  322.     // So no error and no problem ;)
  323.     public function postFlush(): void
  324.     {
  325.         if (!empty($this->pendingLogs))
  326.         {
  327.             // Handle logs of objects that have been created => Update ID now that we have it
  328.             foreach ($this->pendingLogs as $logData)
  329.             {
  330.                 $log = $logData['log'];
  331.                 $object = $logData['object'];
  332.                 if (empty($log->getObjectId()))
  333.                 {
  334.                     $log->setObjectId($object->getId());
  335.                 }                
  336.                 // Handle Special Cases
  337.                 $this->societyGroupLog->handleSocietyGroupCreation($log, $object);
  338.                 //     > $objectClientId case (Client creation)
  339.                 $this->individualLog->handleIndividual($log, $object);
  340.                 //     > $objectMissionId case (Mission creation)
  341.                 $this->missionLog->handleMission($log, $object);
  342.                 //     > $objectHumanResourceId case (HumanResource creation)
  343.                 $this->humanResourceLog->handleHumanResource($log, $object);
  344.                 $this->em->persist($log);
  345.             }
  346.             // Reset arrays
  347.             $this->pendingLogs = [];
  348.             try
  349.             {
  350.                 // Save data to database
  351.                 $this->em->flush();
  352.             }
  353.             catch (\Exception $e)
  354.             {
  355.                 $allGood = false;
  356.                 $this->logTools->errorlog($e->getMessage());
  357.                 $this->logTools->errorlog_db($e);
  358.             }
  359.             $this->contextLogger->clear();
  360.         }
  361.         // Reset duplicates array
  362.         $this->avoidDuplicates = [];
  363.     }
  364.     protected function handleData($caller, $args)
  365.     {
  366.         // Get Entity and Entity class
  367.         $entity = $args->getObject();
  368.         // Avoid getting Proxies\__CG__\App\Entity\NameOfEntity
  369.         // instead of App\Entity\NameOfEntity
  370.         $entityClass = $entity instanceof Proxy
  371.         ? get_parent_class($entity)
  372.         : get_class($entity);
  373.         // Optionally ignore certain entity types (like internal logs themselves)
  374.         if (!$entity instanceof LoggableInterface)
  375.         {
  376.             return null;
  377.         }
  378.         if (!array_key_exists($entityClass, $this->logServices))
  379.         {
  380.             return null;
  381.         }
  382.         // Avoid duplicates
  383.         // I really have no idea if this is necessary
  384.         // And I really hope it does harm either
  385.         $hash = spl_object_hash($entity);
  386.         if (in_array($hash, $this->avoidDuplicates))
  387.         {
  388.             return null;
  389.         }
  390.         $this->avoidDuplicates[] = $hash;
  391.         // Get the corresponding Log Service
  392.         $logService = $this->logServices[$entityClass];
  393.         // Check to see if the Entity has some info stored
  394.         $info = null;
  395.         if (method_exists($entity, "getLoggingInfo"))
  396.         {
  397.             $info = $entity->getLoggingInfo();
  398.         }
  399.         return array(
  400.             'entity'        =>    $entity,
  401.             'entityClass'    =>    $entityClass,
  402.             'logService'    =>    $logService,
  403.             'info'            =>    $info,
  404.         );
  405.     }
  406.     protected function handleLogs($caller, $logArgs, $entity)
  407.     {
  408.         foreach ($logArgs as $key => $args)
  409.         {
  410.             $log = $this->logger->smartLog($args);
  411.             $this->pendingLogs[] = array(
  412.                 'log'        =>    $log,
  413.                 'object'    =>    $entity,
  414.             );
  415.         }
  416.     }
  417. }