$value) { if (is_array($value)) { $kept = array_diff_key($value, ['innerContent' => true]); if ($kept !== []) { $all[$key] = $kept; } } } return ['all' => $all, 'style' => $all, 'render' => []]; }; } private static function composer(bool $unfiltered = true): PresetComposer { return new PresetComposer( ComposeFixture::composer($unfiltered), new StoredNodeGuard( ComposeFixture::cleaner($unfiltered), ComposeFixture::references(), ComposeFixture::sanitizer($unfiltered) ), self::presetAttrs(), static fn (string $module): array => [ 'module.decoration.spacing' => 'divi/spacing', 'button.decoration.font' => 'divi/font', ], '5.15.1', static fn (): int => self::NOW ); } private static function book(): PresetBook { return PresetBook::fromDivi(PresetBookTest::stored()); } public function testNewModulePresetFromAttrs(): void { $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), null, [ 'name' => 'CTA sekundär', 'attrs' => ['button.decoration.background' => ['desktop' => ['color' => '#123456']]], ], 'items[0]', null); self::assertSame([], $result['errors']); $item = $result['item']; self::assertMatchesRegularExpression('/^[0-9a-z]{10}$/', $item['id']); self::assertSame(['module', 'CTA sekundär', 'divi/button', '5.15.1'], [$item['type'], $item['name'], $item['moduleName'], $item['version']]); self::assertSame([self::NOW, self::NOW], [$item['created'], $item['updated']]); self::assertSame('#123456', $item['attrs']['button']['decoration']['background']['desktop']['value']['color']); self::assertSame($item['attrs'], $item['styleAttrs']); self::assertArrayNotHasKey('renderAttrs', $item); } public function testContentPathsAreRefused(): void { $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), null, [ 'name' => 'Mit Text', 'set' => ['text' => 'Jetzt buchen'], ], 'items[0]', null); self::assertArrayHasKey('items[0].attrs.button.innerContent', $result['errors']); self::assertStringContainsString('kein Preset-Attribut', $result['errors']['items[0].attrs.button.innerContent']); } public function testChangingMergesKeepsIdCreatedAndOrder(): void { $existing = self::book()->items(new PresetScope('module', 'divi/button'))['aaaaaaaaaa']; $existing['created'] = 5; $existing['order'] = 3; $existing['attrs'] = ['button' => ['decoration' => ['border' => ['desktop' => ['value' => ['radius' => '4px']]]]]]; $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), $existing, [ 'rename' => 'CTA Primär', 'attrs' => ['button.decoration.background' => ['desktop' => ['color' => '#000000']]], ], 'items[0]', null); self::assertSame([], $result['errors']); self::assertSame(['aaaaaaaaaa', 'CTA Primär', 5, self::NOW, 3], [$result['item']['id'], $result['item']['name'], $result['item']['created'], $result['item']['updated'], $result['item']['order']]); self::assertSame('4px', $result['item']['attrs']['button']['decoration']['border']['desktop']['value']['radius']); } public function testFromNodeTakesTheDesignButNotTheContent(): void { $node = Block::create('divi/button', [ 'button' => [ 'innerContent' => ['desktop' => ['value' => ['text' => 'Hallo']]], 'decoration' => ['background' => ['desktop' => ['value' => ['color' => '#abcdef']]]], ], ]); $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), null, [ 'name' => 'Aus Seite', ], 'items[0]', $node); self::assertSame([], $result['errors']); self::assertSame('#abcdef', $result['item']['attrs']['button']['decoration']['background']['desktop']['value']['color']); self::assertArrayNotHasKey('innerContent', $result['item']['attrs']['button']); } public function testEditorCannotCarryBuilderOnlyValuesFromANode(): void { $node = Block::create('divi/button', [ 'css' => ['desktop' => ['value' => ['mainElement' => 'color:red']]], 'button' => ['decoration' => ['background' => ['desktop' => ['value' => ['color' => '#000000']]]]], ]); $result = self::composer(false)->compose(self::book(), new PresetScope('module', 'divi/button'), null, [ 'name' => 'Mit CSS', ], 'items[0]', $node); self::assertArrayHasKey('items[0].from_node', $result['errors']); } public function testGroupPresetOnlyTakesItsGroup(): void { $result = self::composer()->compose(self::book(), new PresetScope('group', 'divi/spacing'), null, [ 'name' => 'Abstand groß', 'source_module' => 'button', 'attrs' => [ 'module.decoration.spacing' => ['desktop' => ['padding' => ['top' => '40px']]], 'button.decoration.background' => ['desktop' => ['color' => '#000000']], ], ], 'items[0]', null); self::assertSame( 'gehört nicht zur Gruppe module.decoration.spacing', $result['errors']['items[0].attrs.button.decoration.background'] ); self::assertSame(['group', 'divi/spacing', 'module.decoration.spacing', 'divi/button'], [ $result['item']['type'], $result['item']['groupName'], $result['item']['groupId'], $result['item']['moduleName'], ]); } public function testNestedGroupPresetsByShortName(): void { $book = self::book()->with(new PresetScope('group', 'divi/font'), [ 'type' => 'group', 'id' => 'ffffffffff', 'name' => 'Button-Schrift', 'groupName' => 'divi/font', 'groupId' => 'button.decoration.font', 'moduleName' => 'divi/button', 'attrs' => [], ]); $result = self::composer()->compose($book, new PresetScope('module', 'divi/button'), null, [ 'name' => 'Mit Schrift', 'group_presets' => ['font' => 'Button-Schrift'], ], 'items[0]', null); self::assertSame([], $result['errors']); self::assertSame( ['button.decoration.font' => ['presetId' => ['ffffffffff'], 'groupName' => 'divi/font']], $result['item']['groupPresets'] ); } public function testUnknownGroupAndPresetAreErrors(): void { $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), null, [ 'name' => 'X', 'group_presets' => ['sizing' => 'Gibt es nicht', 'font' => 'Fehlt'], ], 'items[0]', null); self::assertStringContainsString('keine Gruppe', $result['errors']['items[0].group_presets.sizing']); self::assertStringContainsString('unbekanntes Gruppen-Preset', $result['errors']['items[0].group_presets.font']); } public function testNewPresetNeedsAName(): void { $result = self::composer()->compose(self::book(), new PresetScope('module', 'divi/button'), null, [], 'items[0]', null); self::assertSame('Name des neuen Presets fehlt', $result['errors']['items[0].name']); } }