Stored format like GlobalPreset::get_data(). */ public static function stored(): array { return [ 'module' => [ 'divi/button' => ['default' => '', 'items' => [ 'aaaaaaaaaa' => ['type' => 'module', 'id' => 'aaaaaaaaaa', 'name' => 'CTA primär', 'moduleName' => 'divi/button', 'attrs' => ['button' => ['x' => 1]]], 'bbbbbbbbbb' => ['type' => 'module', 'id' => 'bbbbbbbbbb', 'name' => 'Doppelt', 'moduleName' => 'divi/button', 'attrs' => []], 'cccccccccc' => ['type' => 'module', 'id' => 'cccccccccc', 'name' => 'doppelt', 'moduleName' => 'divi/button', 'attrs' => []], ]], 'divi/text' => ['default' => 'dddddddddd', 'items' => [ 'dddddddddd' => ['type' => 'module', 'id' => 'dddddddddd', 'name' => 'Fließtext', 'moduleName' => 'divi/text', 'attrs' => [], 'groupPresets' => ['content.decoration.bodyFont' => [ 'presetId' => ['gggggggggg'], 'groupName' => 'divi/font-body']]], ]], ], 'group' => [ 'divi/font-body' => ['default' => '', 'items' => [ 'gggggggggg' => ['type' => 'group', 'id' => 'gggggggggg', 'name' => 'Lesetext', 'groupName' => 'divi/font-body', 'groupId' => 'content.decoration.bodyFont', 'moduleName' => 'divi/text', 'attrs' => []], ]], ], ]; } /** @return array stored() with HTML in one preset and CSS with ">" in another. */ public static function storedWithMarkup(): array { $stored = self::stored(); $stored['module']['divi/button']['items']['bbbbbbbbbb']['attrs'] = [ 'module' => ['advanced' => ['html' => ['desktop' => ['value' => ['htmlBefore' => 'x']]]]], ]; $stored['group']['divi/font-body']['items']['gggggggggg']['styleAttrs'] = [ 'css' => ['desktop' => ['value' => ['freeForm' => 'selector > p { color: red; }']]], ]; return $stored; } /** Final review I-2: presets whose HTML/CSS Divi's prepare_data() would strip for editors. */ public function testMarkupOutsideListsUntouchedPresetsWithHtmlOrCss(): void { $book = PresetBook::fromDivi(self::storedWithMarkup()); self::assertSame([], PresetBook::fromDivi(self::stored())->markupOutside([])); self::assertSame(['bbbbbbbbbb', 'gggggggggg'], $book->markupOutside([])); self::assertSame(['gggggggggg'], $book->markupOutside(['bbbbbbbbbb', 'aaaaaaaaaa'])); self::assertSame([], $book->markupOutside(['bbbbbbbbbb', 'gggggggggg'])); } public function testFindsByIdOrUniqueName(): void { $book = PresetBook::fromDivi(self::stored()); $button = new PresetScope('module', 'divi/button'); self::assertSame('aaaaaaaaaa', $book->find($button, 'aaaaaaaaaa')['id']); self::assertSame('aaaaaaaaaa', $book->find($button, 'cta PRIMÄR')['id']); self::assertNull($book->find($button, 'Fehlt')); self::assertNull($book->find(new PresetScope('module', 'divi/text'), 'aaaaaaaaaa')); self::assertSame(['bbbbbbbbbb', 'cccccccccc'], $book->idsNamed($button, 'DOPPELT')); } public function testAmbiguousNameListsTheIds(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( 'Preset-Name "Doppelt" ist mehrdeutig; bitte die ID angeben: bbbbbbbbbb, cccccccccc.' ); PresetBook::fromDivi(self::stored())->find(new PresetScope('module', 'divi/button'), 'Doppelt'); } public function testStdClassGroupsBecomeArraysAndCountCoversBothKinds(): void { $raw = self::stored(); $raw['group'] = (object) ['divi/font-body' => (object) $raw['group']['divi/font-body']]; $book = PresetBook::fromDivi($raw); self::assertSame(5, $book->count()); self::assertIsArray($book->data()['group']['divi/font-body']['items']); self::assertSame('group', $book->scopeOf('gggggggggg')?->kind); self::assertNull($book->scopeOf('zzzzzzzzzz')); self::assertSame(0, PresetBook::fromDivi(new stdClass())->count()); } public function testWithWithoutAndDefaultAreImmutable(): void { $book = PresetBook::fromDivi(self::stored()); $button = new PresetScope('module', 'divi/button'); $new = [ 'type' => 'module', 'id' => 'eeeeeeeeee', 'name' => 'Neu', 'moduleName' => 'divi/button', 'attrs' => [], ]; $added = $book->with($button, $new)->withDefault($button, 'eeeeeeeeee'); $removed = $added->without($button, 'eeeeeeeeee'); self::assertSame(5, $book->count()); self::assertSame(6, $added->count()); self::assertSame('eeeeeeeeee', $added->defaultId($button)); self::assertSame('', $removed->defaultId($button), 'removing the default clears it'); self::assertNotSame($book->rev(), $added->rev()); self::assertSame($book->rev(), PresetBook::fromDivi(self::stored())->rev()); self::assertSame('', $book->defaultId(new PresetScope('group', 'divi/spacing'))); } public function testNestedUsersOfAGroupPreset(): void { $users = PresetBook::fromDivi(self::stored())->nestedUsers('gggggggggg'); self::assertCount(1, $users); self::assertSame(['dddddddddd', 'Fließtext'], [$users[0]['id'], $users[0]['name']]); self::assertSame('divi/text', $users[0]['scope']->name); } public function testRestFormatListsItemsPerName(): void { $rest = PresetBook::fromDivi(self::stored())->toRest(); self::assertSame('dddddddddd', $rest['module'][1]['default']); self::assertSame(['aaaaaaaaaa', 'bbbbbbbbbb', 'cccccccccc'], array_column($rest['module'][0]['items'], 'id')); self::assertSame('gggggggggg', $rest['group'][0]['items'][0]['id']); self::assertTrue(array_is_list($rest['module'])); } public function testNewIdsLookLikeTheBuildersIds(): void { self::assertMatchesRegularExpression('/^[0-9a-z]{10}$/', PresetBook::newId()); self::assertNotSame(PresetBook::newId(), PresetBook::newId()); } }