render_accordion_item_faq_schema(); if (empty(self::$faq_schema) || empty(self::$faq_entities)) { return; } $graph = array( '@context' => 'https://schema.org', '@type' => 'FAQPage', 'mainEntity' => array_values(self::$faq_entities), ); /** * The graph used to be concatenated by hand: a quote, backslash or line * break in an answer produced invalid JSON, and the answer markup was * only passed through strip_tags(), which keeps an allowed tag (, *

...) with all of its attributes intact. wp_json_encode() with * JSON_HEX_TAG writes every < and > as \u003C / \u003E, so nothing in an * answer can close the ' . "\n", esc_attr(self::$faq_schema), $json // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_json_encode() with JSON_HEX_TAG. ); } /** * Load faq schema */ public function render_accordion_item_faq_schema() { if (!is_singular()) { return; } $post = get_queried_object(); if (!($post instanceof WP_Post) || post_password_required($post)) { return; } if (function_exists('has_blocks') && has_blocks($post)) { $blocks = $this->eb_parse_blocks($post->post_content); if (!is_array($blocks) || empty($blocks)) { return; } foreach ($blocks as $block) { if (!is_object($block) && is_array($block) && isset($block['blockName'])) { if ('accordion-toggle/accordion-toggle' === $block['blockName']) { if (isset($block['attrs']) && is_array($block['attrs'])) { $attributes = $block['attrs']; if (!empty($attributes['blockId'])) { $unique_id = $attributes['blockId']; if (isset($attributes['faqSchema']) && $attributes['faqSchema']) { if (is_null(self::$faq_schema)) { self::$faq_schema = 'eb-faq-schema-graph eb-faq-schema-graph--eb-faq' . sanitize_html_class($unique_id); } } } } } // check for accordion-item blocks if ('accordion-toggle/accordion-item' === $block['blockName']) { if (isset($block['attrs']) && is_array($block['attrs'])) { if (isset($block['attrs']['faqSchema']) && $block['attrs']['faqSchema']) { $this->render_accordion_item_scheme_head($block); } } } if (isset($block['innerBlocks']) && !empty($block['innerBlocks']) && is_array($block['innerBlocks'])) { $this->recursive_inner_blocks($block['innerBlocks']); } } } } } /** * Recursively check inner blocks * * @param array $inner_blocks inner blocks array */ public function recursive_inner_blocks($inner_blocks) { foreach ($inner_blocks as $inner_block) { if (!is_object($inner_block) && is_array($inner_block) && isset($inner_block['blockName'])) { if ('accordion-toggle/accordion-toggle' === $inner_block['blockName']) { if (isset($inner_block['attrs']) && is_array($inner_block['attrs'])) { $attributes = $inner_block['attrs']; if (!empty($attributes['blockId'])) { $unique_id = $attributes['blockId']; if (isset($attributes['faqSchema']) && $attributes['faqSchema']) { if (is_null(self::$faq_schema)) { self::$faq_schema = 'eb-faq-schema-graph eb-faq-schema-graph--eb-faq' . sanitize_html_class($unique_id); } } } } } if ('accordion-toggle/accordion-item' === $inner_block['blockName']) { if (isset($inner_block['attrs']) && is_array($inner_block['attrs'])) { if (isset($inner_block['attrs']['faqSchema']) && $inner_block['attrs']['faqSchema']) { $this->render_accordion_item_scheme_head($inner_block); } } } if (isset($inner_block['innerBlocks']) && !empty($inner_block['innerBlocks']) && is_array($inner_block['innerBlocks'])) { $this->recursive_inner_blocks($inner_block['innerBlocks']); } } } } /** * Parse blocks of a page/post * * @param string $content content of a page/post */ public function eb_parse_blocks($content) { $parser_class = apply_filters('block_parser_class', 'WP_Block_Parser'); if (class_exists($parser_class)) { $parser = new $parser_class(); return $parser->parse($content); } elseif (function_exists('gutenberg_parse_blocks')) { return gutenberg_parse_blocks($content); } else { return false; } } /** * build FAQ schema * * @param array @block array of blocks */ public function render_accordion_item_scheme_head($block) { if (!is_null(self::$faq_schema)) { if (isset($block['innerBlocks']) && is_array($block['innerBlocks']) && !empty($block['innerBlocks'])) { $answer = ''; foreach ($block['innerBlocks'] as $inner_block) { if (!empty($inner_block['innerHTML'])) { $inner_html = trim(strip_tags($inner_block['innerHTML'], '