You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
5.6 KiB
PHTML
239 lines
5.6 KiB
PHTML
8 months ago
|
<?php
|
||
|
/**
|
||
|
* The FAQ Block
|
||
|
*
|
||
|
* @since 0.9.0
|
||
|
* @package RankMath
|
||
|
* @subpackage RankMath\Schema
|
||
|
* @author Rank Math <support@rankmath.com>
|
||
|
*/
|
||
|
|
||
|
namespace RankMath\Schema;
|
||
|
|
||
|
use WP_Block_Type_Registry;
|
||
|
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* Block_FAQ class.
|
||
|
*/
|
||
|
class Block_FAQ extends Block {
|
||
|
|
||
|
/**
|
||
|
* Block type name.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
private $block_type = 'rank-math/faq-block';
|
||
|
|
||
|
/**
|
||
|
* The single instance of the class.
|
||
|
*
|
||
|
* @var Block_FAQ
|
||
|
*/
|
||
|
protected static $instance = null;
|
||
|
|
||
|
/**
|
||
|
* Retrieve main Block_FAQ instance.
|
||
|
*
|
||
|
* Ensure only one instance is loaded or can be loaded.
|
||
|
*
|
||
|
* @return Block_FAQ
|
||
|
*/
|
||
|
public static function get() {
|
||
|
if ( is_null( self::$instance ) && ! ( self::$instance instanceof Block_FAQ ) ) {
|
||
|
self::$instance = new Block_FAQ();
|
||
|
}
|
||
|
|
||
|
return self::$instance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The Constructor.
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
|
||
|
if ( WP_Block_Type_Registry::get_instance()->is_registered( $this->block_type ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
register_block_type(
|
||
|
$this->block_type,
|
||
|
[
|
||
|
'render_callback' => [ $this, 'render' ],
|
||
|
'editor_style' => 'rank-math-block-admin',
|
||
|
'attributes' => [
|
||
|
'listStyle' => [
|
||
|
'type' => 'string',
|
||
|
'default' => '',
|
||
|
],
|
||
|
'titleWrapper' => [
|
||
|
'type' => 'string',
|
||
|
'default' => 'h3',
|
||
|
],
|
||
|
'sizeSlug' => [
|
||
|
'type' => 'string',
|
||
|
'default' => 'thumbnail',
|
||
|
],
|
||
|
'questions' => [
|
||
|
'type' => 'array',
|
||
|
'default' => [],
|
||
|
'items' => [ 'type' => 'object' ],
|
||
|
],
|
||
|
'listCssClasses' => [
|
||
|
'type' => 'string',
|
||
|
'default' => '',
|
||
|
],
|
||
|
'titleCssClasses' => [
|
||
|
'type' => 'string',
|
||
|
'default' => '',
|
||
|
],
|
||
|
'contentCssClasses' => [
|
||
|
'type' => 'string',
|
||
|
'default' => '',
|
||
|
],
|
||
|
'textAlign' => [
|
||
|
'type' => 'string',
|
||
|
'default' => 'left',
|
||
|
],
|
||
|
],
|
||
|
]
|
||
|
);
|
||
|
|
||
|
add_filter( 'rank_math/schema/block/faq-block', [ $this, 'add_graph' ], 10, 2 );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add FAQ schema data in JSON-LD array.
|
||
|
*
|
||
|
* @param array $data Array of JSON-LD data.
|
||
|
* @param array $block JsonLD Instance.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function add_graph( $data, $block ) {
|
||
|
// Early bail.
|
||
|
if ( ! $this->has_questions( $block['attrs'] ) ) {
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
if ( ! isset( $data['faqs'] ) ) {
|
||
|
$data['faqs'] = [
|
||
|
'@type' => 'FAQPage',
|
||
|
'mainEntity' => [],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$permalink = get_permalink() . '#';
|
||
|
foreach ( $block['attrs']['questions'] as $question ) {
|
||
|
if ( empty( $question['title'] ) || empty( $question['content'] ) || empty( $question['visible'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$question['title'] = do_shortcode( $question['title'] );
|
||
|
$question['content'] = do_shortcode( $question['content'] );
|
||
|
|
||
|
if ( empty( $question['id'] ) ) {
|
||
|
$question['id'] = 'rm-faq-' . md5( $question['title'] );
|
||
|
}
|
||
|
|
||
|
$data['faqs']['mainEntity'][] = [
|
||
|
'@type' => 'Question',
|
||
|
'url' => $permalink . $question['id'],
|
||
|
'name' => wp_strip_all_tags( $question['title'] ),
|
||
|
'acceptedAnswer' => [
|
||
|
'@type' => 'Answer',
|
||
|
'text' => $this->clean_text( $question['content'] ),
|
||
|
],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render block content.
|
||
|
*
|
||
|
* @param array $attributes Array of atributes.
|
||
|
* @return string
|
||
|
*/
|
||
|
public static function markup( $attributes = [] ) {
|
||
|
$list_tag = self::get()->get_list_style( $attributes['listStyle'] );
|
||
|
$item_tag = self::get()->get_list_item_style( $attributes['listStyle'] );
|
||
|
$class = 'rank-math-block';
|
||
|
if ( ! empty( $attributes['className'] ) ) {
|
||
|
$class .= ' ' . esc_attr( $attributes['className'] );
|
||
|
}
|
||
|
|
||
|
// HTML.
|
||
|
$out = [];
|
||
|
$out[] = sprintf( '<div id="rank-math-faq" class="%1$s"%2$s>', $class, self::get()->get_styles( $attributes ) );
|
||
|
$out[] = sprintf( '<%1$s class="rank-math-list %2$s">', $list_tag, esc_attr( $attributes['listCssClasses'] ) );
|
||
|
|
||
|
// Questions.
|
||
|
foreach ( $attributes['questions'] as $question ) {
|
||
|
if ( empty( $question['title'] ) || empty( $question['content'] ) || empty( $question['visible'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( empty( $question['id'] ) ) {
|
||
|
$question['id'] = 'rm-faq-' . md5( $question['title'] );
|
||
|
}
|
||
|
|
||
|
$out[] = sprintf( '<%1$s id="%2$s" class="rank-math-list-item">', $item_tag, $question['id'] );
|
||
|
|
||
|
$out[] = sprintf(
|
||
|
'<%1$s class="rank-math-question %2$s">%3$s</%1$s>',
|
||
|
apply_filters( 'rank_math/blocks/faq/title_wrapper', esc_attr( $attributes['titleWrapper'] ) ),
|
||
|
esc_attr( $attributes['titleCssClasses'] ),
|
||
|
wp_kses_post( $question['title'] )
|
||
|
);
|
||
|
|
||
|
$out[] = '<div class="rank-math-answer ' . esc_attr( $attributes['contentCssClasses'] ) . '">';
|
||
|
|
||
|
if ( ! empty( $question['imageUrl'] ) ) {
|
||
|
$out[] = '<img src="' . esc_url( $question['imageUrl'] ) . '" />';
|
||
|
} else {
|
||
|
$out[] = self::get()->get_image( $question, $attributes['sizeSlug'] );
|
||
|
}
|
||
|
|
||
|
$out[] = self::get()->normalize_text( $question['content'], 'faq' );
|
||
|
$out[] = '</div>';
|
||
|
|
||
|
$out[] = sprintf( '</%1$s>', $item_tag );
|
||
|
}
|
||
|
|
||
|
$out[] = sprintf( '</%1$s>', $list_tag );
|
||
|
$out[] = '</div>';
|
||
|
|
||
|
return join( "\n", $out );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render block content
|
||
|
*
|
||
|
* @param array $attributes Array of atributes.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function render( $attributes ) {
|
||
|
// Early bail.
|
||
|
if ( ! $this->has_questions( $attributes ) ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return self::markup( $attributes );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if FAQ block has questions data.
|
||
|
*
|
||
|
* @param array $attributes Array of attributes.
|
||
|
*
|
||
|
* @return boolean
|
||
|
*/
|
||
|
private function has_questions( $attributes ) {
|
||
|
return ! isset( $attributes['questions'] ) || empty( $attributes['questions'] ) ? false : true;
|
||
|
}
|
||
|
}
|