<?php
namespace App\Helpers\System;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\Yaml\Parser;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class LoggerHelper
{
protected $em;
public function __construct(UrlGeneratorInterface $router, TokenStorageInterface $tokenStorage, EntityManagerInterface $entityManager, RequestStack $requestStack)
{
$this->router = $router;
$this->token_storage = $tokenStorage;
$this->em = $entityManager;
$this->request = $requestStack;
// Known identifiers
$this->knownIdentifiers = [
"BOOKING" => [
"CREATE" => "created booking {{ BOOKING }}",
"EDIT" => "edited booking {{ BOOKING }}",
"DELETE" => "deleted {{ BOOKING }}",
"CANCELLED" => "cancelled booking {{ BOOKING }}",
"UNCANCELLED" => "uncancelled booking {{ BOOKING }}",
"EDIT_ADD_ANIMAL" => "added {{ ANIMAL }} to booking {{ BOOKING }}",
"EDIT_REMOVE_ANIMAL" => "removed {{ ANIMAL }} from booking {{ BOOKING }}",
"EDIT_EDIT_ANIMAL" => "edited {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_ANIMAL_ADD_SERVICE" => "added the service '{{ SERVICE }}' to {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_ANIMAL_EDIT_SERVICE" => "edited the service '{{ SERVICE }}' for {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_ANIMAL_REMOVE_SERVICE" => "removed the service '{{ SERVICE }}' from {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_ADD_PAYMENT" => "added a payment on booking {{ BOOKING }}",
"EDIT_REFUND_PAYMENT" => "refunded a payment from booking {{ BOOKING }}",
"EDIT_REMOVE_PAYMENT" => "removed a payment from booking {{ BOOKING }}",
"EDIT_EDIT_GUARDIAN" => "edited the guardian on booking {{ BOOKING }}",
"EDIT_REVERSE_CHECKIN" => "reversed the check in for animal: {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_REVERSE_CHECKOUT" => "reversed the check out for animal: {{ ANIMAL }} on booking {{ BOOKING }}",
"EDIT_DISCOUNT" => "updated the discount on booking {{ BOOKING }}"
],
"ANIMAL" => [
"CREATE" => "created {{ ANIMAL }}",
"EDIT" => "edited {{ ANIMAL }}",
"DELETE" => "deleted {{ ANIMAL }}",
"EDIT_VET" => "edited the vet for animal: {{ ANIMAL }}",
"REMOVE_VET" => "removed the vet from animal: {{ ANIMAL }}",
"MARKED_DECEASED" => "marked the animal {{ ANIMAL }} as deceased",
"UNMARKED_DECEASED" => "unmarked the animal {{ ANIMAL }} as deceased",
"DOCUMENT_UPLOAD" => "uploaded a document to {{ ANIMAL }}",
"DOCUMENT_DELETE" => "deleted a document from {{ ANIMAL }}"
],
"CUSTOMER" => [
"CREATE" => "created {{ CUSTOMER }}",
"EDIT" => "edited {{ CUSTOMER }}",
"EDIT_BLACKLIST" => "blacklisted customer {{ CUSTOMER }}",
"EDIT_REMOVEBLACKLIST" => "un-blacklisted customer {{ CUSTOMER }}",
"EDIT_ARCHIVE" => "archived customer {{ CUSTOMER }}",
"EDIT_RESTORE" => "restored customer {{ CUSTOMER }}",
"DELETE" => "deleted {{ CUSTOMER }}"
],
"VET" => [
"CREATE" => "created {{ VET }}",
"EDIT" => "edited {{ VET }}",
"DELETE" => "deleted {{ VET }}"
],
"AGREEMENT" => [
"CREATE" => "created {{ AGREEMENT }} for {{ CUSTOMER }}",
"EDIT" => "edited {{ AGREEMENT }} for {{ CUSTOMER }}"
],
"CUSTOMERAGREEMENT" => [
"EMAIL" => "sent agreement {{ CUSTOMERAGREEMENT }} via email to {{ CUSTOMER }}",
"DELETE" => "deleted {{ AGREEMENT }} for {{ CUSTOMER }}",
"INVALIDATE" => "invalidated agreement {{ CUSTOMERAGREEMENT }} for {{ CUSTOMER }}"
],
"PERMISSION" => [
"EDIT" => "edited the permissions",
],
"USER" => [
"CREATE" => "created {{ USER }}",
"EDIT" => "edited {{ USER }}",
"DELETE" => "deleted {{ USER }}",
"SUSPEND" => "suspended {{ USER }}"
],
"SETTING" => [
"CAPACITY_EDIT" => "edited capacity in settings",
"VACCINATION_CREATE" => "created vaccination type: {{ VACCINATION }}",
"VACCINATION_EDIT" => "edited vaccination type: {{ VACCINATION }}",
"VACCINATION_DELETE" => "deleted vaccination type: {{ VACCINATION }}",
"SERVICE_CREATE" => "created service: {{ SERVICE }}",
"SERVICE_EDIT" => "edited service: {{ SERVICE }}",
"SERVICE_DELETE" => "deleted service: {{ SERVICE }}",
"MIXERCATEGORY_CREATE" => "created mixer category: {{ MIXERCATEGORY }}",
"MIXERCATEGORY_EDIT" => "edited mixer category: {{ MIXERCATEGORY }}",
"MIXERCATEGORY_DELETE" => "deleted mixer category: {{ MIXERCATEGORY }}",
"ANIMALSIZE_CREATE" => "created animal size: {{ ANIMALSIZE }}",
"ANIMALSIZE_EDIT" => "edited animal size: {{ ANIMALSIZE }}",
"ANIMALSIZE_DELETE" => "deleted animal size: {{ ANIMALSIZE }}",
"ANIMALTYPE_CREATE" => "created animal type: {{ ANIMALTYPE }}",
"ANIMALTYPE_EDIT" => "edited animal type: {{ ANIMALTYPE }}",
"ANIMALTYPE_DELETE" => "deleted animal type: {{ ANIMALTYPE }}",
"PRICING_EDIT" => "edited pricing",
"ADDITIONALCHARGE_CREATE" => "created the additional charge: {{ ADDITIONALCHARGE }}",
"ADDITIONALCHARGE_EDIT" => "edited the additional charge: {{ ADDITIONALCHARGE }}",
"ADDITIONALCHARGE_DELETE" => "deleted the additional charge: {{ ADDITIONALCHARGE }}",
"DEPOSIT_CREATE" => "created the deposit type: {{ DEPOSIT }}",
"DEPOSIT_EDIT" => "edited the deposit type: {{ DEPOSIT }}",
"DEPOSIT_DELETE" => "deleted the deposit type: {{ DEPOSIT }}",
"MEAL_CREATE" => "created the meal: {{ MEAL }}",
"MEAL_EDIT" => "edited the meal: {{ MEAL }}",
"MEAL_DELETE" => "deleted the meal: {{ MEAL }}",
"MEALSIZE_CREATE" => "created the meal size: {{ MEALSIZE }}",
"MEALSIZE_EDIT" => "edited the meal size: {{ MEALSIZE }}",
"MEALSIZE_DELETE" => "deleted the meal size: {{ MEALSIZE }}",
"AGREEMENT_CREATE" => "created the agreement: {{ AGREEMENT }}",
"AGREEMENT_EDIT" => "edited the agreement: {{ AGREEMENT }}",
"AGREEMENT_INVALIDATE" => "invalidated the agreement: {{ AGREEMENT }}",
"AGREEMENT_DELETE" => "delete the agreement: {{ AGREEMENT }}",
"OPENINGTIME_CREATE" => "created the opening time: {{ OPENINGTIME }}",
"OPENINGTIME_EDIT" => "edited the opening time: {{ OPENINGTIME }}",
"OPENINGTIME_DELETE" => "deleted the opening time: {{ OPENINGTIME }}",
"BLOCKOUTDATE_CREATE" => "created the blockout date: {{ BLOCKOUTDATE }}",
"BLOCKOUTDATE_EDIT" => "edited the blockout date: {{ BLOCKOUTDATE }}",
"BLOCKOUTDATE_DELETE" => "deleted the blockout date: {{ BLOCKOUTDATE }}",
"USERGROUP_CREATE" => "created the user group: {{ USERGROUP }}",
"USERGROUP_EDIT" => "edited the user group: {{ USERGROUP }}",
"USERGROUP_DELETE" => "deleted the user group: {{ USERGROUP }}",
"MISC_EDIT" => "edited the misc settings",
],
"HANDSONCHECKLIST" => [
"CREATE" => "created {{ HANDSONCHECKLIST }}",
"DELETE" => "deleted {{ HANDSONCHECKLIST }}"
],
"LONGSTAYCHECKLIST" => [
"CREATE" => "created {{ LONGSTAYCHECKLIST }}",
"DELETE" => "deleted {{ LONGSTAYCHECKLIST }}"
]
];
}
public function record($identifier = null, $data = array())
{
$identifier = strtoupper($identifier);
// Split the itentifier up
$identifierBits = explode("_", $identifier);
// The area which the identifier belongs to
$identifierSection = $identifierBits[0];
// The rest of the identifier
unset($identifierBits[0]);
$identifierAction = implode("_", $identifierBits);
// Check if identifier section exists
if(!array_key_exists($identifierSection, $this->knownIdentifiers))
throw new \Exception("Section identifier '" . $identifierSection . "' does not exist.");
// Check if identifier is valid
if(!array_key_exists($identifierAction, $this->knownIdentifiers[$identifierSection]))
throw new \Exception("Identifier '" . $identifier . "' is not a known identifier.");
// Fetch the action into a variable
$action = $this->knownIdentifiers[$identifierSection][$identifierAction];
// Build data array
$formattedData = array();
// Loop the data
foreach($data AS $key => $someData)
{
$formattedData[$key] = array(
'id' => $someData->getId(),
'label' => $someData->__toString(),
'class' => get_class($someData)
);
}
// Count the number of tags in string
preg_match_all('/(?<={)[^}]*(?=})/', $action, $tagMatches);
// Inconsistent tag matches?
if(count($tagMatches[0]) != count($formattedData))
throw new \Exception("Inconsistent tag matches. You have provided " . count($formattedData) . ' data parameters. ' . count($tagMatches) . ' required!');
// Create new instance of audit log
$auditLog = new \App\Entity\System\AuditLog([
"ipAddress" => $_SERVER['REMOTE_ADDR'],
"url" => $this->request->getCurrentRequest()->getRequestUri(),
"identifier" => $identifier,
"data" => $formattedData,
"user" => $this->token_storage->getToken()->getUser()
]);
// Persist and flush
$this->em->persist($auditLog);
$this->em->flush($auditLog);
return;
}
public function render(?\App\Entity\System\AuditLog $auditLog = null)
{
if(!$auditLog)
throw new \Exception("Audit log must be provided!");
// Get identifier
$identifier = $auditLog->getIdentifier();
// Split the itentifier up
$identifierBits = explode("_", $identifier);
// The area which the identifier belongs to
$identifierSection = $identifierBits[0];
// The rest of the identifier
unset($identifierBits[0]);
$identifierAction = implode("_", $identifierBits);
// Fetch the action into a variable
$action = $this->knownIdentifiers[$identifierSection][$identifierAction];
// No action?
if(!$action)
return 'Unsupported action';
// Loop data to inject data
foreach($auditLog->getData() AS $key => $someData)
{
// Uppercase key
$tag = strtoupper($key);
// Search for the object
$entity = $this->em->getRepository($someData['class'])->findOneFiltered(array(
'id' => $someData['id'],
));
// Found an entity
if($entity)
{
// Get associated url
$url = $this->getEntityUrl($entity);
// Inject the tags with links
if($url)
$action = str_replace("{{ " . $tag . " }}", '<a href="' . $url . '">' . $someData['label'] . '</a>', $action);
else
$action = str_replace("{{ " . $tag . " }}", $someData['label'], $action);
}
else
$action = str_replace("{{ " . $tag . " }}", $someData['label'], $action);
}
// Got a user?
if($auditLog->getUser())
$action = $auditLog->getUser()->getName() . " " . $action;
// Return the action
return $action;
}
public function getEntityUrl($entity = null)
{
if(!$entity)
throw new \Exception("Provide an entity when looking up a url");
if($entity instanceof \App\Entity\Animals\Animal)
{
return $this->router->generate("animals_view", array(
'animal_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Bookings\Booking)
{
return $this->router->generate("bookings_edit", array(
'booking_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Bookings\Item)
{
return $this->router->generate("bookings_edit", array(
'booking_uuid' => $entity->getBooking()->getUuid()
));
}
elseif($entity instanceof \App\Entity\Customers\Customer)
{
return $this->router->generate("customers_edit", array(
'customer_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Users\User)
{
return $this->router->generate("users_edit", array(
'user_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Vets\Vet)
{
return $this->router->generate("vets_view", array(
'vet_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Agreements\Agreement)
{
return $this->router->generate("settings_agreements_edit", array(
'agreement_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Customers\Agreement)
{
return $this->router->generate("customers_view_agreements_download", array(
'agreement_uuid' => $entity->getUuid(),
'customer_uuid' => $entity->getCustomer()->getUuid()
));
}
elseif($entity instanceof \App\Entity\Services\AdditionalCharge)
{
return $this->router->generate("settings_additionalcharges_edit", array(
'additionalcharge_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Services\Deposit)
{
return $this->router->generate("settings_deposits_edit", array(
'deposit_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Users\Group)
{
return $this->router->generate("settings_usergroups_edit", array(
'group_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\System\BlockoutDate)
{
return $this->router->generate("settings_blockoutdates_edit", array(
'date_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Meals\Size)
{
return $this->router->generate("settings_meal_sizes_edit", array(
'size_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Meals\Meal)
{
return $this->router->generate("settings_meals_edit", array(
'meal_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Vaccinations\Type)
{
return $this->router->generate("settings_vaccinations_edit", array(
'vaccinationtype_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Services\Service)
{
return $this->router->generate("settings_services_edit", array(
'service_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\System\OpeningTime)
{
return $this->router->generate("settings_openingtimes_edit", array(
'period_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Animals\Type)
{
return $this->router->generate("settings_animaltypes_edit", array(
'type_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Animals\Size)
{
return $this->router->generate("settings_animalsizes_edit", array(
'size_uuid' => $entity->getUuid()
));
}
elseif($entity instanceof \App\Entity\Animals\MixerCategory)
{
return $this->router->generate("settings_mixercategories_edit", array(
'mixer_uuid' => $entity->getUuid()
));
}
return null;
}
public function getCategory(?\App\Entity\System\AuditLog $auditLog = null)
{
if(!$auditLog)
throw new \Exception("Audit log must be provided!");
$identifierBits = explode("_", $auditLog->getIdentifier());
// Return category only
return ucfirst(strtolower($identifierBits[0]));
}
}