Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
119 lines
5.1 KiB
PHP
119 lines
5.1 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Compose;
|
||
|
||
use LIT\MCP\Integrations\Divi\Compose\LoopScope;
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
/** Rulings X1/X2: the loop kind of a node, from Divi's queryType (LoopUtils.php:730-739, VB "Zj"). */
|
||
final class LoopScopeTest extends TestCase
|
||
{
|
||
/** @return array<string, array{string, string, string}> */
|
||
public static function queryTypes(): array
|
||
{
|
||
return [
|
||
'post types' => ['post_types', LoopScope::POST, 'Beiträge'],
|
||
'current page (archive main query)' => ['current_page', LoopScope::POST, 'Beiträge'],
|
||
'taxonomies' => ['post_taxonomies', LoopScope::TERM, 'Terme'],
|
||
'user roles' => ['user_roles', LoopScope::USER, 'Benutzer'],
|
||
'menus' => ['menus', LoopScope::MENU, 'Menü'],
|
||
'terms alias (audit L2)' => ['terms', LoopScope::TERM, 'Terme'],
|
||
'users alias (audit L2)' => ['users', LoopScope::USER, 'Benutzer'],
|
||
];
|
||
}
|
||
|
||
/** @dataProvider queryTypes */
|
||
public function testTheFiveQueryTypesOfTheBuilderHaveAKind(string $queryType, string $kind, string $label): void
|
||
{
|
||
$scope = LoopScope::ofQueryType($queryType);
|
||
|
||
self::assertTrue($scope->active());
|
||
self::assertSame($kind, $scope->kind());
|
||
self::assertSame($queryType, $scope->queryType());
|
||
self::assertSame($label, $scope->label());
|
||
}
|
||
|
||
public function testNoneIsNoLoop(): void
|
||
{
|
||
$scope = LoopScope::none();
|
||
|
||
self::assertFalse($scope->active());
|
||
self::assertNull($scope->kind());
|
||
self::assertNull($scope->queryType());
|
||
self::assertSame('', $scope->label());
|
||
}
|
||
|
||
/**
|
||
* Ruling X2: repeater_<acf field> rows need the acf_type setting the rules refuse (X7e); Divi's
|
||
* renderer knows no "terms"/"users" aliases for the content (LoopUtils.php:3130-3148), and sanitize_key()
|
||
* turns "" or an array into "" – a loop the tools do not support: no kind, every loop_* refused.
|
||
*/
|
||
public function testOtherQueryTypesAreALoopWithoutKind(): void
|
||
{
|
||
foreach (['repeater_team', '', 'Post_Types', 'post_types '] as $queryType) {
|
||
$scope = LoopScope::ofQueryType($queryType);
|
||
|
||
self::assertFalse($scope->active(), $queryType);
|
||
self::assertNull($scope->kind(), $queryType);
|
||
self::assertSame($queryType, $scope->queryType(), $queryType);
|
||
self::assertSame($queryType, $scope->label(), $queryType);
|
||
}
|
||
}
|
||
|
||
/** @return array<string, array{string, string|null}> */
|
||
public static function optionKinds(): array
|
||
{
|
||
return [
|
||
'post title' => ['loop_post_title', LoopScope::POST],
|
||
'post terms' => ['loop_post_terms', LoopScope::POST],
|
||
'post meta' => ['loop_post_meta_key_manual_custom_field', LoopScope::POST],
|
||
'product (post loop of products)' => ['loop_product_price_current', LoopScope::POST],
|
||
'term name (key, not the id "loop_name")' => ['loop_term_name', LoopScope::TERM],
|
||
'term meta' => ['loop_term_meta_key_manual_custom_field', LoopScope::TERM],
|
||
'user avatar' => ['loop_user_avatar', LoopScope::USER],
|
||
'user meta' => ['loop_user_meta_key_manual_custom_field', LoopScope::USER],
|
||
'menu link' => ['loop_menu_link', LoopScope::MENU],
|
||
'acf repeater row' => ['loop_acf_team|||name', null],
|
||
'no loop option' => ['post_title', null],
|
||
'prefix without underscore' => ['loopy_title', null],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* The kind an option NAME belongs to – Divi takes the meta type of loop_<type>_meta_key_* from the
|
||
* name too (DynamicContentOptionLoopPostMetaKey::get_meta_type_from_name, :334-345).
|
||
*
|
||
* @dataProvider optionKinds
|
||
*/
|
||
public function testTheOptionNameGivesItsKind(string $option, ?string $kind): void
|
||
{
|
||
self::assertSame($kind, LoopScope::kindOfOption($option));
|
||
}
|
||
|
||
public function testFitsOnlyAnOptionOfTheSameKind(): void
|
||
{
|
||
$terms = LoopScope::ofQueryType('post_taxonomies');
|
||
|
||
self::assertTrue($terms->fits('loop_term_name'));
|
||
self::assertTrue($terms->fits('loop_term_meta_key_manual_custom_field'));
|
||
self::assertFalse($terms->fits('loop_post_meta_key_manual_custom_field'));
|
||
self::assertFalse($terms->fits('loop_acf_team|||name'));
|
||
self::assertFalse($terms->fits('post_title'));
|
||
self::assertFalse(LoopScope::none()->fits('loop_post_title'));
|
||
self::assertFalse(LoopScope::ofQueryType('repeater_team')->fits('loop_post_title'));
|
||
self::assertTrue(LoopScope::ofQueryType('current_page')->fits('loop_post_title'));
|
||
}
|
||
|
||
/** The one reading of Divi's sanitize_key() (LoopUtils.php:725-731) the loop checks share. */
|
||
public function testSanitizeKeyReadsLikeDivi(): void
|
||
{
|
||
self::assertSame('userbb_roles', LoopScope::sanitizeKey(' User<b></b>_Roles '));
|
||
self::assertSame('on', LoopScope::sanitizeKey('o n'));
|
||
self::assertSame('1', LoopScope::sanitizeKey(true));
|
||
self::assertSame('', LoopScope::sanitizeKey(null));
|
||
self::assertSame('', LoopScope::sanitizeKey(['on']));
|
||
}
|
||
}
|