diff --git a/src/Integrations/Divi/Design/DiviThemeOptionsGetAbility.php b/src/Integrations/Divi/Design/DiviThemeOptionsGetAbility.php index 386b263..c3d137b 100644 --- a/src/Integrations/Divi/Design/DiviThemeOptionsGetAbility.php +++ b/src/Integrations/Divi/Design/DiviThemeOptionsGetAbility.php @@ -122,7 +122,8 @@ final class DiviThemeOptionsGetAbility implements Ability, RequiresDiviFeatures return $keys; } - $book = ThemeOptionBook::fromDivi($this->options->read()); + $stored = ThemeOptionBook::fromDivi($this->options->read()); + $book = $stored->withoutFalse(); $rows = []; foreach ($keys as $key) { $definition = ThemeOptionSpec::definition($key); @@ -137,7 +138,7 @@ final class DiviThemeOptionsGetAbility implements Ability, RequiresDiviFeatures ] + array_intersect_key($definition, array_flip(self::RULES)); } - return ['options' => $rows, 'design_rev' => $book->rev(), 'notes' => self::NOTES]; + return ['options' => $rows, 'design_rev' => $stored->rev(), 'notes' => self::NOTES]; } /** Like lit/divi-design-system: whoever edits content may read the design. */ diff --git a/src/Integrations/Divi/Design/DiviThemeOptionsUpdateAbility.php b/src/Integrations/Divi/Design/DiviThemeOptionsUpdateAbility.php index 1e004f2..ffebb23 100644 --- a/src/Integrations/Divi/Design/DiviThemeOptionsUpdateAbility.php +++ b/src/Integrations/Divi/Design/DiviThemeOptionsUpdateAbility.php @@ -123,7 +123,7 @@ final class DiviThemeOptionsUpdateAbility implements Ability, RequiresDiviFeatur $this->name(), new ThemeOptionsArea($this->options), $input, - fn (array $raw): DesignPlan|WP_Error => $this->plan(ThemeOptionBook::fromDivi($raw), $set) + fn (array $raw): DesignPlan|WP_Error => $this->plan(ThemeOptionBook::fromDivi($raw)->withoutFalse(), $set) ); } diff --git a/src/Integrations/Divi/Design/ThemeOptionBook.php b/src/Integrations/Divi/Design/ThemeOptionBook.php index 32d2c26..da23463 100644 --- a/src/Integrations/Divi/Design/ThemeOptionBook.php +++ b/src/Integrations/Divi/Design/ThemeOptionBook.php @@ -77,4 +77,10 @@ final class ThemeOptionBook { return self::fromDivi(array_diff_key($this->data, [$key => true])); } + + /** Divi stores its default font as false: that is "not set" (W3), as ThemeOptionSpec::effective() sees it. */ + public function withoutFalse(): self + { + return self::fromDivi(array_filter($this->data, static fn (mixed $value): bool => $value !== false)); + } } diff --git a/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsGetAbilityTest.php b/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsGetAbilityTest.php index e357a75..93e5acf 100644 --- a/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsGetAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsGetAbilityTest.php @@ -84,6 +84,23 @@ final class DiviThemeOptionsGetAbilityTest extends TestCase self::assertSame('Open Sans', $rows['body_font']['value']); } + /** Divi stores its default font as false: reported as not set, with the default in effect. */ + public function testAStoredFalseCountsAsNotSet(): void + { + $stored = ['heading_font' => false] + ThemeOptionsAreaTest::stored(); + $writes = []; + $ability = new DiviThemeOptionsGetAbility(ThemeOptionsAreaTest::adapter($stored, $writes)); + + $result = $ability->execute([]); + $row = self::byKey($result)['heading_font']; + self::assertSame(ThemeOptionBook::fromDivi($stored)->rev(), $result['design_rev'], 'the rev of the dry run'); + + self::assertNull($row['value']); + self::assertTrue($row['is_default']); + self::assertSame(ThemeOptionSpec::effective('heading_font', []), $row['effective']); + self::assertSame($row['effective'], $row['default']); + } + /** Ruling W3: an unset tablet size inherits the desktop size – as effective value and as its default. */ public function testUnsetSizesInheritTheLargerSize(): void { diff --git a/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsUpdateAbilityTest.php b/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsUpdateAbilityTest.php index f3ffbaf..fef9be7 100644 --- a/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsUpdateAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Design/DiviThemeOptionsUpdateAbilityTest.php @@ -280,6 +280,22 @@ final class DiviThemeOptionsUpdateAbilityTest extends TestCase self::assertSame([], $this->writes); } + /** A stored false (Divi's default font) is "not set": null is no change, a font is "added". */ + public function testAStoredFalseCountsAsNotSet(): void + { + $this->stored = ['heading_font' => false] + $this->stored; + + self::assertSame([], $this->ability()->execute(['set' => ['heading_font' => null]])['diff']); + $dry = self::assertToolError( + $this->ability()->execute(['set' => ['heading_font' => 'Roboto']]), + 'confirm_required' + ); + self::assertSame([['heading_font', 'added']], array_map( + static fn (array $row): array => [$row['key'], $row['action']], + $dry['diff'] + )); + } + public function testUnchangedValuesAreNoChange(): void { $result = $this->ability()->execute(['set' => ['body_font_size' => 16, 'gutter_width' => null]]);