Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions src/main/log/Archive/LogRotator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Claroline\LogBundle\Archive;

use Claroline\AppBundle\Persistence\ObjectManager;
use Claroline\LogBundle\Entity\AbstractLog;
use Claroline\LogBundle\Entity\Archive\SecurityLogArchive;
use Claroline\LogBundle\Repository\LogRepositoryInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Connection;

class LogRotator implements LogRotatorInterface
{
private $connection;
private $om;

public function __construct(Connection $connection, ObjectManager $om)
{
$this->connection = $connection;
$this->om = $om;
}

/**
* @param \DateTimeInterface $to The date until when log entries should be archived
* @param class-string $logType The FQCN of the log entity whose entries should be rotated
*/
public function rotateLogs(\DateTimeInterface $to, string $logType): void
{
$logRepository = $this->om->getRepository($logType);

if (!is_subclass_of($logRepository, LogRepositoryInterface::class)) {
throw new \LogicException(sprintf('The log entity must have a repository implementing "%s", "%s" given.', LogRepositoryInterface::class, get_debug_type($logType)));
}

// Find all log entries created before $to

/** @var AbstractLog $log */
foreach ($qb->getQuery()->getResult() as $log) {

}

/** @var AbstractLog $oldestLog */
$oldestLog = $logs->last();

$archiveTableName = $logType::ARCHIVE_TABLE_PREFIX."{$to->format('Ymd')}-{$oldestLog->getDate()->format('Ymd')}";

$findLastArchivedLogQuery = "SELECT date FROM {$lastArchiveTable} ORDER BY date DESC LIMIT 1";
$date = ''; // fixme perform query
$newArchiveTableName = SecurityLogArchive::ARCHIVE_TABLE_PREFIX.$now->getTimestamp();
$createArchiveTableQuery = <<<SQL
CREATE TABLE
SQL;

// Create archive table (claro_log_archive_functionnal_{$now} https://stackoverflow.com/questions/30871721/doctrine2-dynamic-table-name-for-entity
// Begin transaction
// Fetch active logs where date between $endDate and $toDate (preconfigured period)
// Move logs from active table to the archive table https://stackoverflow.com/questions/1612267/move-sql-data-from-one-table-to-another
// Delete archived logs from active logs table

// Add claro_log_archives table to keep a reference of all archives (filename, date from, date to)

}

private function getLastArchiveTable(string $type): ?string
{
$archiveTablePrefix = $type::ARCHIVE_TABLE_PREFIX;

$archiveTables = array_filter(
$this->connection->getSchemaManager()->listTableNames(),
fn($tableName) => str_contains($tableName, $archiveTablePrefix)
);

$now = (new \DateTime)->getTimestamp();
$mostRecentDate = 0;
$lastArchiveTable = null;

foreach ($archiveTables as $archiveTable) {
$date = substr($archiveTable, strpos($archiveTable, \strlen($archiveTablePrefix) -1);
$archiveTableDate = strtotime($date);

if ($archiveTableDate > $mostRecentDate && $archiveTableDate < $now) {
$mostRecentDate = $archiveTableDate;
$lastArchiveTable = $archiveTable;
}
}

return $lastArchiveTable ?? null;
}
}
8 changes: 8 additions & 0 deletions src/main/log/Archive/LogRotatorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Claroline\LogBundle\Archive;

interface LogRotatorInterface
{
public function rotateLogs(\DateTimeInterface $interval, string $type): void;
}
116 changes: 116 additions & 0 deletions src/main/log/Entity/Archive/FunctionalLogArchive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace Claroline\LogBundle\Entity\Archive;

use Claroline\LogBundle\Entity\AbstractLog;
use Claroline\LogBundle\Entity\FunctionalLog;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(null)
*/
class FunctionalLogArchive extends AbstractLog
{
public const ARCHIVE_TABLE_PREFIX = 'claro_log_functional_archive_';

/**
* @var string|null
* @ORM\Column(type="int", nullable=true)
*/
private $userId;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $userUuid;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $userUsername;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $workspaceUuid;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $resourceUuid;

public static function fromFunctionalLog(FunctionalLog $functionalLog)
{
$user = $functionalLog->getUser();
$workspace = $functionalLog->getWorkspace();
$resource = $functionalLog->getResource();

$archive = new self();
$archive->setUserId($user->getId());
$archive->setUserUuid($user->getUuid());
$archive->setUserUsername($user->getUsername());
$archive->setResourceUuid($resource ? $resource->getUuid() : null);
$archive->setWorkspaceUuid($workspace ? $workspace->getUuid() : null);

$archive->setDate($functionalLog->getDate());
$archive->setDetails($functionalLog->getDetails());
$archive->setEvent($functionalLog->getEvent());

return $archive;
}

public function getUserId(): ?int
{
return $this->userId;
}

public function setUserId(?int $userId): void
{
$this->userId = $userId;
}

public function getUserUuid(): ?string
{
return $this->userUuid;
}

public function setUserUuid(?string $userUuid): void
{
$this->userUuid = $userUuid;
}

public function getUserUsername(): ?string
{
return $this->userUsername;
}

public function setUserUsername(?string $userUsername): void
{
$this->userUsername = $userUsername;
}

public function getWorkspaceUuid(): ?string
{
return $this->workspaceUuid;
}

public function setWorkspaceUuid(?string $workspaceUuid): void
{
$this->workspaceUuid = $workspaceUuid;
}

public function getResourceUuid(): ?string
{
return $this->resourceUuid;
}

public function setResourceUuid(?string $resourceUuid): void
{
$this->resourceUuid = $resourceUuid;
}
}
131 changes: 131 additions & 0 deletions src/main/log/Entity/Archive/MessageLogArchive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

namespace Claroline\LogBundle\Entity\Archive;

use Claroline\LogBundle\Entity\AbstractLog;
use Claroline\LogBundle\Entity\MessageLog;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(null)
*/
class MessageLogArchive extends AbstractLog
{
public const ARCHIVE_TABLE_PREFIX = 'claro_log_message_archive_';

/**
* @var int|null
* @ORM\Column(type="integer", nullable=true)
*/
private $senderId;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $senderUuid;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $senderUsername;

/**
* @var int|null
* @ORM\Column(type="integer", nullable=true)
*/
private $receiverId;

/**
* @var string|null
* @ORM\Column(type="string", nullable=true)
*/
private $receiverUuid;

/**
* @var string|null
* @ORM\Column(type="string")
*/
private $receiverUsername;

public static function fromMessageLog(MessageLog $messageLog)
{
$sender = $messageLog->getSender();
$receiver = $messageLog->getReceiver();

$archive = new self();
$archive->setDate($messageLog->getDate());
$archive->setDetails($messageLog->getDetails());
$archive->setEvent($messageLog->getEvent());
$archive->setSenderId($sender->getId());
$archive->setSenderUuid($sender->getUuid());
$archive->setSenderUsername($sender->getUsername());
$archive->setReceiverId($receiver->getId());
$archive->setReceiverUuid($receiver->getUuid());
$archive->setReceiverUsername($receiver->getUsername());

return $archive;
}

public function getSenderId(): ?int
{
return $this->senderId;
}

public function setSenderId(?int $senderId): void
{
$this->senderId = $senderId;
}

public function getSenderUuid(): ?string
{
return $this->senderUuid;
}

public function setSenderUuid(?string $senderUuid): void
{
$this->senderUuid = $senderUuid;
}

public function getSenderUsername(): ?string
{
return $this->senderUsername;
}

public function setSenderUsername(?string $senderUsername): void
{
$this->senderUsername = $senderUsername;
}

public function getReceiverId(): ?int
{
return $this->receiverId;
}

public function setReceiverId(?int $receiverId): void
{
$this->receiverId = $receiverId;
}

public function getReceiverUuid(): ?string
{
return $this->receiverUuid;
}

public function setReceiverUuid(?string $receiverUuid): void
{
$this->receiverUuid = $receiverUuid;
}

public function getReceiverUsername(): ?string
{
return $this->receiverUsername;
}

public function setReceiverUsername(?string $receiverUsername): void
{
$this->receiverUsername = $receiverUsername;
}
}
Loading