diff --git a/lib/discourse-publish.php b/lib/discourse-publish.php index c8c242a3..6370819a 100644 --- a/lib/discourse-publish.php +++ b/lib/discourse-publish.php @@ -839,14 +839,14 @@ protected function get_excluded_tag_slugs() { } /** - * Strip html tags from titles before passing them to Discourse. + * Strip html tags and convert HTML entities before passing them to Discourse. * * @param string $title The title of the post. * * @return string */ protected function sanitize_title( $title ) { - return wp_strip_all_tags( $title ); + return wp_specialchars_decode( wp_strip_all_tags( $title ) ); } /** diff --git a/tests/phpunit/test-discourse-publish.php b/tests/phpunit/test-discourse-publish.php index 09b00c8e..14722a48 100644 --- a/tests/phpunit/test-discourse-publish.php +++ b/tests/phpunit/test-discourse-publish.php @@ -854,6 +854,46 @@ public function test_force_publish_max_age_prevents_older_posts_from_being_publi wp_delete_post( $post_id ); } + /** + * Test that HTML entities are converted to their special characters. + */ + public function test_conversion_of_html_entities_in_title() { + $title_with_entities = 'Title with &'; + $title_with_decoded_entities = 'Title with &'; + self::$post_atts['post_title'] = $title_with_entities; + + $response = $this->build_response( 'success' ); + $response['body'] = $this->response_body_json( 'post_create' ); + + add_filter( + 'pre_http_request', + function( $prempt, $args, $url ) use ( $response, $title_with_decoded_entities ) { + $body = json_decode( $args['body'] ); + + if ( $body->title !== $title_with_decoded_entities ) { + return new \WP_Error( 'http_request_failed', 'Failed to decode title' ); + } else { + return $response; + } + }, + 10, + 3 + ); + + // Setup post. + $post_id = wp_insert_post( self::$post_atts, false, false ); + + // Run the publication. + $post = get_post( $post_id ); + $this->publish->publish_post_after_save( $post_id, $post ); + + // Ensure publication occurs. + $this->assertEquals( get_post_meta( $post_id, 'wpdc_publishing_response', true ), 'success' ); + + // Cleanup. + wp_delete_post( $post_id ); + } + /** * Posts can only be published via XMLRPC by hooking into the wp_discourse_before_xmlrpc_publish filter with a function * that returns `true`.