mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Enhance behaviour of duplicating storedObject to keep only the last "kept before conversion" version if any
Enhance the duplication service to selectively handle versions tagged with "KEEP_BEFORE_CONVERSION". Modify StoredObject to support retrieval and checking of such versions. Add relevant test cases to validate this behavior.
This commit is contained in:
parent
6c52ff84a8
commit
9a9d14eb5a
@ -18,6 +18,8 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
|||||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Doctrine\Common\Collections\Order;
|
||||||
|
use Doctrine\Common\Collections\ReadableCollection;
|
||||||
use Doctrine\Common\Collections\Selectable;
|
use Doctrine\Common\Collections\Selectable;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
@ -257,11 +259,33 @@ class StoredObject implements Document, TrackCreationInterface
|
|||||||
return $this->template;
|
return $this->template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Selectable<int, StoredObjectVersion>&Collection<int, StoredObjectVersion>
|
||||||
|
*/
|
||||||
public function getVersions(): Collection&Selectable
|
public function getVersions(): Collection&Selectable
|
||||||
{
|
{
|
||||||
return $this->versions;
|
return $this->versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves versions sorted by a given order.
|
||||||
|
*
|
||||||
|
* @param 'ASC'|'DESC' $order the sorting order, default is Order::Ascending
|
||||||
|
*
|
||||||
|
* @return readableCollection&Selectable The ordered collection of versions
|
||||||
|
*/
|
||||||
|
public function getVersionsOrdered(string $order = 'ASC'): ReadableCollection&Selectable
|
||||||
|
{
|
||||||
|
$versions = $this->getVersions()->toArray();
|
||||||
|
|
||||||
|
match ($order) {
|
||||||
|
'ASC' => usort($versions, static fn (StoredObjectVersion $a, StoredObjectVersion $b) => $a->getVersion() <=> $b->getVersion()),
|
||||||
|
'DESC' => usort($versions, static fn (StoredObjectVersion $a, StoredObjectVersion $b) => $b->getVersion() <=> $a->getVersion()),
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ArrayCollection($versions);
|
||||||
|
}
|
||||||
|
|
||||||
public function hasCurrentVersion(): bool
|
public function hasCurrentVersion(): bool
|
||||||
{
|
{
|
||||||
return null !== $this->getCurrentVersion();
|
return null !== $this->getCurrentVersion();
|
||||||
@ -272,6 +296,47 @@ class StoredObject implements Document, TrackCreationInterface
|
|||||||
return null !== $this->template;
|
return null !== $this->template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there is a version kept before conversion.
|
||||||
|
*
|
||||||
|
* @return bool true if a version is kept before conversion, false otherwise
|
||||||
|
*/
|
||||||
|
public function hasKeptBeforeConversionVersion(): bool
|
||||||
|
{
|
||||||
|
foreach ($this->getVersions() as $version) {
|
||||||
|
foreach ($version->getPointInTimes() as $pointInTime) {
|
||||||
|
if (StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION === $pointInTime->getReason()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the last version of the stored object that was kept before conversion.
|
||||||
|
*
|
||||||
|
* This method iterates through the ordered versions and their respective points
|
||||||
|
* in time to find the most recent version that has a point in time with the reason
|
||||||
|
* 'KEEP_BEFORE_CONVERSION'.
|
||||||
|
*
|
||||||
|
* @return StoredObjectVersion|null the version that was kept before conversion,
|
||||||
|
* or null if not found
|
||||||
|
*/
|
||||||
|
public function getLastKeptBeforeConversionVersion(): ?StoredObjectVersion
|
||||||
|
{
|
||||||
|
foreach ($this->getVersionsOrdered('DESC') as $version) {
|
||||||
|
foreach ($version->getPointInTimes() as $pointInTime) {
|
||||||
|
if (StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION === $pointInTime->getReason()) {
|
||||||
|
return $version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public function setTemplate(?DocGeneratorTemplate $template): StoredObject
|
public function setTemplate(?DocGeneratorTemplate $template): StoredObject
|
||||||
{
|
{
|
||||||
$this->template = $template;
|
$this->template = $template;
|
||||||
|
@ -22,9 +22,18 @@ class StoredObjectDuplicate
|
|||||||
{
|
{
|
||||||
public function __construct(private readonly StoredObjectManagerInterface $storedObjectManager, private readonly LoggerInterface $logger) {}
|
public function __construct(private readonly StoredObjectManagerInterface $storedObjectManager, private readonly LoggerInterface $logger) {}
|
||||||
|
|
||||||
public function duplicate(StoredObject|StoredObjectVersion $from): StoredObject
|
public function duplicate(StoredObject|StoredObjectVersion $from, bool $onlyLastKeptBeforeConversionVersion = true): StoredObject
|
||||||
{
|
{
|
||||||
$fromVersion = $from instanceof StoredObjectVersion ? $from : $from->getCurrentVersion();
|
$storedObject = $from instanceof StoredObjectVersion ? $from->getStoredObject() : $from;
|
||||||
|
|
||||||
|
$fromVersion = match ($storedObject->hasKeptBeforeConversionVersion() && $onlyLastKeptBeforeConversionVersion) {
|
||||||
|
true => $from->getLastKeptBeforeConversionVersion(),
|
||||||
|
false => $storedObject->getCurrentVersion(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (null === $fromVersion) {
|
||||||
|
throw new \UnexpectedValueException('could not find a version to restore');
|
||||||
|
}
|
||||||
|
|
||||||
$oldContent = $this->storedObjectManager->read($fromVersion);
|
$oldContent = $this->storedObjectManager->read($fromVersion);
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ declare(strict_types=1);
|
|||||||
namespace Chill\DocStoreBundle\Tests\Entity;
|
namespace Chill\DocStoreBundle\Tests\Entity;
|
||||||
|
|
||||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTime;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTimeReasonEnum;
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,4 +56,27 @@ class StoredObjectTest extends KernelTestCase
|
|||||||
|
|
||||||
self::assertNotSame($firstVersion, $version);
|
self::assertNotSame($firstVersion, $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHasKeptBeforeConversionVersion(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
$version1 = $storedObject->registerVersion();
|
||||||
|
|
||||||
|
self::assertFalse($storedObject->hasKeptBeforeConversionVersion());
|
||||||
|
|
||||||
|
// add a point in time without the correct version
|
||||||
|
new StoredObjectPointInTime($version1, StoredObjectPointInTimeReasonEnum::KEEP_BY_USER);
|
||||||
|
|
||||||
|
self::assertFalse($storedObject->hasKeptBeforeConversionVersion());
|
||||||
|
self::assertNull($storedObject->getLastKeptBeforeConversionVersion());
|
||||||
|
|
||||||
|
new StoredObjectPointInTime($version1, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
|
||||||
|
self::assertTrue($storedObject->hasKeptBeforeConversionVersion());
|
||||||
|
// add a second version
|
||||||
|
$version2 = $storedObject->registerVersion();
|
||||||
|
new StoredObjectPointInTime($version2, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
|
||||||
|
self::assertSame($version2, $storedObject->getLastKeptBeforeConversionVersion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,13 @@ declare(strict_types=1);
|
|||||||
namespace Chill\DocStoreBundle\Tests\Service;
|
namespace Chill\DocStoreBundle\Tests\Service;
|
||||||
|
|
||||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTime;
|
||||||
|
use Chill\DocStoreBundle\Entity\StoredObjectPointInTimeReasonEnum;
|
||||||
use Chill\DocStoreBundle\Service\StoredObjectDuplicate;
|
use Chill\DocStoreBundle\Service\StoredObjectDuplicate;
|
||||||
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
use Psr\Log\NullLogger;
|
use Psr\Log\NullLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,9 +28,13 @@ use Psr\Log\NullLogger;
|
|||||||
*/
|
*/
|
||||||
class StoredObjectDuplicateTest extends TestCase
|
class StoredObjectDuplicateTest extends TestCase
|
||||||
{
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
public function testDuplicateHappyScenario(): void
|
public function testDuplicateHappyScenario(): void
|
||||||
{
|
{
|
||||||
$storedObject = new StoredObject();
|
$storedObject = new StoredObject();
|
||||||
|
// we create multiple version, we want the last to be duplicated
|
||||||
|
$storedObject->registerVersion(type: 'application/test');
|
||||||
$version = $storedObject->registerVersion(type: $type = 'application/test');
|
$version = $storedObject->registerVersion(type: $type = 'application/test');
|
||||||
|
|
||||||
$manager = $this->createMock(StoredObjectManagerInterface::class);
|
$manager = $this->createMock(StoredObjectManagerInterface::class);
|
||||||
@ -45,4 +53,78 @@ class StoredObjectDuplicateTest extends TestCase
|
|||||||
self::assertNotNull($actual->getCurrentVersion()->getCreatedFrom());
|
self::assertNotNull($actual->getCurrentVersion()->getCreatedFrom());
|
||||||
self::assertSame($version, $actual->getCurrentVersion()->getCreatedFrom());
|
self::assertSame($version, $actual->getCurrentVersion()->getCreatedFrom());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDuplicateWithKeptVersion(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
// we create two versions for stored object
|
||||||
|
// the first one is "kept before conversion", and that one should
|
||||||
|
// be duplicated, not the second one
|
||||||
|
$version1 = $storedObject->registerVersion(type: $type = 'application/test');
|
||||||
|
new StoredObjectPointInTime($version1, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
$version2 = $storedObject->registerVersion(type: $type = 'application/test');
|
||||||
|
|
||||||
|
$manager = $this->prophesize(StoredObjectManagerInterface::class);
|
||||||
|
|
||||||
|
// we create both possibilities for the method "read"
|
||||||
|
$manager->read($version1)->willReturn('1234');
|
||||||
|
$manager->read($version2)->willReturn('4567');
|
||||||
|
|
||||||
|
// we create the write method, and check that it is called with the content from version1, not version2
|
||||||
|
$manager->write(Argument::type(StoredObject::class), '1234', 'application/test')
|
||||||
|
->shouldBeCalled()
|
||||||
|
->will(function ($args) {
|
||||||
|
/** @var StoredObject $storedObject */
|
||||||
|
$storedObject = $args[0]; // args are ordered by key, so the first one is the stored object...
|
||||||
|
$type = $args[2]; // and the last one is the string $type
|
||||||
|
|
||||||
|
return $storedObject->registerVersion(type: $type);
|
||||||
|
});
|
||||||
|
|
||||||
|
// we create the service which will duplicate things
|
||||||
|
$storedObjectDuplicate = new StoredObjectDuplicate($manager->reveal(), new NullLogger());
|
||||||
|
|
||||||
|
$actual = $storedObjectDuplicate->duplicate($storedObject);
|
||||||
|
|
||||||
|
self::assertNotNull($actual->getCurrentVersion());
|
||||||
|
self::assertNotNull($actual->getCurrentVersion()->getCreatedFrom());
|
||||||
|
self::assertSame($version1, $actual->getCurrentVersion()->getCreatedFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDuplicateWithKeptVersionButWeWantToDuplicateTheLastOne(): void
|
||||||
|
{
|
||||||
|
$storedObject = new StoredObject();
|
||||||
|
// we create two versions for stored object
|
||||||
|
// the first one is "kept before conversion", and that one should
|
||||||
|
// be duplicated, not the second one
|
||||||
|
$version1 = $storedObject->registerVersion(type: $type = 'application/test');
|
||||||
|
new StoredObjectPointInTime($version1, StoredObjectPointInTimeReasonEnum::KEEP_BEFORE_CONVERSION);
|
||||||
|
$version2 = $storedObject->registerVersion(type: $type = 'application/test');
|
||||||
|
|
||||||
|
$manager = $this->prophesize(StoredObjectManagerInterface::class);
|
||||||
|
|
||||||
|
// we create both possibilities for the method "read"
|
||||||
|
$manager->read($version1)->willReturn('1234');
|
||||||
|
$manager->read($version2)->willReturn('4567');
|
||||||
|
|
||||||
|
// we create the write method, and check that it is called with the content from version1, not version2
|
||||||
|
$manager->write(Argument::type(StoredObject::class), '4567', 'application/test')
|
||||||
|
->shouldBeCalled()
|
||||||
|
->will(function ($args) {
|
||||||
|
/** @var StoredObject $storedObject */
|
||||||
|
$storedObject = $args[0]; // args are ordered by key, so the first one is the stored object...
|
||||||
|
$type = $args[2]; // and the last one is the string $type
|
||||||
|
|
||||||
|
return $storedObject->registerVersion(type: $type);
|
||||||
|
});
|
||||||
|
|
||||||
|
// we create the service which will duplicate things
|
||||||
|
$storedObjectDuplicate = new StoredObjectDuplicate($manager->reveal(), new NullLogger());
|
||||||
|
|
||||||
|
$actual = $storedObjectDuplicate->duplicate($storedObject, false);
|
||||||
|
|
||||||
|
self::assertNotNull($actual->getCurrentVersion());
|
||||||
|
self::assertNotNull($actual->getCurrentVersion()->getCreatedFrom());
|
||||||
|
self::assertSame($version2, $actual->getCurrentVersion()->getCreatedFrom());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user