66
77class Feed_Shortcode {
88
9+ private static $ schema_scripts = array ();
10+
911 public function __construct (Feed_Deserializer $ feed_deserializer ) {
1012 $ this ->feed_deserializer = $ feed_deserializer ;
13+ // Hook into wp_head to output schemas
14+ add_action ('wp_head ' , array ($ this , 'output_schemas_to_head ' ), 1 );
1115 }
1216
1317 function custom_esc ($ str ) {
@@ -18,6 +22,53 @@ public function register() {
1822 add_shortcode ('opio_feed ' , array ($ this , 'init ' ));
1923 }
2024
25+ /**
26+ * Extract JSON-LD schema scripts from HTML content
27+ */
28+ private function extract_schema_from_html ($ html ) {
29+ $ schemas = array ();
30+
31+ // Pattern to match script tags with type="application/ld+json" and id="jsonldSchema"
32+ // Handles attributes in any order and with single or double quotes
33+ $ pattern = '/<script[^>]*(?:id=[" \']jsonldSchema[" \'][^>]*type=[" \']application\/ld\+json[" \']|type=[" \']application\/ld\+json[" \'][^>]*id=[" \']jsonldSchema[" \'])[^>]*>(.*?)<\/script>/is ' ;
34+
35+ if (preg_match_all ($ pattern , $ html , $ matches , PREG_SET_ORDER )) {
36+ foreach ($ matches as $ match ) {
37+ $ schemas [] = $ match [0 ]; // Full script tag
38+ }
39+ }
40+
41+ return $ schemas ;
42+ }
43+
44+ /**
45+ * Remove schema scripts from HTML content
46+ */
47+ private function remove_schema_from_html ($ html ) {
48+ // Remove script tags with id="jsonldSchema" and type="application/ld+json"
49+ // Handles attributes in any order and with single or double quotes
50+ $ pattern = '/<script[^>]*(?:id=[" \']jsonldSchema[" \'][^>]*type=[" \']application\/ld\+json[" \']|type=[" \']application\/ld\+json[" \'][^>]*id=[" \']jsonldSchema[" \'])[^>]*>.*?<\/script>/is ' ;
51+ $ html = preg_replace ($ pattern , '' , $ html );
52+
53+ // Also remove any stray head tags that might be in the content
54+ // Remove opening <head> tags
55+ $ html = preg_replace ('/<head[^>]*>/i ' , '' , $ html );
56+ // Remove closing </head> tags
57+ $ html = preg_replace ('/<\/head>/i ' , '' , $ html );
58+
59+ return $ html ;
60+ }
61+
62+ /**
63+ * Output all collected schemas to the head
64+ */
65+ public function output_schemas_to_head () {
66+ if (!empty (self ::$ schema_scripts )) {
67+ foreach (self ::$ schema_scripts as $ schema ) {
68+ echo $ schema . "\n" ;
69+ }
70+ }
71+ }
2172
2273 public function init ($ atts ) {
2374 if (get_option ('opio_active ' ) === '0 ' ) {
@@ -58,6 +109,15 @@ public function init($atts) {
58109 $ opio_handler = new Opio_Handler ($ biz_id , $ option , $ review_type , $ org_id );
59110 $ reviews = $ opio_handler ->get_business ();
60111
112+ // Extract schema scripts from the feed HTML
113+ $ schemas = $ this ->extract_schema_from_html ($ reviews );
114+ if (!empty ($ schemas )) {
115+ // Store schemas to be output in head
116+ self ::$ schema_scripts = array_merge (self ::$ schema_scripts , $ schemas );
117+ // Remove schemas from body content
118+ $ reviews = $ this ->remove_schema_from_html ($ reviews );
119+ }
120+
61121 // Wrap entire feed content with Nitropack exclusion wrapper
62122 echo '<div data-nitro-exclude="all" data-nitro-ignore="true" data-nitro-no-optimize="true" data-nitro-preserve-ws="true"> ' ;
63123
0 commit comments