['value' => $value]]; } /** * @param list}> $blocks name and attributes, in the order of the column * @return NodeIndex Blocks below s0.r0.c0 are m0, m1, … (g0, … for instances, x0, … for other blocks). */ private static function index(array $blocks): NodeIndex { $inner = ''; foreach ($blocks as [$name, $attrs]) { $inner .= sprintf('', $name, Json::encode($attrs)); } return NodeIndex::build((new Parser())->parse( '' . $inner . '' )); } private static function node(NodeIndex $index, string $id): Block { $block = $index->find('s0.r0.c0.' . $id); self::assertNotNull($block); return $block; } public function testReplacesWholeNumberReferencesAtAnyDepth(): void { $index = self::index([['divi/button', [ 'button' => ['decoration' => ['border' => self::desktop([ 'radius' => ['topLeft' => self::ref(self::RADIUS), 'topRight' => self::ref(self::RADIUS)], ])]], 'module' => ['decoration' => ['spacing' => self::desktop(['padding' => ['top' => '10px']])]], ]]]); $attrs = (new VariableDetachRewrite(self::RADIUS, '8px', 'numbers'))->rewrite(self::node($index, 'm0')); self::assertSame( ['topLeft' => '8px', 'topRight' => '8px'], $attrs['button']['decoration']['border']['desktop']['value']['radius'] ?? null ); self::assertSame('10px', $attrs['module']['decoration']['spacing']['desktop']['value']['padding']['top']); } public function testAStringsVariableKeepsBeforeAndAfterOfTheReference(): void { $index = self::index([ ['divi/text', ['content' => ['innerContent' => self::desktop( self::ref(self::CLAIM, ['before' => 'Jetzt: ', 'after' => '!']) )]]], ['divi/text', ['content' => ['innerContent' => self::desktop(self::ref(self::CLAIM))]]], ]); $rewrite = new VariableDetachRewrite(self::CLAIM, 'Gut beraten', 'strings'); self::assertSame( 'Jetzt: Gut beraten!', $rewrite->rewrite(self::node($index, 'm0'))['content']['innerContent']['desktop']['value'] ?? null ); self::assertSame( 'Gut beraten', $rewrite->rewrite(self::node($index, 'm1'))['content']['innerContent']['desktop']['value'] ?? null ); } public function testOtherTypesIgnoreBeforeAndAfter(): void { self::assertSame( 'Open Sans', VariableDetachRewrite::replacement(self::ref('gvid-font000001', ['before' => 'x']), 'Open Sans', 'fonts') ); self::assertSame('a1b', VariableDetachRewrite::replacement(self::ref(self::CLAIM, [ 'before' => 'a', 'after' => 'b', ]), '1', 'strings')); } public function testFontsAndOtherReferencesStayUntouched(): void { $color = VariableRef::serialize('color', 'gcid-primary-color', []); $dynamic = VariableRef::serialize('content', 'post_title', []); $index = self::index([ ['divi/heading', [ 'title' => ['decoration' => ['font' => ['font' => self::desktop([ 'family' => self::ref('gvid-font000001'), 'color' => $color, ])]]], 'content' => ['innerContent' => self::desktop($dynamic)], ]], ['divi/text', ['content' => ['innerContent' => self::desktop(self::ref(self::RADIUS))]]], ['core/paragraph', ['content' => self::ref('gvid-font000001')]], ]); $rewrite = new VariableDetachRewrite('gvid-font000001', 'Open Sans', 'fonts'); $attrs = $rewrite->rewrite(self::node($index, 'm0')); self::assertSame( ['family' => 'Open Sans', 'color' => $color], $attrs['title']['decoration']['font']['font']['desktop']['value'] ?? null ); self::assertSame($dynamic, $attrs['content']['innerContent']['desktop']['value']); self::assertNull($rewrite->rewrite(self::node($index, 'm1')), 'another variable'); self::assertNull($rewrite->rewrite(self::node($index, 'x0')), 'not a Divi block'); } public function testEmbeddedReferencesStayAndAreNoted(): void { $embedded = 'Ab ' . self::ref(self::RADIUS) . ' Rundung'; $index = self::index([ ['divi/text', [ 'content' => ['innerContent' => self::desktop($embedded)], 'module' => ['decoration' => ['border' => self::desktop([ 'radius' => ['topLeft' => self::ref(self::RADIUS)], ])]], ]], ['divi/text', ['content' => ['innerContent' => self::desktop($embedded)]]], ]); $rewrite = new VariableDetachRewrite(self::RADIUS, '8px', 'numbers'); $first = self::node($index, 'm0'); $attrs = $rewrite->rewrite($first); self::assertSame($embedded, $attrs['content']['innerContent']['desktop']['value'] ?? null); $first->setAttrs((array) $attrs); self::assertStringContainsString('eingebettet', (string) $rewrite->leftover($first)); self::assertStringContainsString('bleibt unverändert', (string) $rewrite->leftover($first)); self::assertNotNull($rewrite->leftover(self::node($index, 'm1')), 'embedded only: still reported'); self::assertNull($rewrite->rewrite(self::node($index, 'm1')), 'only embedded: nothing to replace'); self::assertNull( (new VariableDetachRewrite(self::CLAIM, 'x', 'strings'))->leftover($first), 'another variable is not reported' ); } public function testUnsafeBeforeAndAfterLeaveTheBlockWholeAndReportIt(): void { $index = self::index([ ['divi/text', ['content' => ['innerContent' => self::desktop(self::ref(self::CLAIM, ['before' => '']))]]], ['divi/text', ['content' => ['innerContent' => self::desktop( // Built by hand: VariableRef::serialize() itself refuses a marker in the settings. '$variable(' . Json::encode(['type' => 'content', 'value' => [ 'name' => self::CLAIM, 'settings' => ['after' => 'a $variable(b'] ]]) . ')$' )]]], ['divi/text', ['content' => ['innerContent' => self::desktop(self::ref(self::CLAIM, ['before' => '']))]]], ]); $strict = new VariableDetachRewrite(self::CLAIM, 'x', 'strings'); $allowed = new VariableDetachRewrite(self::CLAIM, 'x', 'strings', true); self::assertNull($strict->rewrite(self::node($index, 'm0'))); self::assertStringContainsString('Markup', (string) $strict->leftover(self::node($index, 'm0'))); self::assertNull($allowed->rewrite(self::node($index, 'm1')), 'a marker is never inlined'); self::assertNotNull($allowed->leftover(self::node($index, 'm1'))); $third = self::node($index, 'm2'); $attrs = (array) $allowed->rewrite($third); self::assertSame('x', $attrs['content']['innerContent']['desktop']['value'] ?? null); $third->setAttrs($attrs); self::assertNull($allowed->leftover($third)); } public function testInstancesThatMentionTheIdConcernTheRewrite(): void { $index = self::index([ ['divi/global-layout', ['globalModule' => '1058', 'blockName' => 'divi/text', 'localAttrs' => [ 'content' => ['innerContent' => self::desktop(self::ref(self::RADIUS))], ]]], ['divi/global-layout', ['globalModule' => '1059', 'blockName' => 'divi/text']], ]); $rewrite = new VariableDetachRewrite(self::RADIUS, '8px', 'numbers'); self::assertTrue($rewrite->concernsInstance(self::node($index, 'g0'))); self::assertFalse($rewrite->concernsInstance(self::node($index, 'g1'))); } }