feat: Pods fields in Theme Builder bodies checked against the template's post types (E12)
Both forms Divi writes are recognized (ruling Q11): custom_meta_<key> and the dialog form post_meta_key + select_meta_key. Choice fields get a note about the stored value, relation fields name IDs (F4). Only templates the user may edit are checked or named; others are counted (Q21 pattern). Warnings only, also in the dry run of a live body. DynamicFields extracted from lit/divi-dynamic-sources. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicFields;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\FieldDefinition;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
final class DynamicFieldsTest extends TestCase
|
||||
{
|
||||
private static function fields(): DynamicFields
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('fields')->with('lit_person')->andReturn([
|
||||
new FieldDefinition('role', 'Funktion', 'string', 'pods', FieldDefinition::WRITABLE),
|
||||
new FieldDefinition('level', 'Stufe', 'choice', 'pods', FieldDefinition::WRITABLE),
|
||||
new FieldDefinition('mentor', 'Mentor', 'relation', 'pods', FieldDefinition::WRITABLE),
|
||||
]);
|
||||
|
||||
return new DynamicFields($schema, static fn (string $type): ?string => 'meta');
|
||||
}
|
||||
|
||||
public function testTextLikeFieldsAreOfferedOthersOmittedWithTheirReason(): void
|
||||
{
|
||||
[$offered, $omitted] = self::fields()->offered('lit_person');
|
||||
|
||||
self::assertSame(['role', 'level'], array_column($offered, 'key'));
|
||||
self::assertSame('{{field:role}}', $offered[0]['placeholder']);
|
||||
self::assertSame(['mentor'], array_column($omitted, 'key'));
|
||||
}
|
||||
|
||||
public function testReasonForOneKey(): void
|
||||
{
|
||||
self::assertNull(self::fields()->reason('lit_person', 'role'));
|
||||
self::assertStringContainsString('nur IDs', (string) self::fields()->reason('lit_person', 'mentor'));
|
||||
self::assertSame('kein bekanntes Feld dieses Inhaltstyps', self::fields()->reason('lit_person', 'telefon'));
|
||||
}
|
||||
|
||||
/** Answer F4 / stage3b render: a choice field shows its stored value ("senior"), not the label. */
|
||||
public function testChoiceFieldsGetANoteAboutTheStoredValue(): void
|
||||
{
|
||||
self::assertStringContainsString('gespeicherten Wert', (string) self::fields()->note('lit_person', 'level'));
|
||||
self::assertNull(self::fields()->note('lit_person', 'role'));
|
||||
self::assertNull(self::fields()->note('lit_person', 'mentor'));
|
||||
self::assertNull(self::fields()->note('lit_person', 'telefon'));
|
||||
}
|
||||
|
||||
private static function content(string $name, array $settings): string
|
||||
{
|
||||
return VariableRef::serialize('content', $name, $settings);
|
||||
}
|
||||
|
||||
/** Ruling Q11 / stage3b finding 12: both forms Divi resolves (DynamicContentOptionPostMetaKey.php:222-262). */
|
||||
public function testMetaKeyOfReadsBothFormsDiviWrites(): void
|
||||
{
|
||||
self::assertSame('role', DynamicFields::metaKeyOf(self::content('custom_meta_role', ['before' => ''])));
|
||||
self::assertSame('role', DynamicFields::metaKeyOf(self::content('post_meta_key', [
|
||||
'before' => '',
|
||||
'after' => '',
|
||||
'select_meta_key' => 'custom_meta_role',
|
||||
'meta_key' => '',
|
||||
'date_format' => 'default',
|
||||
'custom_date_format' => '',
|
||||
'enable_html' => 'off',
|
||||
])));
|
||||
self::assertSame('telefon', DynamicFields::metaKeyOf(self::content('post_meta_key', ['meta_key' => 'telefon'])));
|
||||
self::assertSame('telefon', DynamicFields::metaKeyOf(self::content('post_meta_key', [
|
||||
'select_meta_key' => 'custom_meta_manual_custom_field_value',
|
||||
'meta_key' => 'telefon',
|
||||
])));
|
||||
self::assertSame('telefon', DynamicFields::metaKeyOf(self::content(
|
||||
'custom_meta_manual_custom_field_value',
|
||||
['meta_key' => 'telefon']
|
||||
)));
|
||||
}
|
||||
|
||||
public function testMetaKeyOfIgnoresEverythingElse(): void
|
||||
{
|
||||
self::assertNull(DynamicFields::metaKeyOf(self::content('post_title', ['before' => ''])));
|
||||
self::assertNull(DynamicFields::metaKeyOf(self::content('post_meta_key', ['meta_key' => ''])));
|
||||
self::assertNull(DynamicFields::metaKeyOf(self::content('post_meta_key', ['select_meta_key' => 'role'])));
|
||||
self::assertNull(DynamicFields::metaKeyOf(self::content('custom_meta_', [])));
|
||||
self::assertNull(DynamicFields::metaKeyOf(
|
||||
'$variable({"type":"color","value":{"name":"custom_meta_role","settings":{}}})$'
|
||||
));
|
||||
self::assertNull(DynamicFields::metaKeyOf('custom_meta_role'));
|
||||
}
|
||||
|
||||
/** The real builder output (stage3b body 2391) names role, level and mentor. */
|
||||
public function testMetaKeysOfTheRealBuilderBody(): void
|
||||
{
|
||||
$content = DiviFixtures::markup('stage3b/tb-body--person-body.html');
|
||||
preg_match_all('/"value":"(\$variable\(.*?\)\$)"/', $content, $matches);
|
||||
$keys = [];
|
||||
foreach ($matches[1] as $value) {
|
||||
$key = DynamicFields::metaKeyOf((string) json_decode('"' . $value . '"'));
|
||||
if ($key !== null) {
|
||||
$keys[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
self::assertSame(['role', 'level', 'mentor'], $keys);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user