Pick images, pages, forms, sections and terms instead of typing ids and addresses
The share image and featured image of a page become image fields with the library dialog, as do image settings of plugins. The editor offers forms, sections, categories and tags as lists, a page search next to every link target and in text links, the redirect target has a page search, and the form editor picks the reply field, the condition and the option images. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
31fb53c1fc
commit
711af312af
19 files changed
+446
-43
No files matched your search
@@ -9,6 +9,7 @@ use App\Content\MediaLibrary;
|
||||
use App\Content\MenuRepository;
|
||||
use App\Content\PageRepository;
|
||||
use App\Content\PartialRepository;
|
||||
use App\Content\PostRepository;
|
||||
use App\Content\SiteSettings;
|
||||
use App\Content\Theme;
|
||||
use App\Domain\InvalidForm;
|
||||
@@ -268,6 +269,35 @@ final class EditorSecurityTest extends WebTestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testImageSettingsOfAPostArePickedFromTheLibraryNotTypedAsAnId(): void
|
||||
{
|
||||
// Umut: „nicht dein ernst? ID aus Mediathek? schöne auswahl rein! auch bei Beitragsbild"
|
||||
$client = $this->login('editor');
|
||||
$pages = new PageRepository($this->db, new DocumentValidator(), new SiteSettings($this->db, new MediaLibrary($this->db, $this->path.'-media')));
|
||||
$id = $pages->createPage('mit-bild', null, 'post', DemoContent::pages()['home']);
|
||||
$media = str_repeat('c', 32);
|
||||
$this->db->insert('media', ['id' => $media, 'title' => 'Klassenzimmer', 'alt' => '', 'variants' => json_encode([['src' => '/media/'.$media.'/480', 'width' => 480, 'height' => 320, 'bytes' => 1]]), 'archived' => 0, 'version' => 1, 'created_at' => gmdate('Y-m-d H:i:s')]);
|
||||
$this->db->executeStatement('UPDATE page SET featured_media_id = ? WHERE id = ?', [$media, $id]);
|
||||
|
||||
$crawler = $client->request('GET', '/admin/posts');
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringNotContainsString('ID aus der Mediathek', $client->getResponse()->getContent());
|
||||
self::assertCount(1, $crawler->filter('script[src^="/assets/media-field.js"]'));
|
||||
// Das gewählte Beitragsbild: Kennung versteckt, Vorschau und Titel sichtbar.
|
||||
$featured = $crawler->filter('input[name="featuredMediaId"]')->closest('[data-media-field]');
|
||||
self::assertCount(1, $featured);
|
||||
self::assertSame('hidden', $featured->filter('input[name="featuredMediaId"]')->attr('type'));
|
||||
self::assertSame($media, $featured->filter('input[name="featuredMediaId"]')->attr('value'));
|
||||
self::assertSame('/media/'.$media.'/480', $featured->filter('img')->attr('src'));
|
||||
self::assertStringContainsString('Klassenzimmer', $featured->text());
|
||||
self::assertStringContainsString('Anderes Bild wählen', $featured->text());
|
||||
// Ohne Vorschaubild: Wählen statt Kennung eintippen.
|
||||
$og = $crawler->filter('input[name="ogMediaId"]')->closest('[data-media-field]');
|
||||
self::assertCount(1, $og);
|
||||
self::assertStringContainsString('Bild wählen oder hochladen', $og->text());
|
||||
self::assertNull($og->filter('img')->attr('src'));
|
||||
}
|
||||
|
||||
public function testLiveSearchReturnsFilteredEscapedResultsWithTheSamePermissionsAsTheFullScreen(): void
|
||||
{
|
||||
$client = $this->login('editor');
|
||||
@@ -653,6 +683,29 @@ final class EditorSecurityTest extends WebTestCase
|
||||
self::assertSame('Kontakt', $this->db->fetchOne('SELECT name FROM form'));
|
||||
}
|
||||
|
||||
public function testTheEditorPicksFormsSectionsAndTermsFromListsInsteadOfTypedAddresses(): void
|
||||
{
|
||||
// Was ein Baustein nur verknüpft, kommt als Liste Adresse => Name - der Editor macht
|
||||
// daraus Auswahlfelder statt Textfelder für Adressen.
|
||||
$media = new MediaLibrary($this->db, $this->path.'-media');
|
||||
$pages = new PageRepository($this->db, new DocumentValidator(), new SiteSettings($this->db, $media));
|
||||
(new FormRepository($this->db))->save('anfrage', 'Anfrage', [['name' => 'email', 'type' => 'email', 'label' => 'E-Mail', 'required' => true, 'help' => '', 'options' => []]], ['recipient' => 'info@example.com'], 0);
|
||||
$band = DemoContent::starter('Werbeband');
|
||||
$band['blocks'] = [['id' => 'band-text', 'type' => 'text', 'props' => ['text' => 'Aktion']]];
|
||||
(new PartialRepository($this->db, new DocumentValidator()))->create('section', 'band', 'Werbeband', $band);
|
||||
$post = $pages->createPage('ein-beitrag', null, 'post', DemoContent::pages()['home']);
|
||||
(new PostRepository($this->db, $media, new SiteSettings($this->db, $media)))->saveMetadata($post, [], ['Projekte'], ['Umbau'], $pages->findForEditor($post)['version']);
|
||||
|
||||
$client = $this->login('editor');
|
||||
$client->request('GET', '/admin/api/design');
|
||||
self::assertResponseIsSuccessful();
|
||||
$choices = json_decode($client->getResponse()->getContent(), true)['choices'];
|
||||
self::assertSame(['anfrage' => 'Anfrage'], $choices['forms']);
|
||||
self::assertSame(['band' => 'Werbeband'], $choices['sections']);
|
||||
self::assertSame(['projekte' => 'Projekte'], $choices['categories']);
|
||||
self::assertSame(['umbau' => 'Umbau'], $choices['tags']);
|
||||
}
|
||||
|
||||
public function testStylePresetsNeedAnEditorRoleACsrfTokenAndAValidStyle(): void
|
||||
{
|
||||
$client = $this->login('editor');
|
||||
|
||||
Reference in new issue
Block a user