2020-01-26 13:59:30 +01:00
< ? php
2020-02-22 18:14:36 +01:00
/**
* This file is part of Part - DB ( https :// github . com / Part - DB / Part - DB - symfony ) .
*
2022-11-29 22:28:53 +01:00
* Copyright ( C ) 2019 - 2022 Jan Böhmer ( https :// github . com / jbtronics )
2020-02-22 18:14:36 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*/
2020-02-01 16:17:20 +01:00
declare ( strict_types = 1 );
2020-01-26 13:59:30 +01:00
namespace App\Services\LogSystem ;
2023-06-11 14:55:06 +02:00
use Symfony\Bundle\SecurityBundle\Security ;
use Symfony\Component\Security\Core\User\UserInterface ;
2020-01-26 13:59:30 +01:00
use App\Entity\LogSystem\AbstractLogEntry ;
use App\Entity\UserSystem\User ;
2023-04-07 22:44:59 +02:00
use App\Services\Misc\ConsoleInfoHelper ;
2020-01-26 13:59:30 +01:00
use Doctrine\ORM\EntityManagerInterface ;
2023-06-11 15:02:59 +02:00
/**
* @ see \App\Tests\Services\LogSystem\EventLoggerTest
*/
2020-01-26 13:59:30 +01:00
class EventLogger
{
2023-06-11 14:55:06 +02:00
public function __construct ( protected int $minimum_log_level , protected array $blacklist , protected array $whitelist , protected EntityManagerInterface $em , protected Security $security , protected ConsoleInfoHelper $console_info_helper )
2020-01-26 13:59:30 +01:00
{
}
/**
* Adds the given log entry to the Log , if the entry fullfills the global configured criterias .
* The change will not be flushed yet .
2020-02-01 16:17:20 +01:00
*
2020-08-21 21:36:22 +02:00
* @ return bool returns true , if the event was added to log
2020-01-26 13:59:30 +01:00
*/
public function log ( AbstractLogEntry $logEntry ) : bool
{
$user = $this -> security -> getUser ();
//If the user is not specified explicitly, set it to the current user
2023-06-11 14:55:06 +02:00
if (( ! $user instanceof UserInterface || $user instanceof User ) && ! $logEntry -> getUser () instanceof User ) {
if ( ! $user instanceof User ) {
2020-01-26 13:59:30 +01:00
$repo = $this -> em -> getRepository ( User :: class );
$user = $repo -> getAnonymousUser ();
}
2020-02-03 13:33:15 +01:00
//If no anonymous user is available skip the log (needed for data fixtures)
2023-06-11 14:55:06 +02:00
if ( ! $user instanceof User ) {
2020-02-03 13:33:15 +01:00
return false ;
}
2020-01-26 13:59:30 +01:00
$logEntry -> setUser ( $user );
}
2023-04-07 22:44:59 +02:00
//Set the console user info, if the log entry was created in a console command
if ( $this -> console_info_helper -> isCLI ()) {
2023-04-08 01:13:13 +02:00
$logEntry -> setCLIUsername ( $this -> console_info_helper -> getCLIUser () ? ? 'Unknown' );
2023-04-07 22:44:59 +02:00
}
2020-01-26 13:59:30 +01:00
if ( $this -> shouldBeAdded ( $logEntry )) {
$this -> em -> persist ( $logEntry );
2020-02-01 16:17:20 +01:00
2020-01-26 13:59:30 +01:00
return true ;
}
return false ;
}
2023-01-24 22:55:03 +01:00
/**
* Same as log (), but this function can be safely called from within the onFlush () doctrine event , as it
* updated the changesets of the unit of work .
*/
public function logFromOnFlush ( AbstractLogEntry $logEntry ) : bool
{
if ( $this -> log ( $logEntry )) {
$uow = $this -> em -> getUnitOfWork ();
//As we call it from onFlush, we have to recompute the changeset here, according to https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/events.html#reference-events-on-flush
2023-06-11 14:15:46 +02:00
$uow -> computeChangeSet ( $this -> em -> getClassMetadata ( $logEntry :: class ), $logEntry );
2023-01-24 22:55:03 +01:00
return true ;
}
2023-04-15 23:14:53 +02:00
//If the normal log function does not get added to the log entry, we just do nothing
2023-01-24 22:55:03 +01:00
return false ;
}
2020-01-26 13:59:30 +01:00
/**
2023-04-15 23:14:53 +02:00
* Adds the given log entry to the Log , if the entry fulfills the global configured criteria and flush afterward .
2020-02-01 16:17:20 +01:00
*
2020-08-21 21:36:22 +02:00
* @ return bool returns true , if the event was added to log
2020-01-26 13:59:30 +01:00
*/
public function logAndFlush ( AbstractLogEntry $logEntry ) : bool
{
$tmp = $this -> log ( $logEntry );
$this -> em -> flush ();
2020-02-01 16:17:20 +01:00
2020-01-26 13:59:30 +01:00
return $tmp ;
}
public function shouldBeAdded (
AbstractLogEntry $logEntry ,
? int $minimum_log_level = null ,
? array $blacklist = null ,
? array $whitelist = null
) : bool {
//Apply the global settings, if nothing was specified
2023-06-11 14:15:46 +02:00
$minimum_log_level ? ? = $this -> minimum_log_level ;
$blacklist ? ? = $this -> blacklist ;
$whitelist ? ? = $this -> whitelist ;
2020-01-26 13:59:30 +01:00
2023-04-15 23:14:53 +02:00
//Don't add the entry if it does not reach the minimum level
2020-01-26 13:59:30 +01:00
if ( $logEntry -> getLevel () > $minimum_log_level ) {
return false ;
}
2023-04-15 23:14:53 +02:00
//Check if the event type is blacklisted
2023-06-11 14:15:46 +02:00
if ( $blacklist !== [] && $this -> isObjectClassInArray ( $logEntry , $blacklist )) {
2020-01-26 13:59:30 +01:00
return false ;
}
//Check for whitelisting
2023-04-15 23:14:53 +02:00
// By default, all things should be added
2023-06-11 14:15:46 +02:00
return ! ( $whitelist !== [] && ! $this -> isObjectClassInArray ( $logEntry , $whitelist ));
2020-01-26 13:59:30 +01:00
}
/**
2020-02-01 16:17:20 +01:00
* Check if the object type is given in the classes array . This also works for inherited types .
*
* @ param object $object The object which should be checked
2020-08-21 21:36:22 +02:00
* @ param string [] $classes the list of class names that should be used for checking
2020-01-26 13:59:30 +01:00
*/
protected function isObjectClassInArray ( object $object , array $classes ) : bool
{
//Check if the class is directly in the classes array
2023-06-11 14:15:46 +02:00
if ( in_array ( $object :: class , $classes , true )) {
2020-01-26 13:59:30 +01:00
return true ;
}
//Iterate over all classes and check for inheritance
foreach ( $classes as $class ) {
2023-06-11 14:15:46 +02:00
if ( $object instanceof $class ) {
2020-01-26 13:59:30 +01:00
return true ;
}
}
return false ;
}
2020-02-01 16:17:20 +01:00
}