Use enum for undo mode

This commit is contained in:
Jan Böhmer 2023-06-18 21:26:28 +02:00
parent 218b0adb8f
commit 8a20584e27
14 changed files with 140 additions and 180 deletions

View file

@ -34,6 +34,7 @@ use App\Entity\LogSystem\ElementEditedLogEntry;
use App\Form\Filters\LogFilterType; use App\Form\Filters\LogFilterType;
use App\Repository\DBElementRepository; use App\Repository\DBElementRepository;
use App\Services\LogSystem\EventUndoHelper; use App\Services\LogSystem\EventUndoHelper;
use App\Services\LogSystem\EventUndoMode;
use App\Services\LogSystem\LogEntryExtraFormatter; use App\Services\LogSystem\LogEntryExtraFormatter;
use App\Services\LogSystem\LogLevelHelper; use App\Services\LogSystem\LogLevelHelper;
use App\Services\LogSystem\LogTargetHelper; use App\Services\LogSystem\LogTargetHelper;
@ -128,13 +129,17 @@ class LogController extends AbstractController
#[Route(path: '/undo', name: 'log_undo', methods: ['POST'])] #[Route(path: '/undo', name: 'log_undo', methods: ['POST'])]
public function undoRevertLog(Request $request, EventUndoHelper $eventUndoHelper): RedirectResponse public function undoRevertLog(Request $request, EventUndoHelper $eventUndoHelper): RedirectResponse
{ {
$mode = EventUndoHelper::MODE_UNDO; $mode = EventUndoMode::UNDO;
$id = $request->request->get('undo'); $id = $request->request->getInt('undo');
//If no undo value was set check if a revert was set //If no undo value was set check if a revert was set
if (null === $id) { if (0 === $id) {
$id = $request->get('revert'); $id = $request->request->getInt('revert');
$mode = EventUndoHelper::MODE_REVERT; $mode = EventUndoMode::REVERT;
}
if (0 === $id) {
throw new InvalidArgumentException('No log entry ID was given!');
} }
$log_element = $this->entityManager->find(AbstractLogEntry::class, $id); $log_element = $this->entityManager->find(AbstractLogEntry::class, $id);
@ -147,9 +152,9 @@ class LogController extends AbstractController
$eventUndoHelper->setMode($mode); $eventUndoHelper->setMode($mode);
$eventUndoHelper->setUndoneEvent($log_element); $eventUndoHelper->setUndoneEvent($log_element);
if (EventUndoHelper::MODE_UNDO === $mode) { if (EventUndoMode::UNDO === $mode) {
$this->undoLog($log_element); $this->undoLog($log_element);
} elseif (EventUndoHelper::MODE_REVERT === $mode) { } elseif (EventUndoMode::REVERT === $mode) {
$this->revertLog($log_element); $this->revertLog($log_element);
} }

View file

@ -67,8 +67,6 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
{ {
use ParametersTrait; use ParametersTrait;
final public const ID_ROOT_ELEMENT = 0;
/** /**
* This is a not standard character, so build a const, so a dev can easily use it. * This is a not standard character, so build a const, so a dev can easily use it.
*/ */

View file

@ -42,6 +42,7 @@ declare(strict_types=1);
namespace App\Entity\Contracts; namespace App\Entity\Contracts;
use App\Entity\LogSystem\AbstractLogEntry; use App\Entity\LogSystem\AbstractLogEntry;
use App\Services\LogSystem\EventUndoMode;
interface LogWithEventUndoInterface interface LogWithEventUndoInterface
{ {
@ -60,12 +61,12 @@ interface LogWithEventUndoInterface
* *
* @return $this * @return $this
*/ */
public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): self; public function setUndoneEvent(AbstractLogEntry $event, EventUndoMode $mode = EventUndoMode::UNDO): self;
/** /**
* Returns the mode how the event was undone: * Returns the mode how the event was undone:
* "undo" = Only a single event was applied to element * "undo" = Only a single event was applied to element
* "revert" = Element was reverted to the state it was to the timestamp of the log. * "revert" = Element was reverted to the state it was to the timestamp of the log.
*/ */
public function getUndoMode(): string; public function getUndoMode(): EventUndoMode;
} }

View file

@ -87,10 +87,10 @@ use InvalidArgumentException;
#[ORM\Entity] #[ORM\Entity]
class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventUndoInterface class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventUndoInterface
{ {
use LogWithEventUndoTrait;
protected string $typeString = 'collection_element_deleted'; protected string $typeString = 'collection_element_deleted';
public function __construct(AbstractDBElement $changed_element, string $collection_name, AbstractDBElement $deletedElement) public function __construct(AbstractDBElement $changed_element, string $collection_name, AbstractDBElement $deletedElement)
{ {
parent::__construct(); parent::__construct();
@ -218,39 +218,4 @@ class CollectionElementDeleted extends AbstractLogEntry implements LogWithEventU
{ {
return $this->extra['i']; return $this->extra['i'];
} }
public function isUndoEvent(): bool
{
return isset($this->extra['u']);
}
public function getUndoEventID(): ?int
{
return $this->extra['u'] ?? null;
}
public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface
{
$this->extra['u'] = $event->getID();
if ('undo' === $mode) {
$this->extra['um'] = 1;
} elseif ('revert' === $mode) {
$this->extra['um'] = 2;
} else {
throw new InvalidArgumentException('Passed invalid $mode!');
}
return $this;
}
public function getUndoMode(): string
{
$mode_int = $this->extra['um'] ?? 1;
if (1 === $mode_int) {
return 'undo';
}
return 'revert';
}
} }

View file

@ -27,12 +27,15 @@ use App\Entity\Contracts\LogWithCommentInterface;
use App\Entity\Contracts\LogWithEventUndoInterface; use App\Entity\Contracts\LogWithEventUndoInterface;
use App\Entity\UserSystem\Group; use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Services\LogSystem\EventUndoMode;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException; use InvalidArgumentException;
#[ORM\Entity] #[ORM\Entity]
class ElementCreatedLogEntry extends AbstractLogEntry implements LogWithCommentInterface, LogWithEventUndoInterface class ElementCreatedLogEntry extends AbstractLogEntry implements LogWithCommentInterface, LogWithEventUndoInterface
{ {
use LogWithEventUndoTrait;
protected string $typeString = 'element_created'; protected string $typeString = 'element_created';
public function __construct(AbstractDBElement $new_element) public function __construct(AbstractDBElement $new_element)
@ -79,39 +82,4 @@ class ElementCreatedLogEntry extends AbstractLogEntry implements LogWithCommentI
return $this; return $this;
} }
public function isUndoEvent(): bool
{
return isset($this->extra['u']);
}
public function getUndoEventID(): ?int
{
return $this->extra['u'] ?? null;
}
public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface
{
$this->extra['u'] = $event->getID();
if ('undo' === $mode) {
$this->extra['um'] = 1;
} elseif ('revert' === $mode) {
$this->extra['um'] = 2;
} else {
throw new InvalidArgumentException('Passed invalid $mode!');
}
return $this;
}
public function getUndoMode(): string
{
$mode_int = $this->extra['um'] ?? 1;
if (1 === $mode_int) {
return 'undo';
}
return 'revert';
}
} }

View file

@ -29,6 +29,7 @@ use App\Entity\Contracts\NamedElementInterface;
use App\Entity\Contracts\TimeTravelInterface; use App\Entity\Contracts\TimeTravelInterface;
use App\Entity\UserSystem\Group; use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\User; use App\Entity\UserSystem\User;
use App\Services\LogSystem\EventUndoMode;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use InvalidArgumentException; use InvalidArgumentException;
@ -37,6 +38,8 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter
{ {
protected string $typeString = 'element_deleted'; protected string $typeString = 'element_deleted';
use LogWithEventUndoTrait;
public function __construct(AbstractDBElement $deleted_element) public function __construct(AbstractDBElement $deleted_element)
{ {
parent::__construct(); parent::__construct();
@ -112,39 +115,4 @@ class ElementDeletedLogEntry extends AbstractLogEntry implements TimeTravelInter
return $this; return $this;
} }
public function isUndoEvent(): bool
{
return isset($this->extra['u']);
}
public function getUndoEventID(): ?int
{
return $this->extra['u'] ?? null;
}
public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface
{
$this->extra['u'] = $event->getID();
if ('undo' === $mode) {
$this->extra['um'] = 1;
} elseif ('revert' === $mode) {
$this->extra['um'] = 2;
} else {
throw new InvalidArgumentException('Passed invalid $mode!');
}
return $this;
}
public function getUndoMode(): string
{
$mode_int = $this->extra['um'] ?? 1;
if (1 === $mode_int) {
return 'undo';
}
return 'revert';
}
} }

View file

@ -33,6 +33,8 @@ use InvalidArgumentException;
#[ORM\Entity] #[ORM\Entity]
class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterface, LogWithCommentInterface, LogWithEventUndoInterface, LogWithNewDataInterface class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterface, LogWithCommentInterface, LogWithEventUndoInterface, LogWithNewDataInterface
{ {
use LogWithEventUndoTrait;
protected string $typeString = 'element_edited'; protected string $typeString = 'element_edited';
public function __construct(AbstractDBElement $changed_element) public function __construct(AbstractDBElement $changed_element)
@ -139,39 +141,4 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf
return $this; return $this;
} }
public function isUndoEvent(): bool
{
return isset($this->extra['u']);
}
public function getUndoEventID(): ?int
{
return $this->extra['u'] ?? null;
}
public function setUndoneEvent(AbstractLogEntry $event, string $mode = 'undo'): LogWithEventUndoInterface
{
$this->extra['u'] = $event->getID();
if ('undo' === $mode) {
$this->extra['um'] = 1;
} elseif ('revert' === $mode) {
$this->extra['um'] = 2;
} else {
throw new InvalidArgumentException('Passed invalid $mode!');
}
return $this;
}
public function getUndoMode(): string
{
$mode_int = $this->extra['um'] ?? 1;
if (1 === $mode_int) {
return 'undo';
}
return 'revert';
}
} }

View file

@ -0,0 +1,51 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 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/>.
*/
namespace App\Entity\LogSystem;
use App\Entity\Contracts\LogWithEventUndoInterface;
use App\Services\LogSystem\EventUndoMode;
trait LogWithEventUndoTrait
{
public function isUndoEvent(): bool
{
return isset($this->extra['u']);
}
public function getUndoEventID(): ?int
{
return $this->extra['u'] ?? null;
}
public function setUndoneEvent(AbstractLogEntry $event, EventUndoMode $mode = EventUndoMode::UNDO): LogWithEventUndoInterface
{
$this->extra['u'] = $event->getID();
$this->extra['um'] = $mode->toExtraInt();
return $this;
}
public function getUndoMode(): EventUndoMode
{
$mode_int = $this->extra['um'] ?? 1;
return EventUndoMode::fromExtraInt($mode_int);
}
}

View file

@ -28,10 +28,6 @@ use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity] #[ORM\Entity]
class PartStockChangedLogEntry extends AbstractLogEntry class PartStockChangedLogEntry extends AbstractLogEntry
{ {
final public const TYPE_ADD = "add";
final public const TYPE_WITHDRAW = "withdraw";
final public const TYPE_MOVE = "move";
protected string $typeString = 'part_stock_changed'; protected string $typeString = 'part_stock_changed';
protected const COMMENT_MAX_LENGTH = 300; protected const COMMENT_MAX_LENGTH = 300;

View file

@ -46,27 +46,19 @@ use InvalidArgumentException;
class EventUndoHelper class EventUndoHelper
{ {
final public const MODE_UNDO = 'undo';
final public const MODE_REVERT = 'revert';
protected const ALLOWED_MODES = [self::MODE_REVERT, self::MODE_UNDO];
protected ?AbstractLogEntry $undone_event = null; protected ?AbstractLogEntry $undone_event = null;
protected string $mode = self::MODE_UNDO; protected EventUndoMode $mode = EventUndoMode::UNDO;
public function __construct() public function __construct()
{ {
} }
public function setMode(string $mode): void public function setMode(EventUndoMode $mode): void
{ {
if (!in_array($mode, self::ALLOWED_MODES, true)) {
throw new InvalidArgumentException('Invalid mode passed!');
}
$this->mode = $mode; $this->mode = $mode;
} }
public function getMode(): string public function getMode(): EventUndoMode
{ {
return $this->mode; return $this->mode;
} }

View file

@ -0,0 +1,46 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 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/>.
*/
namespace App\Services\LogSystem;
use InvalidArgumentException;
enum EventUndoMode: string
{
case UNDO = 'undo';
case REVERT = 'revert';
public function toExtraInt(): int
{
return match ($this) {
self::UNDO => 1,
self::REVERT => 2,
};
}
public static function fromExtraInt(int $int): self
{
return match ($int) {
1 => self::UNDO,
2 => self::REVERT,
default => throw new InvalidArgumentException('Invalid int ' . (string) $int . ' for EventUndoMode'),
};
}
}

View file

@ -127,9 +127,9 @@ class LogEntryExtraFormatter
} }
if (($context instanceof LogWithEventUndoInterface) && $context->isUndoEvent()) { if (($context instanceof LogWithEventUndoInterface) && $context->isUndoEvent()) {
if ('undo' === $context->getUndoMode()) { if (EventUndoMode::UNDO === $context->getUndoMode()) {
$array['log.undo_mode.undo'] = '#' . $context->getUndoEventID(); $array['log.undo_mode.undo'] = '#' . $context->getUndoEventID();
} elseif ('revert' === $context->getUndoMode()) { } elseif (EventUndoMode::REVERT === $context->getUndoMode()) {
$array['log.undo_mode.revert'] = '#' . $context->getUndoEventID(); $array['log.undo_mode.revert'] = '#' . $context->getUndoEventID();
} }
} }

View file

@ -32,16 +32,19 @@
<i class="fas fa-fw fa-backward" title="{% trans %}log.undo.revert{% endtrans %}"></i> {{ 'log.undo.revert.short' | trans }} <i class="fas fa-fw fa-backward" title="{% trans %}log.undo.revert{% endtrans %}"></i> {{ 'log.undo.revert.short' | trans }}
</button> </button>
{% set url = timetravel_url(target_element, entry.timestamp) %}
{# View button #} {# View button #}
{% if target_element and ((attribute(entry, 'oldDataInformation') is defined and entry.oldDataInformation) {% if target_element and ((attribute(entry, 'oldDataInformation') is defined and entry.oldDataInformation)
or entry is instanceof('App\\Entity\\LogSystem\\CollectionElementDeleted')) or entry is instanceof('App\\Entity\\LogSystem\\CollectionElementDeleted'))
and url is not null %} %}
{% set url = timetravel_url(target_element, entry.timestamp) %}
{% if url %}
<a class="btn btn-outline-secondary" href="{{ url }}"><i class="fas fa-fw fa-eye"></i> <a class="btn btn-outline-secondary" href="{{ url }}"><i class="fas fa-fw fa-eye"></i>
{% trans %}log.view_version{% endtrans %} {% trans %}log.view_version{% endtrans %}
</a> </a>
{% endif %} {% endif %}
{% endif %}
</div> </div>
</form> </form>
{% endmacro %} {% endmacro %}

View file

@ -26,11 +26,11 @@
<td> <td>
{{ ('log.type.' ~ log_entry.type) | trans }} {{ ('log.type.' ~ log_entry.type) | trans }}
{% if log_entry.type == 'part_stock_changed' %} {% if log_entry.type == 'part_stock_changed' %}
({{ ('log.part_stock_changed.' ~ log_entry.instockChangeType)|trans }}) ({{ ('log.part_stock_changed.' ~ log_entry.instockChangeType.value)|trans }})
{% endif %} {% endif %}
{% if log_entry is instanceof('App\\Entity\\Contracts\\LogWithEventUndoInterface') and log_entry.undoEvent %} {% if log_entry is instanceof('App\\Entity\\Contracts\\LogWithEventUndoInterface') and log_entry.undoEvent %}
<b>({{ ('log.undo_mode.' ~ log_entry.undoMode)|trans }}: <a href="{{ path('log_details', {"id": log_entry.UndoEventID}) }}">#{{ log_entry.UndoEventID }}</a>)</b> <b>({{ ('log.undo_mode.' ~ log_entry.undoMode.value)|trans }}: <a href="{{ path('log_details', {"id": log_entry.UndoEventID}) }}">#{{ log_entry.UndoEventID }}</a>)</b>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>