Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions includes/create-theme/theme-patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ public static function strip_php_tags( $content ) {
return $content;
}

// Strip ANY `<?` open tag. On hosts with `short_open_tag=1`, PHP parses
// `<?` followed by `$`, `(`, `"`, `//`, `/*`, `;`, or `xml` as an open
// tag — preserving any of them would either re-execute as PHP or
// produce a fatal parse error when the exported `.php` file is loaded.
// Block patterns are HTML/block markup, so there's no legitimate
// `<?xml` content to preserve.
$content = preg_replace( '/<\?/', '', $content );

// Strip legacy `<script language="php">…</script>` blocks. PHP 7+
// removed this parser, but custom SAPIs / polyfills could still
// honour it. Match the entire block (opening tag → closing tag,
// inclusive of inner content).
$content = preg_replace( '#<script\s+language\s*=\s*["\']?php["\']?[^>]*>.*?</script>#is', '', $content );
// Repeat until stable because removing one sequence can bring adjacent
// fragments together and expose another sequence for the next pass.
do {
$previous_content = $content;

// Strip ANY `<?` open tag. On hosts with `short_open_tag=1`, PHP parses
// `<?` followed by `$`, `(`, `"`, `//`, `/*`, `;`, or `xml` as an open
// tag. Block patterns are HTML/block markup, so there's no legitimate
// `<?xml` content to preserve.
$content = preg_replace( '/<\?/', '', $content );

// Strip legacy `<script language="php">…</script>` blocks. Match the
// entire block, including its inner content.
$content = preg_replace( '#<script\s+language\s*=\s*["\']?php["\']?[^>]*>.*?</script>#is', '', $content );
} while ( $content !== $previous_content );

return $content;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/test-theme-patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,24 @@ public function test_pattern_from_wp_block_strips_script_language_php() {
}
}

public function test_pattern_from_wp_block_stabilizes_overlapping_open_tags() {
$post = $this->make_wp_block_post( '<p>safe</p><<??template data' );
$pattern = CBT_Theme_Patterns::pattern_from_wp_block( $post );
$body = substr( $pattern->content, strpos( $pattern->content, '?>' ) + 2 );

$this->assertStringNotContainsString( '<?', $body );
$this->assertStringContainsString( '<p>safe</p>', $body );
}

public function test_pattern_from_wp_block_stabilizes_after_legacy_script_removal() {
$post = $this->make_wp_block_post( '<p>safe</p><<script language="php">bridge</script>?template data' );
$pattern = CBT_Theme_Patterns::pattern_from_wp_block( $post );
$body = substr( $pattern->content, strpos( $pattern->content, '?>' ) + 2 );

$this->assertStringNotContainsString( '<?', $body );
$this->assertStringContainsString( '<p>safe</p>', $body );
}

public function test_pattern_from_wp_block_preserves_unrelated_script_tags() {
// `<script type="application/json">` and similar non-PHP scripts are legitimate
// in block markup and MUST NOT be stripped.
Expand Down
Loading