mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-01 20:43:49 +00:00
Add functionality to delete old versions of documents
This commit introduces a feature that automatically deletes old versions of StoredObjects in the Chill application. A cron job, "RemoveOldVersionCronJob", has been implemented to delete versions older than 90 days. A message handler, "RemoveOldVersionMessageHandler", has been added to handle deletion requests. Furthermore, unit tests for the new functionality have been provided.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\DocStoreBundle\Tests\Repository;
|
||||
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectVersionRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class StoredObjectVersionRepositoryTest extends KernelTestCase
|
||||
{
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$this->entityManager = self::getContainer()->get(EntityManagerInterface::class);
|
||||
}
|
||||
|
||||
public function testFindIdsByVersionsOlderThanDateAndNotLastVersion(): void
|
||||
{
|
||||
$repository = new StoredObjectVersionRepository($this->entityManager);
|
||||
|
||||
// get old version, to get a chance to get one
|
||||
$actual = $repository->findIdsByVersionsOlderThanDateAndNotLastVersion(new \DateTimeImmutable('1970-01-01'));
|
||||
|
||||
self::assertIsIterable($actual);
|
||||
self::assertContainsOnly('int', $actual);
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Tests\Service\StoredObjectCleaner;
|
||||
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectVersionRepository;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectCleaner\RemoveOldVersionCronJob;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectCleaner\RemoveOldVersionMessage;
|
||||
use Chill\MainBundle\Entity\CronJobExecution;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Clock\MockClock;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class RemoveOldVersionCronJobTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider buildTestCanRunData
|
||||
*/
|
||||
public function testCanRun(?CronJobExecution $cronJobExecution, bool $expected): void
|
||||
{
|
||||
$repository = $this->createMock(StoredObjectVersionRepository::class);
|
||||
$clock = new MockClock(new \DateTimeImmutable('2024-01-01 00:00:00', new \DateTimeZone('+00:00')));
|
||||
|
||||
$cronJob = new RemoveOldVersionCronJob($clock, $this->buildMessageBus(), $repository);
|
||||
|
||||
self::assertEquals($expected, $cronJob->canRun($cronJobExecution));
|
||||
}
|
||||
|
||||
public function testRun(): void
|
||||
{
|
||||
// we create a clock in the future. This led us a chance to having stored object to delete
|
||||
$clock = new MockClock(new \DateTimeImmutable('2024-01-01 00:00:00', new \DateTimeZone('+00:00')));
|
||||
$repository = $this->createMock(StoredObjectVersionRepository::class);
|
||||
$repository->expects($this->once())
|
||||
->method('findIdsByVersionsOlderThanDateAndNotLastVersion')
|
||||
->with(new \DateTime('2023-10-03 00:00:00', new \DateTimeZone('+00:00')))
|
||||
->willReturnCallback(function ($arg) {
|
||||
yield 1;
|
||||
yield 3;
|
||||
yield 2;
|
||||
})
|
||||
;
|
||||
|
||||
$cronJob = new RemoveOldVersionCronJob($clock, $this->buildMessageBus(true), $repository);
|
||||
|
||||
$results = $cronJob->run([]);
|
||||
|
||||
self::assertArrayHasKey('last-deleted-stored-object-version-id', $results);
|
||||
self::assertIsInt($results['last-deleted-stored-object-version-id']);
|
||||
}
|
||||
|
||||
public static function buildTestCanRunData(): iterable
|
||||
{
|
||||
yield [
|
||||
(new CronJobExecution('last-deleted-stored-object-version-id'))->setLastEnd(new \DateTimeImmutable('2023-12-31 00:00:00', new \DateTimeZone('+00:00'))),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
(new CronJobExecution('last-deleted-stored-object-version-id'))->setLastEnd(new \DateTimeImmutable('2023-12-30 23:59:59', new \DateTimeZone('+00:00'))),
|
||||
true,
|
||||
];
|
||||
|
||||
yield [
|
||||
(new CronJobExecution('last-deleted-stored-object-version-id'))->setLastEnd(new \DateTimeImmutable('2023-12-31 00:00:01', new \DateTimeZone('+00:00'))),
|
||||
false,
|
||||
];
|
||||
|
||||
yield [
|
||||
null,
|
||||
true,
|
||||
];
|
||||
}
|
||||
|
||||
private function buildMessageBus(bool $expectDistpatchAtLeastOnce = false): MessageBusInterface
|
||||
{
|
||||
$messageBus = $this->createMock(MessageBusInterface::class);
|
||||
|
||||
$methodDispatch = match ($expectDistpatchAtLeastOnce) {
|
||||
true => $messageBus->expects($this->atLeastOnce())->method('dispatch')->with($this->isInstanceOf(RemoveOldVersionMessage::class)),
|
||||
false => $messageBus->method('dispatch'),
|
||||
};
|
||||
|
||||
$methodDispatch->willReturnCallback(function (RemoveOldVersionMessage $message) {
|
||||
return new Envelope($message);
|
||||
});
|
||||
|
||||
return $messageBus;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Tests\Service\StoredObjectCleaner;
|
||||
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\DocStoreBundle\Repository\StoredObjectVersionRepository;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectCleaner\RemoveOldVersionMessage;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectCleaner\RemoveOldVersionMessageHandler;
|
||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class RemoveOldVersionMessageHandlerTest extends TestCase
|
||||
{
|
||||
public function testInvoke(): void
|
||||
{
|
||||
$object = new StoredObject();
|
||||
$version = $object->registerVersion();
|
||||
$storedObjectVersionRepository = $this->createMock(StoredObjectVersionRepository::class);
|
||||
$storedObjectVersionRepository->expects($this->once())->method('find')
|
||||
->with($this->identicalTo(1))
|
||||
->willReturn($version);
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects($this->once())->method('remove')->with($this->identicalTo($version));
|
||||
$entityManager->expects($this->once())->method('flush');
|
||||
$entityManager->expects($this->once())->method('clear');
|
||||
|
||||
$storedObjectManager = $this->createMock(StoredObjectManagerInterface::class);
|
||||
$storedObjectManager->expects($this->once())->method('delete')->with($this->identicalTo($version));
|
||||
|
||||
$handler = new RemoveOldVersionMessageHandler($storedObjectVersionRepository, new NullLogger(), $entityManager, $storedObjectManager);
|
||||
|
||||
$handler(new RemoveOldVersionMessage(1));
|
||||
}
|
||||
}
|
@@ -198,6 +198,37 @@ final class StoredObjectManagerTest extends TestCase
|
||||
self::assertSame($storedObject->getCurrentVersion(), $newVersion);
|
||||
}
|
||||
|
||||
public function testDelete(): void
|
||||
{
|
||||
$storedObject = new StoredObject();
|
||||
$version = $storedObject->registerVersion(filename: 'object_name');
|
||||
|
||||
$httpClient = new MockHttpClient(function ($method, $url, $options) {
|
||||
self::assertEquals('DELETE', $method);
|
||||
self::assertEquals('https://example.com/object_name', $url);
|
||||
|
||||
return new MockResponse('', [
|
||||
'http_code' => 204,
|
||||
]);
|
||||
});
|
||||
|
||||
$tempUrlGenerator = $this->createMock(TempUrlGeneratorInterface::class);
|
||||
$tempUrlGenerator
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->identicalTo('DELETE'), $this->identicalTo('object_name'))
|
||||
->willReturnCallback(function (string $method, string $objectName) {
|
||||
return new SignedUrl(
|
||||
$method,
|
||||
'https://example.com/'.$objectName,
|
||||
new \DateTimeImmutable('1 hours')
|
||||
);
|
||||
});
|
||||
|
||||
$storedObjectManager = new StoredObjectManager($httpClient, $tempUrlGenerator);
|
||||
$storedObjectManager->delete($version);
|
||||
}
|
||||
|
||||
public function testWriteWithDeleteAt()
|
||||
{
|
||||
$storedObject = new StoredObject();
|
||||
|
Reference in New Issue
Block a user