Kant CMS: Grundgerüst, visueller Editor, Mediathek

Symfony 7.4 / Twig / Doctrine DBAL auf herkömmlichem PHP-Webhosting.
Versionierte Blockdokumente (v1-v3) mit unveränderlichen Revisionen,
getrennten Entwürfen/Veröffentlichungen und optimistischer
Konflikterkennung. Visueller Editor mit Strukturbaum, Live-Vorschau,
responsiven Gerätewerten, Abschnittsvorlagen, Bildmediathek,
Galerien und Effekten. Öffentliche Ausgabe ohne Editor-JavaScript.

Geprüft: 41 PHP-Tests / 155 Assertions, 10 JavaScript-Modelltests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-12 10:19:05 +02:00
commit 82b07820bc
87 files changed
+14463

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
<?php
namespace App\Security;
use App\Domain\CmsUser;
use Doctrine\DBAL\Connection;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
final class UserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
public function __construct(private Connection $db)
{
}
public function loadUserByIdentifier(string $identifier): CmsUser
{
$row = $this->db->fetchAssociative('SELECT * FROM cms_user WHERE username = ?', [strtolower(trim($identifier))]);
if (false === $row) {
throw new UserNotFoundException();
}
return new CmsUser($row['id'], $row['username'], $row['password_hash'], json_decode($row['roles'], true, 512, JSON_THROW_ON_ERROR));
}
public function refreshUser(UserInterface $user): UserInterface
{
if (!$user instanceof CmsUser) {
throw new UnsupportedUserException();
}
$fresh = $this->loadUserByIdentifier($user->getUserIdentifier());
if ($fresh->id !== $user->id) {
throw new UserNotFoundException();
}
return $fresh;
}
public function supportsClass(string $class): bool
{
return CmsUser::class === $class;
}
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof CmsUser) {
throw new UnsupportedUserException();
}
$changed = $this->db->executeStatement('UPDATE cms_user SET password_hash = ? WHERE id = ? AND password_hash = ?', [$newHashedPassword, $user->id, $user->getPassword()]);
if (1 === $changed) {
$user->setPasswordHash($newHashedPassword);
}
}
}