fix: use string search instead of regex for nbsp publisher stripping

The previous regex approach with \x{00A0} wasn't reliably catching all
nbsp-separated publisher names (e.g., "UC Santa Cruz" on article 19).
Switched to strrpos-based string search which is simpler and avoids
potential PCRE/UTF-8 edge cases with multibyte characters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Terence Ong
2026-04-08 10:49:48 +07:00
parent d6b111ffc8
commit aeceab2ae4
2 changed files with 32 additions and 8 deletions

View File

@@ -248,10 +248,22 @@ class Peptide_News_Rest_API {
// Fallback 2: strip trailing nbsp-separated publisher names. // Fallback 2: strip trailing nbsp-separated publisher names.
// Google News RSS excerpts use double non-breaking space + publisher name // Google News RSS excerpts use double non-breaking space + publisher name
// when the source field doesn't match (e.g., source = "news.google.com"). // when the source field doesn't match (e.g., source = "news.google.com").
$nbsp_pattern = '/(?:\x{00A0}{1,2}|\s{2,})[A-Z][A-Za-z0-9\s.\'\-]{0,50}$/u'; // Uses string search instead of regex to avoid UTF-8/PCRE edge cases.
$candidate = preg_replace( $nbsp_pattern, '', $text ); $double_nbsp = $nbsp . $nbsp;
if ( $candidate !== $text && strlen( $candidate ) > strlen( $text ) * 0.4 ) { $nbsp_pos = strrpos( $text, $double_nbsp );
return rtrim( $candidate ); if ( false !== $nbsp_pos ) {
$after = substr( $text, $nbsp_pos + strlen( $double_nbsp ) );
} else {
$nbsp_pos = strrpos( $text, $nbsp );
if ( false !== $nbsp_pos ) {
$after = substr( $text, $nbsp_pos + strlen( $nbsp ) );
}
}
if ( false !== $nbsp_pos && $nbsp_pos > strlen( $text ) * 0.4 ) {
// Only strip if what follows looks like a publisher name (< 60 chars, starts uppercase).
if ( ! empty( $after ) && strlen( $after ) < 60 && preg_match( '/^[A-Z]/u', $after ) ) {
return rtrim( substr( $text, 0, $nbsp_pos ) );
}
} }
return $text; return $text;

View File

@@ -242,10 +242,22 @@ class Peptide_News_Rest_API {
// Fallback 2: strip trailing nbsp-separated publisher names. // Fallback 2: strip trailing nbsp-separated publisher names.
// Google News RSS excerpts use double non-breaking space + publisher name // Google News RSS excerpts use double non-breaking space + publisher name
// when the source field doesn't match (e.g., source = "news.google.com"). // when the source field doesn't match (e.g., source = "news.google.com").
$nbsp_pattern = '/(?:\x{00A0}{1,2}|\s{2,})[A-Z][A-Za-z0-9\s.\'\-]{0,50}$/u'; // Uses string search instead of regex to avoid UTF-8/PCRE edge cases.
$candidate = preg_replace( $nbsp_pattern, '', $text ); $double_nbsp = $nbsp . $nbsp;
if ( $candidate !== $text && strlen( $candidate ) > strlen( $text ) * 0.4 ) { $nbsp_pos = strrpos( $text, $double_nbsp );
return rtrim( $candidate ); if ( false !== $nbsp_pos ) {
$after = substr( $text, $nbsp_pos + strlen( $double_nbsp ) );
} else {
$nbsp_pos = strrpos( $text, $nbsp );
if ( false !== $nbsp_pos ) {
$after = substr( $text, $nbsp_pos + strlen( $nbsp ) );
}
}
if ( false !== $nbsp_pos && $nbsp_pos > strlen( $text ) * 0.4 ) {
// Only strip if what follows looks like a publisher name (< 60 chars, starts uppercase).
if ( ! empty( $after ) && strlen( $after ) < 60 && preg_match( '/^[A-Z]/u', $after ) ) {
return rtrim( substr( $text, 0, $nbsp_pos ) );
}
} }
return $text; return $text;