Skip to content

Commit 8a72f3b

Browse files
authored
Log entry display (#1608)
* Introduce AuditLog display entries * Add fixed width to the audit log columns for date and type.
1 parent 2a090b3 commit 8a72f3b

18 files changed

+758
-15
lines changed

css/app.scss

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,3 +1864,23 @@ body {
18641864
background-color: #ed9e2e;
18651865
}
18661866
}
1867+
1868+
.audit-log-table {
1869+
table-layout: fixed;
1870+
1871+
.audit-log-datetime {
1872+
width: 200px;
1873+
1874+
@media (max-width: 767px) {
1875+
width: 130px;
1876+
}
1877+
}
1878+
1879+
.audit-log-type {
1880+
width: 180px;
1881+
1882+
@media (max-width: 767px) {
1883+
width: 120px;
1884+
}
1885+
}
1886+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
abstract readonly class AbstractAuditLogDisplay implements AuditLogDisplayInterface
18+
{
19+
public function __construct(
20+
public \DateTimeImmutable $datetime,
21+
public ActorDisplay $actor,
22+
) {
23+
}
24+
25+
abstract public function getType(): AuditRecordType;
26+
27+
public function getDateTime(): \DateTimeImmutable
28+
{
29+
return $this->datetime;
30+
}
31+
32+
public function getActor(): ActorDisplay
33+
{
34+
return $this->actor;
35+
}
36+
37+
public function getTypeTranslationKey(): string
38+
{
39+
return 'audit_log.type.' . $this->getType()->value;
40+
}
41+
42+
}

src/Audit/Display/ActorDisplay.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
readonly class ActorDisplay
16+
{
17+
public function __construct(
18+
public ?int $id,
19+
public string $username,
20+
) {
21+
}
22+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
use App\Entity\AuditRecord;
17+
18+
class AuditLogDisplayFactory
19+
{
20+
/**
21+
* @param iterable<AuditRecord> $auditRecords
22+
* @return array<AuditLogDisplayInterface>
23+
*/
24+
public function build(iterable $auditRecords): array
25+
{
26+
$displays = [];
27+
foreach ($auditRecords as $record) {
28+
$displays[] = $this->buildSingle($record);
29+
}
30+
31+
return $displays;
32+
}
33+
34+
public function buildSingle(AuditRecord $record): AuditLogDisplayInterface
35+
{
36+
return match ($record->type) {
37+
AuditRecordType::PackageCreated => new PackageCreatedDisplay(
38+
$record->datetime,
39+
$record->attributes['name'],
40+
$record->attributes['repository'],
41+
$this->buildActor($record->attributes['actor']),
42+
),
43+
AuditRecordType::PackageDeleted => new PackageDeletedDisplay(
44+
$record->datetime,
45+
$record->attributes['name'],
46+
$record->attributes['repository'],
47+
$this->buildActor($record->attributes['actor']),
48+
),
49+
AuditRecordType::CanonicalUrlChanged => new CanonicalUrlChangedDisplay(
50+
$record->datetime,
51+
$record->attributes['name'],
52+
$record->attributes['repository_from'],
53+
$record->attributes['repository_to'],
54+
$this->buildActor($record->attributes['actor']),
55+
),
56+
AuditRecordType::VersionDeleted => new VersionDeletedDisplay(
57+
$record->datetime,
58+
$record->attributes['name'],
59+
$record->attributes['version'],
60+
$this->buildActor($record->attributes['actor']),
61+
),
62+
AuditRecordType::VersionReferenceChanged => new VersionReferenceChangedDisplay(
63+
$record->datetime,
64+
$record->attributes['name'],
65+
$record->attributes['version'],
66+
$record->attributes['source_from'] ?? null,
67+
$record->attributes['source_to'] ?? null,
68+
$record->attributes['dist_from'] ?? null,
69+
$record->attributes['dist_to'] ?? null,
70+
$this->buildActor($record->attributes['actor'] ?? null),
71+
),
72+
default => throw new \LogicException(sprintf('Unsupported audit record type: %s', $record->type->value)),
73+
};
74+
}
75+
76+
/**
77+
* @param array{id: int, username: string}|string|null $actor
78+
*/
79+
private function buildActor(array|string|null $actor): ActorDisplay
80+
{
81+
if ($actor === null) {
82+
return new ActorDisplay(null, 'unknown');
83+
}
84+
85+
if (is_string($actor)) {
86+
return new ActorDisplay(null, $actor);
87+
}
88+
89+
return new ActorDisplay($actor['id'], $actor['username']);
90+
}
91+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
interface AuditLogDisplayInterface
18+
{
19+
public function getType(): AuditRecordType;
20+
21+
public function getDateTime(): \DateTimeImmutable;
22+
23+
public function getActor(): ActorDisplay;
24+
25+
public function getTypeTranslationKey(): string;
26+
27+
public function getTemplateName(): string;
28+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
readonly class CanonicalUrlChangedDisplay extends AbstractAuditLogDisplay
18+
{
19+
public function __construct(
20+
\DateTimeImmutable $datetime,
21+
public string $packageName,
22+
public string $repositoryFrom,
23+
public string $repositoryTo,
24+
ActorDisplay $actor,
25+
) {
26+
parent::__construct($datetime, $actor);
27+
}
28+
29+
public function getType(): AuditRecordType
30+
{
31+
return AuditRecordType::CanonicalUrlChanged;
32+
}
33+
34+
public function getTemplateName(): string
35+
{
36+
return 'audit_log/display/canonical_url_changed.html.twig';
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
readonly class PackageCreatedDisplay extends AbstractAuditLogDisplay
18+
{
19+
public function __construct(
20+
\DateTimeImmutable $datetime,
21+
public string $packageName,
22+
public string $repository,
23+
ActorDisplay $actor,
24+
) {
25+
parent::__construct($datetime, $actor);
26+
}
27+
28+
public function getType(): AuditRecordType
29+
{
30+
return AuditRecordType::PackageCreated;
31+
}
32+
33+
public function getTemplateName(): string
34+
{
35+
return 'audit_log/display/package_created.html.twig';
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
readonly class PackageDeletedDisplay extends AbstractAuditLogDisplay
18+
{
19+
public function __construct(
20+
\DateTimeImmutable $datetime,
21+
public string $packageName,
22+
public string $repository,
23+
ActorDisplay $actor,
24+
) {
25+
parent::__construct($datetime, $actor);
26+
}
27+
28+
public function getType(): AuditRecordType
29+
{
30+
return AuditRecordType::PackageDeleted;
31+
}
32+
33+
public function getTemplateName(): string
34+
{
35+
return 'audit_log/display/package_deleted.html.twig';
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
3+
/*
4+
* This file is part of Packagist.
5+
*
6+
* (c) Jordi Boggiano <j.boggiano@seld.be>
7+
* Nils Adermann <naderman@naderman.de>
8+
*
9+
* For the full copyright and license information, please view the LICENSE
10+
* file that was distributed with this source code.
11+
*/
12+
13+
namespace App\Audit\Display;
14+
15+
use App\Audit\AuditRecordType;
16+
17+
readonly class VersionDeletedDisplay extends AbstractAuditLogDisplay
18+
{
19+
public function __construct(
20+
\DateTimeImmutable $datetime,
21+
public string $packageName,
22+
public string $version,
23+
ActorDisplay $actor,
24+
) {
25+
parent::__construct($datetime, $actor);
26+
}
27+
28+
public function getType(): AuditRecordType
29+
{
30+
return AuditRecordType::VersionDeleted;
31+
}
32+
33+
public function getTemplateName(): string
34+
{
35+
return 'audit_log/display/version_deleted.html.twig';
36+
}
37+
}

0 commit comments

Comments
 (0)