Skip to content

Commit

Permalink
Merge branch 'timetravel-tests'
Browse files Browse the repository at this point in the history
  • Loading branch information
jbtronics committed Jun 23, 2024
2 parents 8fdf372 + 528d0c7 commit a54ce93
Show file tree
Hide file tree
Showing 7 changed files with 373 additions and 9 deletions.
7 changes: 7 additions & 0 deletions src/DataFixtures/DataStructureFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,37 @@ public function createNodesForClass(string $class, ObjectManager $manager): void
/** @var AbstractStructuralDBElement $node1 */
$node1 = new $class();
$node1->setName('Node 1');
$this->addReference($class . '_1', $node1);

/** @var AbstractStructuralDBElement $node2 */
$node2 = new $class();
$node2->setName('Node 2');
$this->addReference($class . '_2', $node2);

/** @var AbstractStructuralDBElement $node3 */
$node3 = new $class();
$node3->setName('Node 3');
$this->addReference($class . '_3', $node3);

$node1_1 = new $class();
$node1_1->setName('Node 1.1');
$node1_1->setParent($node1);
$this->addReference($class . '_4', $node1_1);

$node1_2 = new $class();
$node1_2->setName('Node 1.2');
$node1_2->setParent($node1);
$this->addReference($class . '_5', $node1_2);

$node2_1 = new $class();
$node2_1->setName('Node 2.1');
$node2_1->setParent($node2);
$this->addReference($class . '_6', $node2_1);

$node1_1_1 = new $class();
$node1_1_1->setName('Node 1.1.1');
$node1_1_1->setParent($node1_1);
$this->addReference($class . '_7', $node1_1_1);

$manager->persist($node1);
$manager->persist($node2);
Expand Down
102 changes: 102 additions & 0 deletions src/DataFixtures/LogEntryFixtures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2024 Jan Böhmer (https://github.com/jbtronics)
*
* 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/>.
*/

declare(strict_types=1);


namespace App\DataFixtures;

use App\Entity\LogSystem\ElementCreatedLogEntry;
use App\Entity\LogSystem\ElementDeletedLogEntry;
use App\Entity\LogSystem\ElementEditedLogEntry;
use App\Entity\Parts\Category;
use App\Entity\UserSystem\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;

class LogEntryFixtures extends Fixture implements DependentFixtureInterface
{

public function load(ObjectManager $manager)
{
$this->createCategoryEntries($manager);
$this->createDeletedCategory($manager);
}

public function createCategoryEntries(ObjectManager $manager): void
{
$category = $this->getReference(Category::class . '_1', Category::class);

$logEntry = new ElementCreatedLogEntry($category);
$logEntry->setUser($this->getReference(UserFixtures::ADMIN, User::class));
$logEntry->setComment('Test');
$manager->persist($logEntry);

$logEntry = new ElementEditedLogEntry($category);
$logEntry->setUser($this->getReference(UserFixtures::ADMIN, User::class));
$logEntry->setComment('Test');

$logEntry->setOldData(['name' => 'Test']);
$logEntry->setNewData(['name' => 'Node 1.1']);

$manager->persist($logEntry);
$manager->flush();
}

public function createDeletedCategory(ObjectManager $manager): void
{
//We create a fictive category to test the deletion
$category = new Category();
$category->setName('Node 100');

//Assume a category with id 100 was deleted
$reflClass = new \ReflectionClass($category);
$reflClass->getProperty('id')->setValue($category, 100);

//The whole lifecycle from creation to deletion
$logEntry = new ElementCreatedLogEntry($category);
$logEntry->setUser($this->getReference(UserFixtures::ADMIN, User::class));
$logEntry->setComment('Creation');
$manager->persist($logEntry);

$logEntry = new ElementEditedLogEntry($category);
$logEntry->setUser($this->getReference(UserFixtures::ADMIN, User::class));
$logEntry->setComment('Edit');
$logEntry->setOldData(['name' => 'Test']);
$logEntry->setNewData(['name' => 'Node 100']);
$manager->persist($logEntry);

$logEntry = new ElementDeletedLogEntry($category);
$logEntry->setUser($this->getReference(UserFixtures::ADMIN, User::class));
$logEntry->setOldData(['name' => 'Node 100', 'id' => 100, 'comment' => 'Test comment']);
$manager->persist($logEntry);

$manager->flush();
}

public function getDependencies(): array
{
return [
UserFixtures::class,
DataStructureFixtures::class
];
}
}
5 changes: 5 additions & 0 deletions src/DataFixtures/PartFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public function load(ObjectManager $manager): void
$part = new Part();
$part->setName('Part 1');
$part->setCategory($manager->find(Category::class, 1));
$this->addReference(Part::class . '_1', $part);
$manager->persist($part);

/** More complex part */
Expand All @@ -86,6 +87,7 @@ public function load(ObjectManager $manager): void
$part->setIpn('IPN123');
$part->setNeedsReview(true);
$part->setManufacturingStatus(ManufacturingStatus::ACTIVE);
$this->addReference(Part::class . '_2', $part);
$manager->persist($part);

/** Part with orderdetails, storelocations and Attachments */
Expand All @@ -98,6 +100,7 @@ public function load(ObjectManager $manager): void
$partLot1->setStorageLocation($manager->find(StorageLocation::class, 1));
$part->addPartLot($partLot1);


$partLot2 = new PartLot();
$partLot2->setExpirationDate(new \DateTimeImmutable());
$partLot2->setComment('Test');
Expand Down Expand Up @@ -133,6 +136,8 @@ public function load(ObjectManager $manager): void
$attachment->setAttachmentType($manager->find(AttachmentType::class, 1));
$part->addAttachment($attachment);

$this->addReference(Part::class . '_3', $part);

$manager->persist($part);
$manager->flush();
}
Expand Down
4 changes: 1 addition & 3 deletions src/Repository/LogEntryRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ public function getTimetravelDataForElement(AbstractDBElement $element, \DateTim
{
$qb = $this->createQueryBuilder('log');
$qb->select('log')
//->where('log INSTANCE OF App\Entity\LogSystem\ElementEditedLogEntry')
->where('log INSTANCE OF '.ElementEditedLogEntry::class)
->orWhere('log INSTANCE OF '.CollectionElementDeleted::class)
->andWhere('log.target_type = :target_type')
Expand Down Expand Up @@ -143,8 +142,7 @@ public function getElementExistedAtTimestamp(AbstractDBElement $element, \DateTi
->andWhere('log.target_type = :target_type')
->andWhere('log.target_id = :target_id')
->andWhere('log.timestamp >= :until')
->orderBy('log.timestamp', 'DESC')
->groupBy('log.id');
;

$qb->setParameter('target_type', LogTargetType::fromElementClass($element));
$qb->setParameter('target_id', $element->getID());
Expand Down
27 changes: 21 additions & 6 deletions src/Services/LogSystem/TimeTravel.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
use Doctrine\ORM\Mapping\MappingException;
use Exception;
use InvalidArgumentException;
use PHPUnit\Util\Type;
use ReflectionClass;
use Symfony\Component\PropertyAccess\PropertyAccessor;

class TimeTravel
{
Expand All @@ -56,8 +56,11 @@ public function __construct(protected EntityManagerInterface $em)
/**
* Undeletes the element with the given ID.
*
* @template T of AbstractDBElement
* @param string $class The class name of the element that should be undeleted
* @phpstan-param class-string<T> $class
* @param int $id the ID of the element that should be undeleted
* @phpstan-return T
*/
public function undeleteEntity(string $class, int $id): AbstractDBElement
{
Expand Down Expand Up @@ -215,14 +218,14 @@ public function applyEntry(AbstractDBElement $element, TimeTravelInterface $logE
foreach ($old_data as $field => $data) {
if ($metadata->hasField($field)) {
//We need to convert the string to a BigDecimal first
if (!$data instanceof BigDecimal && ('big_decimal' === $metadata->getFieldMapping($field)['type'])) {
if (!$data instanceof BigDecimal && ('big_decimal' === $metadata->getFieldMapping($field)->type)) {
$data = BigDecimal::of($data);
}

if (!$data instanceof \DateTimeInterface
&& (in_array($metadata->getFieldMapping($field)['type'],
&& (in_array($metadata->getFieldMapping($field)->type,
[Types::DATETIME_IMMUTABLE, Types::DATETIME_IMMUTABLE, Types::DATE_MUTABLE, Types::DATETIME_IMMUTABLE], true))) {
$data = $this->dateTimeDecode($data, $metadata->getFieldMapping($field)['type']);
$data = $this->dateTimeDecode($data, $metadata->getFieldMapping($field)->type);
}

$this->setField($element, $field, $data);
Expand Down Expand Up @@ -254,8 +257,20 @@ protected function getField(AbstractDBElement $element, string $field): mixed
*/
protected function setField(AbstractDBElement $element, string $field, mixed $new_value): void
{
$reflection = new ReflectionClass($element::class);
$property = $reflection->getProperty($field);
//If the field name contains a dot, it is a embeddedable object and we need to split the field name
if (str_contains($field, '.')) {
[$embedded, $embedded_field] = explode('.', $field);

$elementClass = new ReflectionClass($element::class);
$property = $elementClass->getProperty($embedded);
$embeddedClass = $property->getValue($element);

$embeddedReflection = new ReflectionClass($embeddedClass::class);
$property = $embeddedReflection->getProperty($embedded_field);
} else {
$reflection = new ReflectionClass($element::class);
$property = $reflection->getProperty($field);
}

//Check if the property is an BackedEnum, then convert the int or float value to an enum instance
if ((is_string($new_value) || is_int($new_value))
Expand Down
Loading

0 comments on commit a54ce93

Please sign in to comment.