diff --git a/includes/class-micropub.php b/includes/class-micropub.php index 1006003..d5b9dca 100644 --- a/includes/class-micropub.php +++ b/includes/class-micropub.php @@ -32,6 +32,13 @@ class Micropub { */ const TEXT_DOMAIN = 'micropub'; + /** + * Option name for storing microformats2 theme support detection. + * + * @var string + */ + const MICROFORMATS2_SUPPORT_OPTION = 'micropub_theme_supports_mf2'; + /** * Get the instance of the class. * @@ -59,6 +66,9 @@ public function init() { \add_action( 'rest_api_init', array( $this, 'rest_init' ) ); \add_action( 'init', array( $this, 'plugin_init' ) ); \add_action( 'admin_notices', array( $this, 'ssl_notice' ) ); + + // Clear microformats2 support cache when theme changes. + \add_action( 'switch_theme', array( $this, 'clear_microformats2_support_cache' ) ); } /** @@ -102,4 +112,77 @@ public function ssl_notice() { ]*>.*?<\/\1>/is', '', $output ); + + // If the regex fails, abort detection to avoid incorrect caching. + if ( null === $filtered ) { + return; + } + + // Check if e-content exists as a class attribute value. + // Matches class="...e-content..." or class='...e-content...'. + $has_support = preg_match( '/class=["\'][^"\']*\be-content\b[^"\']*["\']/', $filtered ); + + \update_option( self::MICROFORMATS2_SUPPORT_OPTION, $has_support ? 'yes' : 'no', false ); + } } diff --git a/includes/class-render.php b/includes/class-render.php index 4bc8f98..1d17804 100644 --- a/includes/class-render.php +++ b/includes/class-render.php @@ -159,9 +159,15 @@ public static function generate_post_content( $post_content, $input ) { } if ( ! empty( $post_content ) ) { - $lines[] = '
'; + // Only wrap in e-content if theme doesn't already provide microformats2 support. + $wrap_econtent = ! Micropub::theme_supports_microformats2(); + if ( $wrap_econtent ) { + $lines[] = '
'; + } $lines[] = $post_content; - $lines[] = '
'; + if ( $wrap_econtent ) { + $lines[] = '
'; + } } // Generate gallery markup for media fields. diff --git a/tests/test_functions.php b/tests/test_functions.php index 673b895..07a8962 100644 --- a/tests/test_functions.php +++ b/tests/test_functions.php @@ -27,3 +27,92 @@ function test_mp_filter() { ); } } + +class MicropubMicroformats2DetectionTest extends WP_UnitTestCase { + function tear_down() { + // Clean up after each test. + remove_theme_support( 'microformats2' ); + delete_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ); + parent::tear_down(); + } + + function test_theme_supports_microformats2_with_explicit_support() { + add_theme_support( 'microformats2' ); + + $this->assertTrue( \Micropub\Micropub::theme_supports_microformats2() ); + } + + function test_theme_supports_microformats2_with_cached_yes() { + update_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION, 'yes' ); + + $this->assertTrue( \Micropub\Micropub::theme_supports_microformats2() ); + } + + function test_theme_supports_microformats2_with_cached_no() { + update_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION, 'no' ); + + $this->assertFalse( \Micropub\Micropub::theme_supports_microformats2() ); + } + + function test_theme_supports_microformats2_returns_false_when_not_cached() { + // No theme support and no cached value. + $this->assertFalse( \Micropub\Micropub::theme_supports_microformats2() ); + } + + function test_clear_microformats2_support_cache() { + update_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION, 'yes' ); + + $micropub = \Micropub\Micropub::get_instance(); + $micropub->clear_microformats2_support_cache(); + + $this->assertFalse( get_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ) ); + } + + function test_detect_microformats2_support_finds_econtent_in_class() { + // Start output buffering to simulate page output. + ob_start(); + echo '
Test
'; + + \Micropub\Micropub::detect_microformats2_support(); + + ob_end_clean(); + + $this->assertEquals( 'yes', get_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ) ); + } + + function test_detect_microformats2_support_ignores_econtent_in_code_blocks() { + // Start output buffering to simulate page output. + ob_start(); + echo 'class="e-content"'; + + \Micropub\Micropub::detect_microformats2_support(); + + ob_end_clean(); + + $this->assertEquals( 'no', get_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ) ); + } + + function test_detect_microformats2_support_ignores_econtent_in_pre_blocks() { + // Start output buffering to simulate page output. + ob_start(); + echo '
class="e-content"
'; + + \Micropub\Micropub::detect_microformats2_support(); + + ob_end_clean(); + + $this->assertEquals( 'no', get_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ) ); + } + + function test_detect_microformats2_support_ignores_econtent_as_plain_text() { + // Start output buffering to simulate page output. + ob_start(); + echo '

The e-content class is used in microformats2.

'; + + \Micropub\Micropub::detect_microformats2_support(); + + ob_end_clean(); + + $this->assertEquals( 'no', get_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ) ); + } +} diff --git a/tests/test_render.php b/tests/test_render.php index 780bc8d..7102666 100644 --- a/tests/test_render.php +++ b/tests/test_render.php @@ -218,4 +218,61 @@ function test_merges_auto_generated_content() { $post_content ); } + + function test_no_econtent_wrapper_when_theme_supports_microformats2() { + // Simulate theme support for microformats2. + add_theme_support( 'microformats2' ); + + $content = '

Test content

'; + $input = array( + 'properties' => array( + 'content' => array( $content ), + ), + ); + $post_content = \Micropub\Render::generate_post_content( $content, $input ); + + // Should not have e-content wrapper. + $this->assertEquals( '

Test content

', $post_content ); + + // Clean up. + remove_theme_support( 'microformats2' ); + } + + function test_econtent_wrapper_when_theme_does_not_support_microformats2() { + // Ensure no theme support. + remove_theme_support( 'microformats2' ); + // Clear any cached detection. + delete_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ); + + $content = '

Test content

'; + $input = array( + 'properties' => array( + 'content' => array( $content ), + ), + ); + $post_content = \Micropub\Render::generate_post_content( $content, $input ); + + // Should have e-content wrapper. + $this->assertEquals( "
\n

Test content

\n
", $post_content ); + } + + function test_no_econtent_wrapper_with_cached_mf2_support() { + // Simulate cached detection of microformats2 support. + remove_theme_support( 'microformats2' ); + update_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION, 'yes' ); + + $content = '

Test content

'; + $input = array( + 'properties' => array( + 'content' => array( $content ), + ), + ); + $post_content = \Micropub\Render::generate_post_content( $content, $input ); + + // Should not have e-content wrapper due to cached support. + $this->assertEquals( '

Test content

', $post_content ); + + // Clean up. + delete_option( \Micropub\Micropub::MICROFORMATS2_SUPPORT_OPTION ); + } }