<?php
//----------------------------------------------------------------------
// src/Services/LogTools.php
//----------------------------------------------------------------------
namespace App\Services;
use DateTime;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Security;
use App\DTO\Log\LogCsvRecord;
use App\Entity\Access;
use App\Entity\AccessClient\AccessClient;
use App\Entity\APIRest\AccessAPI;
use App\Entity\Client\Client;
use App\Entity\HR\HumanResource;
use App\Entity\Ikea\ServiceOrder;
use App\Entity\Mission\Mission;
use App\Entity\OnlinePayment\PaymentType as OnlinePaymentType;
use App\Entity\Planning\Task;
use App\Entity\Platform\Devis\Devis;
use App\Entity\Platform\Invoice\Invoice;
use App\Entity\ProjectManager\ProjectNotebook;
use App\Entity\SocietyGroup;
class LogTools
{
public function __construct(ManagerRegistry $doctrine, TranslatorInterface $translator, LoggerInterface $ouchLogger, Security $security)
{
$this->em = $doctrine->getManager();
$this->translator = $translator;
$this->security = $security;
$this->ouchLogger = $ouchLogger;
}
public function getRootDir()
{
$home = dirname(__FILE__, 3);
return $home;
}
public function getPublicDir()
{
$home = dirname(__FILE__, 3);
$home .= "/public/";
return $home;
}
public function getCustomLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/custom_logs/";
return $home;
}
public function getCustomDataDir()
{
$home = dirname(__FILE__, 3);
$home .= "/custom_data/";
return $home;
}
public function getDMSRootDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/";
return $home;
}
// Plan.io Task #4661
// ROOT/DMS/Ikea/logs/{society_group_id}/
public function getIkeaDMSLogsFolder(SocietyGroup $societyGroup)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Ikea/logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
// Plan.io Task #4661
// ROOT/DMS/Ikea/logs/{society_group_id}/
public function getIkeaDMSLogFile(ServiceOrder $serviceOrder)
{
if ($serviceOrder->getSocietyGroup() !== null)
{
$path = $this->getIkeaDMSLogsFolder($serviceOrder->getSocietyGroup());
$logFile = $path . $serviceOrder->getId() . ".log";
return $logFile;
}
return null;
}
// Plan.io Task #4661
public function logNewXml(ServiceOrder $serviceOrder, string $data)
{
$logFile = $this->getIkeaDMSLogFile($serviceOrder);
if ($logFile !== null)
{
$today = new \DateTime();
$timestamp = $today->format("Y-m-d H:i:s");
error_log("\n[$timestamp] $data", 3, $logFile);
}
}
// Plan.io Task #4448
// ROOT/DMS/IkeaBP/logs/{society_group_id}/
public function getIkeaBpFolder(SocietyGroup $societyGroup)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "IkeaBP/logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
public function getIkeaBpLogFileName(SocietyGroup $societyGroup)
{
$today = new \DateTime();
$timestamp = $today->format("Ymd_His");
$logFileName = "IkeaBP_".$societyGroup->getId()."_".$timestamp.".log";
return $logFileName;
}
public function getIkeaBpErrorFileName(SocietyGroup $societyGroup)
{
$today = new \DateTime();
$timestamp = $today->format("Ymd_His");
$logFileName = "IkeaBP_".$societyGroup->getId()."_".$timestamp.".err";
return $logFileName;
}
public function getIkeaBpLogFile(SocietyGroup $societyGroup)
{
$path = $this->getIkeaBpFolder($societyGroup);
$logFileName = $this->getIkeaBpLogFileName($societyGroup);
$logFile = $path.$logFileName;
return $logFile;
}
public function getIkeaBpErrorFile(SocietyGroup $societyGroup)
{
$path = $this->getIkeaBpFolder($societyGroup);
$logFileName = $this->getIkeaBpErrorFileName($societyGroup);
$logFile = $path.$logFileName;
return $logFile;
}
public function logToBpFile_andTask($logFile, Task $task, $msg)
{
$today = new \DateTime();
$timestamp = $today->format("Y-m-d H:i:s");
error_log("\n[$timestamp] $msg", 3, $logFile);
$ikeaBpProcessInfo = $task->getIkeaBpProcessInfo();
$ikeaBpProcessInfo .= $msg;
$task->setIkeaBpProcessInfo($ikeaBpProcessInfo);
// error_log("\n[$timestamp] $msg", 3, "ploop.log");
}
public function logToBpFile($logFile, $msg)
{
$today = new \DateTime();
$timestamp = $today->format("Y-m-d H:i:s");
error_log("\n[$timestamp] $msg", 3, $logFile);
// error_log("\n[$timestamp] $msg", 3, "ploop.log");
}
// ROOT/DMS/Export/CostAccount/society_group_id/
public function getCostAutoAccountExportFolder($societyGroup = null)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "CostAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
if ($societyGroup !== null)
{
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
}
return $home;
}
// ROOT/DMS/Export/CostAccount/society_group_id/logs/
public function getCostAutoAccountExportLogsFolder(SocietyGroup $societyGroup)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "CostAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
// ROOT/DMS/Export/InvoiceAccount/society_group_id/
public function getInvoiceAutoAccountExportFolder($societyGroup = null)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "InvoiceAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
if ($societyGroup !== null)
{
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
}
return $home;
}
// ROOT/DMS/Export/InstallmentAccount/society_group_id/
public function getInstallmentAutoAccountExportFolder($societyGroup = null)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "InstallmentAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
if ($societyGroup !== null)
{
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
}
return $home;
}
// ROOT/DMS/Export/InstallmentAccount/society_group_id/logs/
public function getInstallmentAutoAccountExportLogsFolder(SocietyGroup $societyGroup)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "InstallmentAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
// ROOT/DMS/Export/InvoiceAccount/society_group_id/logs/
public function getInvoiceAutoAccountExportLogsFolder(SocietyGroup $societyGroup)
{
$home = $this->getDMSRootDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "Export/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "InvoiceAccount/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= $societyGroup->getId();
$home .= "/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
/**
* Exports Logs to ROOT/DMS/Export/InvoiceAccount/society_group_id/logs/
* File Name : { yyyymmdd }_Export_QCompta_error.log
*/
public function logError_invoiceAutoAccount(SocietyGroup $societyGroup, $error)
{
$exportPath = $this->getInvoiceAutoAccountExportLogsFolder($societyGroup);
$today = new \DateTime();
$ymd = $today->format("Ymd");
$timestamp = $today->format("Y-m-d H:i:s");
$fileName = $ymd."_Export_QCompta_Factures_error".".log";
$errorFile = $exportPath.$fileName;
error_log("\n[$timestamp] $error", 3, $errorFile);
}
/**
* Exports Logs to ROOT/DMS/Export/CostAccount/society_group_id/logs/
* File Name : { yyyymmdd }_Export_Achats_QCompta_error.log
*/
public function logError_costAutoAccount(SocietyGroup $societyGroup, $error)
{
$exportPath = $this->getCostAutoAccountExportLogsFolder($societyGroup);
$today = new \DateTime();
$ymd = $today->format("Ymd");
$timestamp = $today->format("Y-m-d H:i:s");
$fileName = $ymd."_Export_QCompta_Achats_error".".log";
$errorFile = $exportPath.$fileName;
error_log("\n[$timestamp] $error", 3, $errorFile);
}
/**
* Exports Logs to ROOT/DMS/Export/InstallmentAccount/society_group_id/logs/
* File Name : { yyyymmdd }_Export_Reglements_QCompta_error.log
*/
public function logError_installmentAutoAccount(SocietyGroup $societyGroup, $error)
{
$exportPath = $this->getInstallmentAutoAccountExportLogsFolder($societyGroup);
$today = new \DateTime();
$ymd = $today->format("Ymd");
$timestamp = $today->format("Y-m-d H:i:s");
$fileName = $ymd."_Export_QCompta_Reglements_error".".log";
$errorFile = $exportPath.$fileName;
error_log("\n[$timestamp] $error", 3, $errorFile);
}
//--------------------------------------------------------------------------
// TO BE USED IN COMMANDS (OneShot) ONLY
//--------------------------------------------------------------------------
public function getCommandLogsDir()
{
$home = $this->getCustomLogsDir()."command_logs/";
return $home;
}
public function command_log($filename, $msg, $newLine = true)
{
$home = $this->getCommandLogsDir();
$logFile = $home . $filename;
if ($newLine)
$msg = "\n".$msg;
error_log($msg,3,$logFile);
}
//--------------------------------------------------------------------------
public function plooplog($msg)
{
error_log("\n".$msg."\n",3,"ploop.log");
}
// public function ploopWrite($msg)
// {
// $filename = "ploop.log";
// $msg = "\n".$msg."\n";
// if (is_writable($filename))
// {
// if ($fp = fopen($filename, 'a'))
// {
// fwrite($fp, $msg);
// }
// }
// }
public function ploop_debug($active, $msg)
{
if (!$active)
return false;
error_log("\n".$msg."\n",3,"ploop.log");
}
public function getGuardConfigDir()
{
$home = $this->getRootDir();
$home .= "/src/Guardian/config/";
return $home;
}
public function getPlanningOptimisationLogsDir()
{
$home = $this->getCustomLogsDir()."planning_optimisation_logs/";
return $home;
}
public function getIkeaKitchenPlannerLogsDir()
{
$home = $this->getCustomLogsDir()."ikea_kitchen_planner_logs/";
return $home;
}
public function getApiIcodLogsDir()
{
$home = $this->getCustomLogsDir()."api_icod/";
return $home;
}
public function getCynclyLogsDir()
{
$home = $this->getCustomLogsDir()."cyncly_logs/";
return $home;
}
// NOTE: This folder is used for WIP subscription system not for the onlinePayment one
public function getStripeLogsDir()
{
$home = $this->getCustomLogsDir()."stripe/";
return $home;
}
public function getGuestSuiteLogsDir()
{
$home = $this->getCustomLogsDir()."guest_suite_log/";
return $home;
}
public function getGuardLogsDir()
{
$home = $this->getCustomLogsDir()."guard_logs/";
return $home;
}
public function getGuardGlobalLogsDir()
{
$home = $this->getCustomLogsDir()."guard_logs/global/";
return $home;
}
public function getIkeaOSLogsDir()
{
$home = $this->getCustomLogsDir()."ikea_os_logs/";
return $home;
}
public function getIkeaOS_statusLogsDir()
{
$home = $this->getCustomLogsDir()."ikea_os_logs/status_logs/";
return $home;
}
public function getIkeaHotlineCallLogsDir(SocietyGroup $societyGroup): string
{
$home = $this->getCustomLogsDir()."ikea_hotline_call/";
if (!is_dir($home))
{
mkdir($home, 0755, true);
}
$home .= $societyGroup->getId()."/";
if (!is_dir($home))
{
mkdir($home, 0755, true);
}
return $home;
}
public function getIkeaSendLogsDir($societyGroup)
{
$home = $this->getCustomLogsDir();
$home .= "ikea_send_logs/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
return null;
}
}
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
public function getPlanningLogsDir()
{
$home = $this->getCustomLogsDir()."planning/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
public function getCostLogsDir()
{
$home = $this->getCustomLogsDir()."cost_logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
public function getInstallmentLogsDir()
{
$home = $this->getCustomLogsDir()."installment_logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
public function getInvoiceLogsDir()
{
$home = $this->getCustomLogsDir()."invoice_logs/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
return $home;
}
// custom_logs/invoice_logs/missing_devis_product/
public function getInvoiceMissingDevisProductsLogsDir()
{
$home = $this->getInvoiceLogsDir();
$home .= "missing_devis_product/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
return null;
}
}
return $home;
}
// custom_logs/cost_logs/export/{society_group_id}/
public function getCostExportLogsDir($societyGroup)
{
$home = $this->getCostLogsDir();
$home .= "export/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
return null;
}
}
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// custom_logs/installment_logs/export/{society_group_id}/
public function getInstallmentExportLogsDir($societyGroup)
{
$home = $this->getInstallmentLogsDir();
$home .= "export/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
return null;
}
}
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// custom_logs/invoice_logs/export/{society_group_id}/
public function getInvoiceExportLogsDir(?SocietyGroup $societyGroup)
{
$home = $this->getInvoiceLogsDir();
$home .= "export/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
return null;
}
}
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
public function getITaskBaseLogsDir()
{
$home = $this->getCustomLogsDir()."itask_logs/";
return $home;
}
public function getITaskLogsDir($societyGroup = null)
{
$home = $this->getITaskBaseLogsDir() . "auto/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
public function getITaskDebugDir()
{
$home = $this->getITaskBaseLogsDir()."debug/";
return $home;
}
public function getLoginLogsDir()
{
$home = $this->getCustomLogsDir()."login_logs/";
return $home;
}
public function getProductLogsDir()
{
$home = $this->getCustomLogsDir()."product_logs/";
return $home;
}
public function getChargeLogsDir()
{
$home = $this->getCustomLogsDir()."charge_logs/";
return $home;
}
public function getSmsLogsDir()
{
$home = $this->getCustomLogsDir()."sms_logs/";
return $home;
}
public function getEmailLogsDir()
{
$home = $this->getCustomLogsDir()."email_logs/";
return $home;
}
// Plan.io Task #4624
public function getProjectManagerLogsDir()
{
$home = $this->getCustomLogsDir()."project_manager/";
return $home;
}
// Plan.io Task #4518
public function getNotifierLogsDir()
{
$home = $this->getCustomLogsDir()."notifier/";
return $home;
}
public function getTemplateLogsDir()
{
$home = $this->getCustomLogsDir()."template/";
return $home;
}
//--------------------------------------------------------------------------
// Plan.io Task #3922
// DMS Global, Email and Object Logs
//--------------------------------------------------------------------------
// Old path : ROOT/custom_logs/global_logs
// New path : ROOT/DMS/Logs/Global/
public function getDMS_GlobalLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/Global/";
return $home;
}
// DMS/Logs/Email/
public function getDMS_EmailLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/Email/";
return $home;
}
// DMS/Logs/Mission/
public function getDMS_MissionLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/Mission/";
return $home;
}
// DMS/Logs/Client/
public function getDMS_ClientLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/Client/";
return $home;
}
// DMS/Logs/HumanResource/
public function getDMS_HumanResourceLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/HumanResource/";
return $home;
}
// DMS/Logs/ProjectManager/Notebook/
public function getDMS_ProjectManagerNotebookLogsDir()
{
$home = dirname(__FILE__, 3);
$home .= "/DMS/Logs/ProjectManager/Notebook/";
return $home;
}
//--------------------------------------------------------------------------
public function getSecurityLogsDir()
{
$home = $this->getCustomLogsDir()."security/";
return $home;
}
// Plan.io Task #4410
public function getWebappLogsDir()
{
$home = $this->getCustomLogsDir()."webapp/";
return $home;
}
// Plan.io Task #4518
// Used in
// src/Services/Platform/NoteTools.php
// src/Services/Communication/Email/NotifierEmails.php
// src/Services/Ding/Notifier.php
public function notifier_debug($msg, $active = true)
{
if ($active)
{
$home = $this->getNotifierLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "notifier_debug_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
error_log("\n".$timestamp.$msg."\n",3,"ploop.log");
}
}
// Plan.io Task #4624
public function project_manager_debug($msg, $active = true)
{
if ($active)
{
$home = $this->getProjectManagerLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "project_manager_debug_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
// error_log("\n".$timestamp.$msg."\n",3,"ploop.log");
}
}
// Plan.io Task #4483
public function analyzePlanning($isActive, $msg)
{
if (!$isActive) return true;
$home = $this->getPlanningLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "global_planning_execution_time_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// Plan.io Task #4410
public function webapp_debug($msg)
{
$home = $this->getWebappLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "webapp_debug_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// Plan.io Task #4410
public function webapp_image_debug($msg)
{
$home = $this->getWebappLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "webapp_image_debug_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s]");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
public function getTakeOutExportDir()
{
$home = $this->getCustomDataDir()."take_out_export/";
return $home;
}
public function getCssDir()
{
$home = $this->getRootDir()."/public/theme/css/";
return $home;
}
public function getJohnDoeDir()
{
$home = $this->getRootDir()."/public/assets/john_doe/";
return $home;
}
// custom_logs/cost/auto_accounting/
public function getCostAutoAccountingDebugDir()
{
$home = $this->getCustomLogsDir()."cost/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
$home .= 'auto_accounting/';
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
return $home;
}
// custom_logs/invoice/auto_accounting/
public function getInvoiceAutoAccountingDebugDir()
{
$home = $this->getCustomLogsDir()."invoice/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
$home .= 'auto_accounting/';
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
return $home;
}
// custom_logs/zone/{society_group_id}
public function getZoneDir($societyGroup = null)
{
$home = $this->getCustomLogsDir()."zone/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// custom_logs/zone/debug/
public function getZoneDebugDir($societyGroup = null)
{
$home = $this->getZoneDir()."debug/";
return $home;
}
// custom_logs/availability/
public function getAvailablityDir()
{
$home = $this->getCustomLogsDir()."availability/";
return $home;
}
// custom_logs/financial/
// Plan.io Task #4386
public function getFinancialDir()
{
$home = $this->getCustomLogsDir()."financial/";
return $home;
}
// custom_logs/financial/scan_financial/
// Plan.io Task #4386
public function getScanFinancialDir()
{
$home = $this->getFinancialDir()."scan_financial/";
return $home;
}
// custom_logs/financial/duplicate_code/
// Plan.io Task #4386
public function getDuplicateCodeFinancialDir()
{
$home = $this->getFinancialDir()."duplicate_code/";
return $home;
}
// Plan.Io Task #3747
// custom_logs/individual/
public function getIndividualDir()
{
$home = $this->getCustomLogsDir()."individual/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
return $home;
}
// Plan.Io Task #3747
// custom_logs/individual/dump/{society_group_id}
public function getIndividualDumpDir($societyGroup = null)
{
$home = $this->getIndividualDir() . "dump/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// Plan.io Task #3747
// custom_logs/individual/merge/{society_group_id}
public function getIndividualMergeDir($societyGroup = null)
{
$home = $this->getIndividualDir() . "merge/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// Plan.io Task #4247
// custom_logs/mission/
public function getMissionDir()
{
$home = $this->getCustomLogsDir()."mission/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
return $home;
}
// Plan.io Task #4247
// custom_logs/mission/dump/{society_group_id}
public function getMissionDumpDir($societyGroup = null)
{
$home = $this->getMissionDir() . "dump/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// Plan.io Task #4247
// custom_logs/mission/merge/{society_group_id}
public function getMissionMergeDir($societyGroup = null)
{
$home = $this->getMissionDir() . "merge/";
if ($societyGroup !== null)
{
$id = $societyGroup->getId();
$home .= $id."/";
if (!is_dir($home))
{
$do = mkdir($home, 0755, true);
if ($do === false)
{
$this->errorLog("Folder $home cannot be created.");
return null;
}
}
}
return $home;
}
// Plan.io Task #4331
// custom_logs/payment_logs/YYYY/MM/
public function getPaymentLogDir()
{
$home = $this->getCustomLogsDir()."payment_logs/";
return $home;
}
public function getPaymentErrorLogDir()
{
$home = $this->getPaymentLogDir() . "error/";
$now = new \DateTime();
$home .= $now->format('Y') . "/" . $now->format('m') . "/";
return $home;
}
// Plan.io Task #4383
public function getBookingLogDir()
{
$home = $this->getCustomLogsDir()."booking/";
return $home;
}
// Plan.io Task #4383
public function getBookingSavSlotLogDir()
{
$home = $this->getBookingLogDir()."booking_sav_slot/";
return $home;
}
// Plan.io Task #4383
public function getCleanBookingSavSlotLogDir()
{
$home = $this->getBookingLogDir()."clean_booking_sav_slot/";
return $home;
}
public function getGuardLogPath(SocietyGroup $societyGroup)
{
// Get the path to the log folder
// If the folder does not exits, this creates it
$logPath = $this->getGuardLogsDir();
// Try to get the name of the log file from the entity
$logName = $societyGroup->getGuardLog();
// If empty, craft it
if (empty($logName))
{
$today = new \DateTime();
$logName = "guard_log_".$today->format('Y_m_d')."_SG_".$societyGroup->getInternalRef().".log";
// Update the object
$societyGroup->setGuardLog($logName);
}
// Craft the path to the file
$logFile = $logPath . $logName;
// If the file does not exist, create it
if (!file_exists($logFile))
{
error_log("",3,$logFile);
}
return $logFile;
}
public function addTimestampToGuardLog($logFile)
{
$today = new \DateTime();
error_log("\n",3,$logFile);
error_log("\n",3,$logFile);
error_log($today->format("Y/m/d H:i:s"),3,$logFile);
error_log("\n",3,$logFile);
}
public function mobileAppLogCall($message = null)
{
// Global switch to enable/disable mobile app logging
$mobileAppLoggingActive = true;
if(!$mobileAppLoggingActive)
return false;
// Returns User object or null if not authenticated
$currentUser = $this->getCurrentUser();
if($currentUser === null) // Do not permit log if user is not authenticated, should not happen
return false;
// Check that current user is not an AccessClient
if( ($currentUser instanceof AccessClient) )
return false;
$logPath = $this->getApiIcodLogsDir();
$now = new DateTime();
$logPath = $logPath . 'api_rest_log/mobileAppCall_' . $now->format('Y_m') . '.log';
$today = new \DateTime();
$currentDate = $today->format('Y-m-d H:i:s.v');
$trace = debug_backtrace();
$func = $trace[1]["function"];
$line = "" . $currentDate . "," . $currentUser->display() . "," . $currentUser->getId() . "," . $currentUser->getSocietyGroup()?->getRef() . "," . $currentUser->getSocietyGroup()?->getId() . "," . $func;
if($message !== null)
$line .= "," . $message;
$line .= "\n";
error_log($line, 3, $logPath);
}
public function getApiRestRateLimitLogPath(): string
{
$baseDir = $this->getApiIcodLogsDir() . "api_rest_log/";
if (!is_dir($baseDir))
{
if (!mkdir($baseDir, 0755, true))
{
$now = new \DateTime();
return $baseDir . "rate_limit_" . $now->format("Y") . "_" . $now->format("m") . ".csv";
}
}
$now = new \DateTime();
$fileName = "rate_limit_" . $now->format("Y") . "_" . $now->format("m") . ".csv";
return $baseDir . $fileName;
}
public function apiRestRateLimitLog(array $args): void
{
$scope = array_key_exists('scope', $args) ? (string) $args['scope'] : '';
$ip = array_key_exists('ip', $args) ? (string) $args['ip'] : '';
$accessApi = array_key_exists('accessApi', $args) && $args['accessApi'] instanceof AccessAPI ? $args['accessApi'] : null;
$route = array_key_exists('route', $args) ? (string) $args['route'] : '';
$maxRequests = array_key_exists('max_requests', $args) ? $args['max_requests'] : '';
$accessApiId = '';
$accessApiUsername = '';
$societyGroupId = '';
$societyGroupRef = '';
if ($accessApi instanceof AccessAPI)
{
$accessApiId = (string) $accessApi->getId();
$accessApiUsername = (string) $accessApi->getUsername();
$societyGroup = $accessApi->getSocietyGroup();
if ($societyGroup instanceof SocietyGroup)
{
$societyGroupId = (string) $societyGroup->getId();
$societyGroupRef = (string) $societyGroup->getRef();
}
}
$path = $this->getApiRestRateLimitLogPath();
$fileExists = file_exists($path);
$stream = fopen($path, $fileExists ? "a" : "w");
if ($stream === false)
{
return;
}
if (!$fileExists)
{
$header = [
"timestamp",
"scope",
"ip",
"access_api.id",
"access_api.username",
"society_group.id",
"society_group.ref",
"route",
"max_requests",
];
fputcsv($stream, $header, ';');
}
$now = new \DateTime();
$timestamp = $now->format("Y-m-d H:i:s");
$line = [
$timestamp,
$scope,
$ip,
$accessApiId,
$accessApiUsername,
$societyGroupId,
$societyGroupRef,
$route,
$maxRequests,
];
fputcsv($stream, $line, ';');
fclose($stream);
}
public function mobileAppLog(array $args)
{
if (empty($args['info_error'])) return false;
// Get data
$errorCode = $args['info_error']['errorCode'];
$errorMessage = $args['info_error']['errorMessage'];
$message = array_key_exists('message', $args) ? $args['message'] : null;
// Optional
$author = array_key_exists('author', $args) ? $args['author'] : null;
if ($author === null)
{
if ($this->security->getUser() instanceof Access)
{
$author = $this->security->getUser();
}
else
{
$author = $this->em
->getRepository(Access::class)
->findOneByUsername(Access::API_ACCESS);
}
}
$authorId = '';
$authorUsername = '';
$authorSocietyGroup = '';
$authorSocietyGroupId = '';
if ($author !== null)
{
$authorId = $author->getId();
$authorUsername = $author->getUsername();
$authorSocietyGroup = $author->getSocietyGroup();
if ($authorSocietyGroup !== null) {
$authorSocietyGroupId = $authorSocietyGroup->getId();
}
}
// Handle OriginalUser
$originalUser = $this->getOriginalUser();
$originalUserId = '';
$originalUserName = '';
if ($originalUser !== null)
{
$originalUserId = $originalUser->getId();
$originalUserName = $originalUser->getUserIdentifier();
}
// Error
$error = false;
if (array_key_exists('error', $args) && ($args['error'] == false || $args['error'] == true))
{
$error = $args['error'];
}
$status = $error ? 'ERROR' : 'DONE';
$logPath = $this->getApiIcodLogsDir();
$now = new DateTime();
$logPath = $logPath . 'api_rest_log/mobile_app_' . $now->format('Y_m') . '.log';
$path = $logPath;
// Backtrace
$backTrace = debug_backtrace()[1];
$backTraceMethod = $backTrace['function'];
$backTraceClass = $backTrace['class'];
// Date
$now = new \DateTime();
$nowDate = $now->format('Y-m-d H:i:s');
$line = "[ " . $nowDate . " ][ " . $status . " ][ " . $errorCode . " ][ " . $errorMessage . " ][ id societyGroup : " . $authorSocietyGroupId . " ][ id access : " . $authorId . " ][ " . $authorUsername . " ][ " . $originalUserId . " ][ " . $originalUserName . " ][ " . $backTraceClass . " ][ " . $backTraceMethod . " ]\t";
if(!empty($message)) $line .= " : " . $message;
$line .= "\n";
error_log($line, 3, $logPath);
}
public function mobileAppLogInternal(array $args)
{
if (empty($args)) return false;
if (!array_key_exists('info_error', $args) || !is_array($args['info_error']))
{
return false;
}
$infoError = $args['info_error'];
$author = array_key_exists('author', $args) ? $args['author'] : null;
if ($author === null)
{
if ($this->security->getUser() instanceof Access)
{
$author = $this->security->getUser();
}
else
{
$author = $this->em
->getRepository(Access::class)
->findOneByUsername(Access::API_ACCESS);
}
}
$authorId = '';
$authorUsername = '';
$authorSocietyGroupId = '';
if ($author !== null)
{
$authorId = $author->getId();
$authorUsername = $author->getUsername();
$authorSocietyGroup = $author->getSocietyGroup();
if ($authorSocietyGroup !== null)
{
$authorSocietyGroupId = $authorSocietyGroup->getId();
}
}
$originalUser = $this->getOriginalUser();
$originalUserId = '';
$originalUserName = '';
if ($originalUser !== null)
{
$originalUserId = $originalUser->getId();
$originalUserName = $originalUser->getUserIdentifier();
}
$now = new DateTime();
$logPath = $this->getApiIcodLogsDir();
$logPath = $logPath . 'api_rest_log/mobile_app_internal_' . $now->format('Y_m') . '.log';
if (!file_exists($logPath))
{
$header = "[ Date ][ Code ][ Message ][ GUID ][ GUID Entity ][ Date Error ][ OS ][ Version ][ id societyGroup ][ id access ][ Author ][ OriginalUserId ][ OriginalUserName ][ StackTrace ]";
error_log($header . "\n", 3, $logPath);
}
$stackTrace = array_key_exists('stackTrace', $infoError) ? $infoError['stackTrace'] : null;
$code = array_key_exists('code', $infoError) ? $infoError['code'] : null;
$message = array_key_exists('message', $infoError) ? $infoError['message'] : null;
$guid = array_key_exists('guid', $infoError) ? $infoError['guid'] : null;
$guidEntity = array_key_exists('guidEntity', $infoError) ? $infoError['guidEntity'] : null;
$date = array_key_exists('date', $infoError) ? $infoError['date'] : null;
$version = array_key_exists('version', $infoError) ? $infoError['version'] : null;
$os = array_key_exists('os', $infoError) ? $infoError['os'] : null;
$info = array_key_exists('info', $infoError) ? $infoError['info'] : null;
$nowDate = $now->format('Y-m-d H:i:s');
$line = "[ " . $nowDate . " ][ " . $code . " ][ " . $message . " ][ " . $guid . " ][ " . $guidEntity . " ][ " . $date . " ][ " . $os . " ][ " . $version . " ][ id societyGroup : " . $authorSocietyGroupId . " ][ id access : " . $authorId . " ][ " . $authorUsername . " ][ " . $originalUserId . " ][ " . $originalUserName . " ][ " . $stackTrace . " ]";
if (!empty($info)) $line .= " : " . $info;
$line .= "\n";
error_log($line, 3, $logPath);
}
public function hasMobileAppLogGuid($guid): bool
{
if ($guid === null || empty($guid))
{
return false;
}
$baseDir = $this->getApiIcodLogsDir() . 'api_rest_log/';
if (!is_dir($baseDir))
{
return false;
}
$pattern = $baseDir . 'mobile_app_internal_*.log';
$needle = '[ ' . $guid . ' ]';
$files = glob($pattern);
if ($files === false)
{
return false;
}
foreach ($files as $file)
{
$handle = @fopen($file, 'rb');
if ($handle === false)
{
continue;
}
while (($line = fgets($handle)) !== false)
{
if (strpos($line, $needle) !== false)
{
fclose($handle);
return true;
}
}
fclose($handle);
}
return false;
}
public function planning_optimisation_error_log($args)
{
$home = $this->getPlanningOptimisationLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "errors/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "planning_errors_".$today->format("Ymd").".log";
$logFile = $home . $log;
$jsonString = json_encode($args, JSON_PRETTY_PRINT);
$fp = fopen($logFile, 'a');
// Is it empty ?
if (filesize($logFile))
{
// Not empty
// Remove last char "}" of file and add ,
$stat = fstat($fp);
ftruncate($fp, $stat['size']-1);
fwrite($fp, ",\n");
}
else
{
// Empty
// Write begining of json object
fwrite($fp, "{\n");
}
fwrite($fp, '"'.uniqid().'"' . " : ");
fwrite($fp, $jsonString);
fwrite($fp, "}");
fclose($fp);
}
public function kitchenPlannerErrorlog($msg)
{
$home = $this->getIkeaKitchenPlannerLogsDir();
if (!is_dir($home))
mkdir($home, 0755, true);
$home .= "errors/";
if (!is_dir($home))
mkdir($home, 0755, true);
$today = new \DateTime();
$log = "kitchen_planner_errors_".$today->format("Ymd").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
public function planning_optimisation_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getPlanningOptimisationLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m');
$log = "planning_optimisation_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
// Logs Errors to root/custom_logs/stripe/errors/stripe_errors_yyyymmdd.log
// One single log each day
public function stripe_error_log($args)
{
$home = $this->getStripeLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$home .= "errors/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "stripe_errors_".$today->format("Ymd").".log";
$logFile = $home . $log;
$jsonString = json_encode($args, JSON_PRETTY_PRINT);
$fp = fopen($logFile, 'a');
// Is it empty ?
if (filesize($logFile))
{
// Not empty
// Remove last char "}" of file and add ,
$stat = fstat($fp);
ftruncate($fp, $stat['size']-1);
fwrite($fp, ",\n");
}
else
{
// Empty
// Write begining of json object
fwrite($fp, "{\n");
}
fwrite($fp, '"'.uniqid().'"' . " : ");
fwrite($fp, $jsonString);
fwrite($fp, "}");
fclose($fp);
}
// Logs Errors to root/custom_logs/guest_suite_log/guest_suite_yyyymmdd.log
// One single log each day
public function guest_suite_log($args)
{
$home = $this->getGuestSuiteLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "guest_suite_".$today->format("Ymd").".log";
$logFile = $home . $log;
$jsonString = json_encode($args, JSON_PRETTY_PRINT);
$fp = fopen($logFile, 'a');
// Is it empty ?
if (filesize($logFile))
{
// Not empty
// Remove last char "}" of file and add ,
$stat = fstat($fp);
ftruncate($fp, $stat['size']-1);
fwrite($fp, ",\n");
}
else
{
// Empty
// Write begining of json object
fwrite($fp, "{\n");
}
fwrite($fp, '"'.uniqid().'"' . " : ");
fwrite($fp, $jsonString);
fwrite($fp, "}");
fclose($fp);
}
// Logs to root/custom_logs/sms_logs/sms_reminder_task_yyyy_mm.log
// Used by CRON command reminder
public function sms_reminder_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getSmsLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m');
$log = "sms_reminder_task_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$content = $timestamp . $msg;
error_log("\n".$content,3,$logFile);
}
// Logs to root/custom_logs/sms_logs/sms_debug_yyyy_mm.log
// Used to debug info SMS
// For errors check LogTools::smsLogDebug method/file
public function sms_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getSmsLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m');
$log = "sms_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
// Logs to root/custom_logs/email_logs/email_debug_yyyy_mm.log
// Handles Backtrace info
public function email_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getEmailLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m');
$log = "email_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
// Logs to root/custom_logs/stripe/stripe_yyyymmdd.log
// One single log each day
public function stripe_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getStripeLogsDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "stripe_".$today->format("Ymd").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// OLD : Logs to root/custom_logs/ikea_debug/ikea_os_yyyymm.log
// NEW : Logs to root/custom_logs/ikea_debug/ikea_os_yyyy_week_{weekNumber}.log
// One single log each week - Log file created on Monday
public function ikea_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getCustomLogsDir()."ikea_debug/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
// Old format : Each month
// $log = "ikea_os_".$today->format("Y").$today->format("m").".log";
// New format : Each week on Mondays
// ikea_os_2026_week_21.log
$log = "ikea_os_".$today->format("o")."_week_".$today->format("W").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
$this->plooplog("\n".$timestamp.$msg."\n");
}
// Logs to root/custom_logs/ikea_debug_status/ikea_os_status_yyyymmdd.log
// One single log each day
public function ikea_debug_status($active, $msg)
{
if (!$active)
return false;
$home = $this->getCustomLogsDir()."ikea_debug_status/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "ikea_os_status_".$today->format("Ymd").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// Logs to root/custom_logs/ikea_debug_status/ikea_os_cancelled_yyyymm.log
// One single log each month
public function ikea_debug_cancelled($active, $msg)
{
if (!$active)
return false;
$home = $this->getCustomLogsDir()."ikea_debug_status/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "ikea_os_cancelled_".$today->format("Ym").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
public function ikea_send($args)
{
//Returns User object or null if not authenticated
$currentUser = $this->getCurrentUser();
if ($currentUser === null)
{
return false;
}
$home = $this->getIkeaSendLogsDir($currentUser->getSocietyGroup());
if ($home === null)
{
return false;
}
$now = new \DateTime();
$log = "ikea_object_send_".$now->format("Ym").".csv";
$logFile = $home . $log;
// $user = array_key_exists('user', $args) ? (string) $args['user'] : '';
$filename = array_key_exists('filename', $args) ? (string) $args['filename'] : '';
$targetPath = array_key_exists('targetPath', $args) ? (string) $args['targetPath'] : '';
$ikeaOrderNumber = array_key_exists('ikeaOrderNumber', $args) ? (string) $args['ikeaOrderNumber'] : '';
$action = array_key_exists('action', $args) ? (string) $args['action'] : '';
$result = array_key_exists('result', $args) ? (string) $args['result'] : '';
$fileExists = file_exists($logFile);
$stream = fopen($logFile, $fileExists ? "a" : "w");
if ($stream === false)
{
return false;
}
if (!$fileExists)
{
$header = [
"timestamp",
"user",
"filename",
"targetPath",
"ikeaOrderNumber",
"action",
"result",
];
fputcsv($stream, $header, ';');
}
$timestamp = $now->format("Y-m-d H:i:s");
$line = [
$timestamp,
$currentUser->getUsername(),
$filename,
$targetPath,
$ikeaOrderNumber,
$action,
$result,
];
fputcsv($stream, $line, ';');
fclose($stream);
return true;
}
// Logs to root/custom_logs/cost/auto_accounting/cost_auto_accounting_debug_yyyy_mm_dd.log
// Handles Backtrace info
public function cost_auto_accounting_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getCostAutoAccountingDebugDir();
if ($home === null) return false;
$today = new \DateTime();
$ym = $today->format('Y_m_d');
$log = "cost_auto_accounting_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
return true;
}
// Logs to root/custom_logs/invoice/auto_accounting/invoice_auto_accounting_debug_yyyy_mm_dd.log
// Handles Backtrace info
public function invoice_auto_accounting_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getInvoiceAutoAccountingDebugDir();
if ($home === null) return false;
$today = new \DateTime();
$ym = $today->format('Y_m_d');
$log = "invoice_auto_accounting_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
return true;
}
// Logs to root/custom_logs/zone/debug/zone_debug_yyyy_mm_dd.log
// Handles Backtrace info
public function zone_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getZoneDebugDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m_d');
$log = "zone_debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
$content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
// Logs to root/custom_logs/itask_logs/debug/debug_yyyy_mm_dd.log
public function itask_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getITaskDebugDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$ym = $today->format('Y_m_d');
$log = "debug_$ym.log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
$content = $msg;
// $backTrace = debug_backtrace()[1];
// $method = $backTrace['function'];
// $class = $backTrace['class'];
// $trace = $class."::".$method;
// $trace = str_replace("\\", "::", $trace);
//
// $content = "[".$trace . "] " . $msg;
error_log("\n".$timestamp.$content."\n",3,$logFile);
}
// Logs to root/custom_logs/pra/pra_os_yyyymm.log
// One single log each month
public function pra_debug($active, $msg)
{
if (!$active)
return false;
$home = $this->getCustomLogsDir()."pra/";
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "pra_".$today->format("Y").$today->format("m").".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// Used to trace SMS related errors
// For happy path check LogTools::sms_debug method/file
public function smsLogDebug($msg, $activeProvider = null)
{
$today = new \DateTime();
$ym = $today->format('Y_m');
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$traceLevelOne = str_replace("\\", "::", $trace);
$backTrace = debug_backtrace()[2];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$traceLevelTwo = str_replace("\\", "::", $trace);
// $backTrace = debug_backtrace()[3];
// $method = $backTrace['function'];
// $class = $backTrace['class'];
// $trace = $class."::".$method;
// $traceLevelThree = str_replace("\\", "::", $trace);
// $content = $traceLevelOne . " : " . $traceLevelTwo . " : " . $traceLevelThree . " : " . $msg;
$content = $traceLevelOne . " : " . $traceLevelTwo . " : " . $msg;
if ($activeProvider !== null)
{
if ($activeProvider->isSmsMode())
{
$file = $this->getSmsLogsDir() . "sms_mode_$ym.log";
}
else
{
if ($activeProvider->isSmsTwilio())
{
$file = $this->getSmsLogsDir() . "sms_twilio_$ym.log";
}
}
}
else
{
$file = $this->getSmsLogsDir() . "sms_unknown_provider_$ym.log";
}
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$content."\n",3,$file);
}
// Task plan.io #4024
// Logs to root/custom_logs/availability/availability_clean_{Y_m_d}.log
public function availabilityClean_log($msg)
{
$home = $this->getAvailablityDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "availability_clean_" . $today->format("Y") . "_" . $today->format("m") . "_" . $today->format("d") . ".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log("\n".$timestamp.$msg."\n",3,$logFile);
}
// Task plan.io #4386
// Logs to root/custom_logs/financial/scan_financial/scan_financial_{Y_m_d}.log
public function scanFinancialCommand_log($msg)
{
$home = $this->getScanFinancialDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "scan_financial_" . $today->format("Y_m_d") . ".log";
$logFile = $home . $log;
$timestamp = $today->format("[Y-m-d H:i:s] ");
error_log($timestamp.$msg."\n",3,$logFile);
}
// Task plan.io #4386
// Logs to root/custom_logs/financial/duplicate_code/duplicate_code_{Y_m_d}.log
public function logDuplicateFinancialCode(Client $client, array $clientsSameAccount)
{
$home = $this->getDuplicateCodeFinancialDir();
if (!is_dir($home)) $do = mkdir($home, 0755, true);
$today = new \DateTime();
$log = "duplicate_code_" . $today->format("Y_m_d") . ".log";
$logFile = $home . $log;
// Build log message
$societyGroup = $client->getSocietyGroup();
$financial = $client->getFinancial();
$societyGroupDisplay = $societyGroup !== null ? $societyGroup->displayForLog() : '';
$financialDisplay = $financial !== null ? $financial->displayForLog() : '';
$timestamp = $today->format("[Y-m-d H:i:s] ");
$msg = "-------------------";
$msg .= "\n" . $timestamp;
$msg .= "\nSocietyGroup : " . $societyGroupDisplay;
$msg .= "\nClient : " . $client->displayForLog();
$msg .= "\nIndividual : " . $client->displayChildrenForLog();
$msg .= "\nFinancial : " . $financialDisplay;
$msg .= "\n";
$msg .= "\nOther client/financial concerned\n";
foreach($clientsSameAccount as $clientSameAccount)
{
$financialSameAccount = $clientSameAccount->getFinancial();
if ($financialSameAccount === null) continue;
$msg .= "\nClient : " . $clientSameAccount->displayForLog();
$msg .= ", Individual : " . $clientSameAccount->displayChildrenForLog();
$msg .= ", Financial : " . $financialSameAccount->displayForLog();
}
error_log("\n" . $msg,3,$logFile);
}
// Task plan.io #4331
// Logs to root/custom_logs/payment_logs/error
public function payment_log_error($msg, $args)
{
// Setup
$today = new \DateTime();
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
// Build logFile
$home = $this->getPaymentErrorLogDir();
if (!is_dir($home)) mkdir($home, 0755, true);
// Build args
$societyGroupDisplay = "no_society_group";
if (array_key_exists('society_group', $args) && $args['society_group'] instanceof SocietyGroup)
{
$societyGroupDisplay = $args['society_group']->displayForLog();
}
$type = !empty($args['type']) ? $args['type'] : "";
switch($type)
{
case OnlinePaymentType::CODE_STRIPE:
{
$prefixLog = "STRIPE";
break;
}
case OnlinePaymentType::CODE_PAYPAL:
{
$prefixLog = "PAYPAL";
break;
}
default:
{
$prefixLog = "PAYMENT";
break;
}
}
$logFilename = "payment_error_" . $today->format("Y-m-d") . ".log";
$logFilename = $home . $logFilename;
if (!file_exists($logFilename))
{
// Create header
$header = "payment_type,timestamp,society_group,trace,message";
error_log($header . "\n", 3, $logFilename);
}
// Log
$logMessage = $prefixLog . ",";
$logMessage .= $today->format("Y-m-d H:i:s") . ",";
$logMessage .= $societyGroupDisplay . ",";
$logMessage .= $trace . ",";
$logMessage .= $msg . "\n";
error_log($logMessage, 3, $logFilename);
}
// Plan.io Task #4327
// Logs to root/custom_logs/booking/booking_sav_slot
public function bookingSavSlot_log($msg, $args)
{
$home = $this->getBookingSavSlotLogDir();
if (!is_dir($home)) mkdir($home, 0755, true);
$today = new \DateTime();
$logFile = "booking-log-" . $today->format("Y-m-d") . ".log";
$logFile = $home . $logFile;
$devis = !empty($args['devis']) ? $args['devis'] : null;
$timestamp = $today->format("[Y-m-d H:i:s]");
$log = $timestamp;
if ($devis !== null)
{
$log .= "[".$devis->getId()."-".$devis->getRef()."]";
}
$log .= " " . $msg;
error_log($log."\n",3,$logFile);
}
// Plan.io Task #4327
// Logs to root/custom_logs/booking/clean_booking_sav_slot
public function cleanBookingSavSlot_log($msg)
{
$home = $this->getCleanBookingSavSlotLogDir();
if (!is_dir($home)) mkdir($home, 0755, true);
$today = new \DateTime();
$logFile = "clean-booking-log-" . $today->format("Y-m-d") . ".log";
$logFile = $home . $logFile;
error_log($msg."\n",3,$logFile);
}
public function errorlog_db($e)
{
if (!is_object($e))
{
return null;
}
if (!($e instanceof \Exception))
{
return null;
}
$sql = null;
$params = null;
$msg = null;
if (method_exists($e, 'getMessage') &&
method_exists($e, 'getQuery') &&
method_exists($e->getQuery(), 'getSql') &&
method_exists($e->getQuery(), 'getParams'))
{
$sql = $e->getQuery()->getSql();
$params = print_r($e->getQuery()->getParams(), true);
$msg = $e->getMessage();
}
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
// Access handling
$access = $this->getCurrentUser();
$originalUser = $this->getOriginalUser();
$accessData = "";
$originalUserData = "";
if ($access !== null)
{
$accessData = $access->displayForLog();
}
if ($originalUser !== null)
{
$originalUserData = $originalUser->displayForLog();
}
$args = array(
'recorded_by' => "LogTools::errorlog_db",
'class' => $class,
'method' => $method,
'access' => $accessData,
'original_access' => $originalUserData,
'msg' => $msg,
'query' => $sql,
'params' => $params,
);
$this->plooplog(print_r($args, true));
$this->ouchLogger->error('', $args);
}
public function errorlog($msg)
{
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
// Access handling
$access = $this->getCurrentUser();
$originalUser = $this->getOriginalUser();
$accessData = "";
$originalUserData = "";
if ($access !== null)
{
$accessData = $access->displayForLog();
}
if ($originalUser !== null)
{
$originalUserData = $originalUser->displayForLog();
}
$args = array(
'recorded_by' => "LogTools::errorlog",
'class' => $class,
'method' => $method,
'original_access' => $originalUserData,
'msg' => $msg,
);
if ($access instanceof Access)
{
$args['access'] = $accessData;
}
else
{
if ($access instanceof AccessClient)
{
$args['accessClient'] = $accessData;
}
else
{
if ($access instanceof AccessAPI)
{
$args['accessApi'] = $accessData;
}
}
}
$this->plooplog(print_r($args, true));
$this->ouchLogger->error('', $args);
}
// plan.io #3716
public function errorlogApi($msg, $accessApi)
{
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
// Access handling
$accessData = "";
if ($accessApi !== null)
{
$accessData = $accessApi->displayForLog();
}
$args = array(
'class' => $class,
'method' => $method,
'access' => $accessData,
'msg' => $msg,
);
$this->ouchLogger->error('', $args);
}
public function getCurrentUser()
{
$emptyAccess = $this->em->getRepository(Access::class)->findOneByEmail(Access::EMPTY_ACCESS);
// Get the Access|AccessAPI|AccessClient object returned by the security
$access = $this->security->getUser();
if (empty($access))
{
// This occurs when the code is execuded by a Command (CRON Task for example)
// In this case there is no firewall, and thus no Access|AccessAPI
$access = $emptyAccess;
}
else
{
// The firewall has been bypassed => We have an user provider,
// either Access or AccessAPI
// Plan.io Task #4327 ... or an AccessClient :)
if (!($access instanceof Access) && !($access instanceof AccessAPI) && !($access instanceof AccessClient))
{
// This should not happen, but hey, life is weird, who knows
// Even VSCode proved to be worse than Atom ;)
$access = $emptyAccess;
}
}
// Plan.io Task #3946
if ($access instanceof AccessAPI)
{
// Almost all AccessAPI have a corresponding Access, so retrive it
$access = $access->getAccess();
}
return $access;
}
// https://symfony.com/doc/5.4/security/impersonating_user.html
// This is also in AdminVoter
// This is also in Logger
// This is also in LogTools
// This is also in AccessTools
// This is also in AlertTools
public function getOriginalUser()
{
$originalUser = null;
// #3251 Fix to avoid infinity loop
$currentUser = $this->getCurrentUser();
if ($currentUser === null || $currentUser->getEmail() == Access::EMPTY_ACCESS)
{
return null;
}
$token = $this->security->getToken();
if ($token instanceof SwitchUserToken)
{
$originalUser = $token->getOriginalToken()->getUser();
}
return $originalUser;
}
public function generateAlphaNumCode($length)
{
$lowercase = "qwertyuiopasdfghjklzxcvbnm";
$numbers = "1234567890";
$randomCode = "";
$length = abs($length);
$lengthSlice = $length / 2;
$max = strlen($lowercase) - 1;
for ($x = 0; $x < $lengthSlice; $x++)
{
$i = random_int(0, $max);
$randomCode .= $lowercase[$i];
}
$max = strlen($numbers) - 1;
for ($x = 0; $x < $lengthSlice; $x++)
{
$i = random_int(0, $max);
$randomCode .= $numbers[$i];
}
return str_shuffle($randomCode);
}
public function generateUniqueGuardLogFileName()
{
$today = new \DateTime();
$prefix = "guard_log_".$today->format("Y_m_d")."_";
$code = $this->generateAlphaNumCode(30);
$logFileName = $prefix . $code . ".log";
return $logFileName;
}
public function fetchGuardLogFile($logFileName)
{
$logPath = $this->getGuardGlobalLogsDir();
if (!file_exists($logPath))
{
if (!mkdir($logPath))
{
return null;
}
}
$logFile = $logPath.$logFileName;
return $logFile;
}
public function formatGuardLogFile($logFile)
{
if (!file_exists($logFile))
{
return "";
}
$log = file_get_contents($logFile);
if ($log)
{
$log = str_replace("\n", "<br>", $log);
$log = str_replace("not found", "<span class='text-danger'>not found</span>", $log);
$log = str_replace("inactive", "<span class='text-danger'>inactive</span>", $log);
$log = str_replace("error", "<span class='text-danger'><strong>error</strong></span>", $log);
$log = str_replace("ADD", "<span style='color:#39c300'><strong>ADD</strong></span>", $log);
$log = str_replace("DENY", "<span style='color:#ff731d'><strong>DENY</strong></span>", $log);
$log = str_replace("ERROR", "<span style='color:#da0000'><strong>ERROR</strong></span>", $log);
$log = str_replace("UPDATE", "<span style='color:#af0076'><strong>UPDATE</strong></span>", $log);
$log = str_replace("SYNC", "<span style='color:#d800a6'><strong>SYNC</strong></span>", $log);
$log = str_replace("DEACTIVATE", "<span style='color:#645caa'><strong>DEACTIVATE</strong></span>", $log);
$log = str_replace("ACTIVATE", "<span style='color:#645caa'><strong>ACTIVATE</strong></span>", $log);
$log = str_replace("REMOVE", "<span style='color:#F94A29'><strong>REMOVE</strong></span>", $log);
$log = str_replace("DELETE", "<span style='color:#F94A29'><strong>DELETE</strong></span>", $log);
}
return $log;
}
public function loadGuardFile($logFile, $fileName)
{
$log = null;
$matrix = null;
// Get the configuration file
$webPath = $this->getGuardConfigDir();
$matrixFile = $webPath . $fileName;
if (!file_exists($matrixFile))
{
$log = array(
"status" => false,
"error" => "config_file_does_not_exist",
"info" => $matrixFile,
);
}
else
{
// Read its contents
$matrix = file_get_contents($matrixFile);
if (!$matrix)
{
$log = array(
"status" => false,
"error" => "config_file_could_not_be_read",
"info" => $matrixFile,
);
}
else
{
// If we are here it means that all went well
return $matrix;
}
}
if ($log !== null)
{
// Something went wrong
// Get the error and translate it
$error = $this->translator->trans($log["error"]);
$error .= " : ";
$error .= $log["info"];
// Save it to the log file, if any
if ($logFile !== null)
{
error_log("\n".$error, 3, $logFile);
}
// Log it to global logs also
$this->errorlog($error);
return null;
}
// If we are here it means that all went well
return $matrix;
}
public function loadGuardConfigFile($logFile, $fileName)
{
$log = null;
$matrix = null;
// Get the configuration file
$webPath = $this->getGuardConfigDir();
$matrixFile = $webPath . $fileName;
if (!file_exists($matrixFile))
{
$log = array(
"status" => false,
"error" => "config_file_does_not_exist",
"info" => $matrixFile,
);
}
else
{
// Read its contents
$matrix = file_get_contents($matrixFile);
if (!$matrix)
{
$log = array(
"status" => false,
"error" => "config_file_could_not_be_read",
"info" => $matrixFile,
);
}
else
{
// Parse it
$yamlparser = new \Symfony\Component\Yaml\Parser();
$matrix = $yamlparser->parse($matrix);
if (!$matrix || empty($matrix))
{
$log = array(
"status" => false,
"error" => "config_file_could_not_be_parsed",
"info" => $matrixFile,
);
}
}
}
if ($log !== null)
{
// Something went wrong
// Get the error and translate it
$error = $this->translator->trans($log["error"]);
$error .= " : ";
$error .= $log["info"];
// Save it to the log file, if any
if ($logFile !== null)
{
error_log("\n".$error, 3, $logFile);
}
// Log it to global logs also
$this->errorlog($error);
return null;
}
// If we are here it means that all went well
return $matrix;
}
// Plan.io Task #4105
public function loadSocietyGroupDeleteScript(SocietyGroup $societyGroup)
{
$matrix = null;
$fileName = "society_group_delete.sql";
// Get the configuration file
$webPath = $this->getGuardConfigDir();
$matrixFile = $webPath . $fileName;
if (!file_exists($matrixFile))
{
return array(
"status" => false,
"error" => "config_file_does_not_exist",
"info" => $matrixFile,
);
}
else
{
// Read its contents
$matrix = file_get_contents($matrixFile);
if (!$matrix)
{
return array(
"status" => false,
"error" => "config_file_could_not_be_read",
"info" => $matrixFile,
);
}
else
{
// If we are here it means that all went well
// Replace SGID with $societyGroup->id
$matrix = str_replace("SGID", $societyGroup->getId(), $matrix);
return array(
"status" => true,
"data" => $matrix,
);
}
}
return array(
"status" => false,
"error" => "unknown_error",
"info" => $matrixFile,
);
}
// Types : add, deny, error, update, sync, activate, deactivate
// add : #39c300 rgb(57,195,0)
// deny : #ff731d rgb(255,115,29)
// error : #da0000 rgb(218,0,0)
// update : #af0076 rgb(175,0,118)
// sync : #d800a6 rgb(216,0,166)
// activate : #645caa rgb(100,92,170)
// deactivate : #645caa rgb(160,132,202)
public function guardLog($logFile, $msg, $type = null)
{
if ($logFile === null)
{
return false;
}
$backTrace = debug_backtrace();
// When the logging is done by the SocietyGroupGenerator
// Allow the deny statements
// Skip them otherwise
$allowDeny = false;
if (in_array($type, array("deny")))
{
if (isset($backTrace[2]))
{
$method = $backTrace[2]['function'];
// $this->plooplog("method(2) = ".$method);
if ($method == 'createSocietyGroupWithGuard')
{
$allowDeny = true;
}
}
}
if (in_array($type, array("deny")) && !$allowDeny)
{
return false;
}
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$class = str_replace("App\\Guardian\\", "", $class);
$class = str_replace("App\\Services\\", "", $class);
$class = str_replace("App\\Controller\\", "", $class);
if ($type !== null)
{
$msg = "\n" . strtoupper($type) . " ; " . $class . " ; " . $method . " ; " . $msg;
}
else
{
$msg = "\n" . $class . " ; " . $method . " ; " . $msg;
}
error_log($msg, 3, $logFile);
return true;
}
public function logInvoiceMissingDevisProduct(Invoice $invoice, Devis $devis, $msg)
{
$logFile = $this->getInvoiceMissingDevisProductsLogsDir().$invoice->getSocietyGroup()->getId().".log";
$today = new \DateTime();
$timestamp = $today->format("Y-m-d H:i:s");
$invoiceId = $invoice->getId();
$invoiceRef = $invoice->getRef();
$devisId = $devis->getId();
$devisRef = $devis->getRef();
$output = "\n[$timestamp][$invoiceId][$invoiceRef][$devisId][$devisRef]$msg";
error_log($output, 3, $logFile);
}
//--------------------------------------------------------------------------
// Plan.io Task #3922
public function camelToSnakeCase($text)
{
return strtolower(preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $text));
}
public function handleLoggingData($entity)
{
$info = null;
$specialAuthor = null;
$ignore = false;
$action = null;
if (method_exists($entity, "getLoggingData"))
{
$loggingData = $entity->getLoggingData();
// $this->ploopLog("[LogTools][handleLoggingData] --------------------------------------------------");
// $this->ploopLog("[LogTools][handleLoggingData] entity = ".$entity->displayForLog());
// $this->ploopLog("[LogTools][handleLoggingData] loggingData = ".print_r($loggingData, true));
if (!empty($loggingData) && is_array($loggingData))
{
if (array_key_exists('action', $loggingData))
{
$action = $loggingData['action'];
}
if (array_key_exists('info', $loggingData))
{
$info = $loggingData['info'];
}
if (array_key_exists('special_author', $loggingData))
{
$specialAuthor = $loggingData['special_author'];
}
if (array_key_exists('ignore', $loggingData))
{
$ignore = boolval($loggingData['ignore']);
}
}
}
// $this->ploopLog("[LogTools][handleLoggingData] info = ".$info);
// if ($ignore) $this->ploopLog("[LogTools][handleLoggingData] ignore = true");
// else $this->ploopLog("[LogTools][handleLoggingData] ignore = false");
// $this->ploopLog("[LogTools][handleLoggingData] --------------------------------------------------");
return array(
'action' => $action,
'info' => $info,
'special_author' => $specialAuthor,
'ignore' => $ignore,
);
}
//--------------------------------------------------------------------------
// Plan.io Task #3922
public function getLogPathForMission(Mission $mission)
{
$originalLogPath = $this->getDMS_MissionLogsDir();
$societyGroup = $mission->getSocietyGroupAuthor();
if ($societyGroup === null)
{
return null;
}
$societyGroupId = $societyGroup->getId();
$societyGroupRef = $societyGroup->getInternalRef();
if (empty($societyGroupId) || empty($societyGroupRef))
{
return null;
}
// Craft folder name
$logFolderName = $societyGroupId."_".$societyGroupRef;
$logPath = $originalLogPath.$logFolderName."/";
// Craft file name
$id = $mission->getId();
$logFileName = "mission_log_".$id.".csv";
$logFile = $logPath.$logFileName;
if (file_exists($logFile))
{
return $logFile;
}
return null;
}
// Plan.io Task #3922
public function getLogPathForClient(Client $client)
{
$originalLogPath = $this->getDMS_ClientLogsDir();
$societyGroup = $client->getSocietyGroup();
if ($societyGroup === null)
{
return null;
}
$societyGroupId = $societyGroup->getId();
$societyGroupRef = $societyGroup->getInternalRef();
if (empty($societyGroupId) || empty($societyGroupRef))
{
return null;
}
// Craft folder name
$logFolderName = $societyGroupId."_".$societyGroupRef;
$logPath = $originalLogPath.$logFolderName."/";
// Craft file name
$id = $client->getId();
$logFileName = "client_log_".$id.".csv";
$logFile = $logPath.$logFileName;
if (file_exists($logFile))
{
return $logFile;
}
return null;
}
/**
* Returns the path to the CSV log file for the given human resource, or null if not found.
* Path pattern: DMS/Logs/HumanResource/{societyGroupId}_{societyGroupRef}/human_resource_log_{id}.csv
*/
public function getLogPathForHumanResource(HumanResource $humanResource)
{
$originalLogPath = $this->getDMS_HumanResourceLogsDir();
$societyGroup = $humanResource->getSocietyGroup();
if ($societyGroup === null)
{
return null;
}
$societyGroupId = $societyGroup->getId();
$societyGroupRef = $societyGroup->getInternalRef();
if (empty($societyGroupId) || empty($societyGroupRef))
{
return null;
}
$logFolderName = $societyGroupId."_".$societyGroupRef;
$logPath = $originalLogPath.$logFolderName."/";
$id = $humanResource->getId();
$logFileName = "human_resource_log_".$id.".csv";
$logFile = $logPath.$logFileName;
if (file_exists($logFile))
{
return $logFile;
}
return null;
}
// Plan.io Task #4624
public function getLogPathForProjectNotebook(ProjectNotebook $notebook)
{
$originalLogPath = $this->getDMS_ProjectManagerNotebookLogsDir();
$societyGroup = $notebook->getSocietyGroup();
if ($societyGroup === null)
{
return null;
}
$societyGroupId = $societyGroup->getId();
$societyGroupRef = $societyGroup->getInternalRef();
if (empty($societyGroupId) || empty($societyGroupRef))
{
return null;
}
// Craft folder name
$logFolderName = $societyGroupId."_".$societyGroupRef;
$logPath = $originalLogPath.$logFolderName."/";
// Craft file name
$id = $notebook->getId();
$logFileName = "project_notebook_log_".$id.".csv";
$logFile = $logPath.$logFileName;
if (file_exists($logFile))
{
return $logFile;
}
return null;
}
/**
* Reads the logging CSV produced by Logging::logToFile() into an array of LogCsvRecord DTOs.
* File format: semicolon-delimited, first line may be blank, then header row, then data rows.
*
* #3922 : This was generated by Cursor => Review and Clean
*
* @return LogCsvRecord[]
*/
public function readLoggingCsv(string $filePath): array
{
// Ensure the file exists and is readable before attempting to load it
if (!is_readable($filePath))
{
return [];
}
// Load the entire file content (CSV may be written with mixed line endings by error_log)
$raw = file_get_contents($filePath);
if ($raw === false)
{
return [];
}
// Split into lines using any common newline sequence (Unix, Windows, legacy Mac)
$allLines = preg_split('/\r\n|\r|\n/', $raw);
if ($allLines === false)
{
return [];
}
// Drop empty lines so the first non-empty line is the header (Logging writes a leading newline)
$nonEmptyLines = array_values(array_filter($allLines, static function (string $line): bool
{
return trim($line) !== '';
}));
if (count($nonEmptyLines) < 2)
{
return [];
}
// First non-empty line is the semicolon-separated header row; normalize and remove empty cells
$headerLine = $nonEmptyLines[0];
$headers = array_values(array_filter(array_map('trim', explode(';', $headerLine)), static function (string $h): bool {
return $h !== '';
}));
// Parse each remaining line as a data row and map to a LogCsvRecord DTO
$records = [];
for ($i = 1, $n = count($nonEmptyLines); $i < $n; $i++)
{
$values = explode(';', $nonEmptyLines[$i]);
$records[] = LogCsvRecord::fromRow($headers, $values);
}
return $records;
}
/**
* Streams the logging CSV produced by Logging::logToFile() as LogCsvRecord DTOs.
* Use this for large files (e.g. tens of MB) to avoid loading the whole file into memory.
* File format: semicolon-delimited, first line may be blank, then header row, then data rows.
*
* #3922 : This was generated by Cursor => Review and Clean
* Working, but still too much data to output
* DOM loading is extremly slow ... and becomes not responsive
*
* @return \Generator<int, LogCsvRecord, void, void>
*
* Example:
* foreach ($logTools->readLoggingCsvXXL('/path/to/file.csv') as $record) {
* // process $record
* }
*/
public function readLoggingCsvXXL(string $filePath): \Generator
{
// Ensure the file exists and is readable before opening
if (!is_readable($filePath))
{
return;
}
$handle = fopen($filePath, 'rb');
if ($handle === false)
{
return;
}
try
{
// Read line by line (fgets stops at \n; \r\n or \r are included and trimmed below)
// so only one line is in memory at a time.
$headers = null;
while (($line = fgets($handle)) !== false)
{
$line = trim($line);
if ($line === '')
{
continue;
}
// First non-empty line is the header; parse and store for mapping data rows
if ($headers === null)
{
$headers = array_values(array_filter(
array_map('trim', explode(';', $line)),
static function (string $h): bool {
return $h !== '';
}
));
continue;
}
// Subsequent non-empty lines are data rows: parse and yield one record
$values = explode(';', $line);
yield LogCsvRecord::fromRow($headers, $values);
}
}
finally
{
// Always close the handle when the generator is exhausted or the consumer stops iterating
fclose($handle);
}
}
}