src/Logging/DatabaseActivitySubscriber.php line 177

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