Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
86 lines
3.5 KiB
PHP
86 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP\Tests\Unit\Guides;
|
|
|
|
use LIT\MCP\Integrations\Divi\Compose\Placeholders;
|
|
use PHPUnit\Framework\TestCase;
|
|
use RecursiveDirectoryIterator;
|
|
use RecursiveIteratorIterator;
|
|
|
|
/**
|
|
* The loop part of the guides (Etappe 4e) says what the tools say: the refusal phrases come from the code, and every
|
|
* {{loop:<name>}} example names an option Divi 5.15.1 really registers (research 4e, table of the loop_* options).
|
|
*/
|
|
final class LoopGuideTest extends TestCase
|
|
{
|
|
/** Divi 5.15.1 option keys (without WooCommerce and ACF repeater options). */
|
|
private const DIVI_LOOP_OPTIONS = [
|
|
'loop_post_title', 'loop_post_excerpt', 'loop_post_date', 'loop_post_modified_date', 'loop_post_author',
|
|
'loop_post_author_bio', 'loop_post_author_profile_picture', 'loop_post_comment_count',
|
|
'loop_post_featured_image', 'loop_post_id', 'loop_post_link', 'loop_post_terms',
|
|
'loop_term_name', 'loop_term_description', 'loop_term_count', 'loop_term_permalink', 'loop_term_taxonomy',
|
|
'loop_term_featured_image', 'loop_user_name', 'loop_user_username', 'loop_user_email', 'loop_user_avatar',
|
|
'loop_user_description', 'loop_user_url', 'loop_menu_text', 'loop_menu_link', 'loop_menu_menu_order',
|
|
'loop_menu_attr_title', 'loop_menu_classes', 'loop_menu_xfn', 'loop_menu_description',
|
|
];
|
|
|
|
private const PHRASES = ['braucht eine Divi-Schleife', 'passt nicht zur Schleife', 'kein Schleifen-Kontext'];
|
|
|
|
private static function root(): string
|
|
{
|
|
return dirname(__DIR__, 3);
|
|
}
|
|
|
|
/** @return string Content of all guides. */
|
|
private static function guides(): string
|
|
{
|
|
$text = '';
|
|
foreach (glob(self::root() . '/docs/guides/*.md') ?: [] as $file) {
|
|
$text .= (string) file_get_contents($file) . "\n";
|
|
}
|
|
|
|
return $text;
|
|
}
|
|
|
|
public function testGuidesExplainTheLoopRefusals(): void
|
|
{
|
|
$guides = self::guides();
|
|
foreach (self::PHRASES as $phrase) {
|
|
self::assertStringContainsString($phrase, $guides, 'guides lack "' . $phrase . '"');
|
|
}
|
|
}
|
|
|
|
public function testRefusalPhrasesAreTheOnesTheCodeSays(): void
|
|
{
|
|
// Only string literals count (no comments), matched exactly including case.
|
|
$code = '';
|
|
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(self::root() . '/src'));
|
|
foreach ($files as $file) {
|
|
if (! str_ends_with((string) $file, '.php')) {
|
|
continue;
|
|
}
|
|
foreach (token_get_all((string) file_get_contents((string) $file)) as $token) {
|
|
if (is_array($token) && in_array($token[0], [T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE], true)) {
|
|
$code .= $token[1] . "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (self::PHRASES as $phrase) {
|
|
self::assertNotFalse(mb_strpos($code, $phrase), 'no source string says "' . $phrase . '"');
|
|
}
|
|
}
|
|
|
|
public function testLoopShortFormExamplesNameRealDiviOptions(): void
|
|
{
|
|
preg_match_all('/\{\{loop:([a-z0-9_]+)\}\}/', self::guides(), $examples);
|
|
self::assertNotEmpty($examples[1], 'the guides show no {{loop:…}} example');
|
|
foreach (array_unique($examples[1]) as $name) {
|
|
self::assertContains('loop_' . $name, self::DIVI_LOOP_OPTIONS, '{{loop:' . $name . '}} is no Divi option');
|
|
self::assertSame('loop_' . $name, Placeholders::LOOP[$name] ?? null, '{{loop:' . $name . '}} is not in Placeholders::LOOP');
|
|
}
|
|
}
|
|
}
|