Created
January 15, 2026 04:52
-
-
Save TanvirHasan19/51fa374e299b091399c137bfa2667e7c to your computer and use it in GitHub Desktop.
Fix HTML entities in XML feeds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Fix HTML entities in XML feeds | |
| */ | |
| add_filter( 'adt_product_feed_xml_attribute_handling', function( $handled, $product, $key, $value, $feed_config, $channel_attributes, $feed ) { | |
| if ( $handled || ! is_object( $product ) || ! is_object( $feed ) ) { | |
| return $handled; | |
| } | |
| $target_feed_id = 37281; | |
| $is_target_feed = false; | |
| if ( method_exists( $feed, 'get_id' ) ) { | |
| try { | |
| $feed_id = (int) $feed->get_id(); | |
| $is_target_feed = ( $feed_id === $target_feed_id ); | |
| } catch ( \Exception $e ) { | |
| // If get_id() fails, check by channel name instead | |
| if ( isset( $feed_config['name'] ) && ( $feed_config['name'] === 'Skroutz' || $feed_config['name'] === 'Custom Feed' ) ) { | |
| $is_target_feed = true; | |
| } | |
| } | |
| } else { | |
| // Fallback: check by channel name if get_id() method doesn't exist | |
| if ( isset( $feed_config['name'] ) && ( $feed_config['name'] === 'Skroutz' || $feed_config['name'] === 'Custom Feed' ) ) { | |
| $is_target_feed = true; | |
| } | |
| } | |
| if ( ! $is_target_feed ) { | |
| return $handled; | |
| } | |
| // Skip variations field (handled separately) | |
| if ( 'skroutz_variations' === $key ) { | |
| return $handled; | |
| } | |
| // Skip if field already exists in XML | |
| if ( isset( $product->$key ) ) { | |
| return $handled; | |
| } | |
| // Only process string values | |
| if ( ! is_string( $value ) && ! is_numeric( $value ) ) { | |
| return $handled; | |
| } | |
| // Convert to string | |
| $decoded = (string) $value; | |
| // Skip empty values | |
| if ( '' === trim( $decoded ) ) { | |
| return $handled; | |
| } | |
| try { | |
| // Decode HTML entities (handles double/triple encoding) | |
| $previous = ''; | |
| $iterations = 0; | |
| $max_iterations = 10; | |
| while ( $decoded !== $previous && $iterations < $max_iterations ) { | |
| $previous = $decoded; | |
| $decoded = html_entity_decode( $decoded, ENT_QUOTES | ENT_XML1 | ENT_HTML5, 'UTF-8' ); | |
| $iterations++; | |
| } | |
| // Validate UTF-8 and remove invalid XML characters | |
| $decoded = wp_check_invalid_utf8( $decoded, true ); | |
| if ( class_exists( '\AdTribes\PFP\Helpers\Sanitization' ) ) { | |
| $decoded = \AdTribes\PFP\Helpers\Sanitization::sanitize_utf8_for_xml( $decoded ); | |
| } | |
| // Sanitize element name to prevent XML injection | |
| $sanitized_key = preg_replace( '/[^a-zA-Z0-9_\-:]/', '', $key ); | |
| if ( '' === $sanitized_key ) { | |
| $sanitized_key = 'value'; | |
| } | |
| // Use DOMDocument to add the node with proper UTF-8 handling | |
| // This ensures plain UTF-8 text without HTML entities | |
| $dom = dom_import_simplexml( $product ); | |
| if ( $dom && $dom->ownerDocument ) { | |
| try { | |
| $child = $dom->ownerDocument->createElement( $sanitized_key ); | |
| if ( $child ) { | |
| $text_node = $dom->ownerDocument->createTextNode( $decoded ); | |
| if ( $text_node ) { | |
| $child->appendChild( $text_node ); | |
| $dom->appendChild( $child ); | |
| return true; // Successfully handled, skip default processing | |
| } | |
| } | |
| } catch ( \DOMException $e ) { | |
| // Log error but don't break feed generation | |
| if ( function_exists( 'wc_get_logger' ) ) { | |
| $logger = wc_get_logger(); | |
| $logger->warning( | |
| 'DOM operation failed in HTML entities fix: ' . $e->getMessage(), | |
| array( 'source' => 'woo-product-feed-pro', 'key' => $key ) | |
| ); | |
| } | |
| // Fall through to SimpleXML fallback | |
| } | |
| } | |
| // Fallback to SimpleXML if DOM operations fail | |
| // Note: This will still encode entities, but at least the feed won't break | |
| try { | |
| $fallback_value = htmlspecialchars( $decoded, ENT_XML1, 'UTF-8' ); | |
| $product->addChild( $sanitized_key, $fallback_value ); | |
| return true; // Handled, skip default processing | |
| } catch ( \Exception $e ) { | |
| // If even SimpleXML fails, log and let default handling proceed | |
| if ( function_exists( 'wc_get_logger' ) ) { | |
| $logger = wc_get_logger(); | |
| $logger->error( | |
| 'Failed to add XML element in HTML entities fix: ' . $e->getMessage(), | |
| array( 'source' => 'woo-product-feed-pro', 'key' => $key ) | |
| ); | |
| } | |
| // Return false to let default handling proceed | |
| return $handled; | |
| } | |
| } catch ( \Exception $e ) { | |
| // Catch any unexpected errors and log them | |
| if ( function_exists( 'wc_get_logger' ) ) { | |
| $logger = wc_get_logger(); | |
| $logger->error( | |
| 'Unexpected error in HTML entities fix: ' . $e->getMessage(), | |
| array( 'source' => 'woo-product-feed-pro', 'key' => $key ) | |
| ); | |
| } | |
| // Return false to let default handling proceed | |
| return $handled; | |
| } | |
| }, 9, 7 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment