• '; /** * WPSEO_Schema_HowTo constructor. * * @param WPSEO_Schema_Context $context A value object with context variables. * * @codeCoverageIgnore */ public function __construct( WPSEO_Schema_Context $context ) { $this->counter = 0; $this->context = $context; add_filter( 'wpseo_schema_block_yoast/how-to-block', [ $this, 'render' ], 10, 2 ); } /** * Renders a list of questions, referencing them by ID. * * @return array $data Our Schema graph. */ public function generate() { return []; } /** * Renders the How-To block into our graph. * * @param array $graph Our Schema data. * @param array $block The How-To block content. * * @return mixed */ public function render( $graph, $block ) { $this->counter++; $data = [ '@type' => 'HowTo', '@id' => $this->context->canonical . '#howto-' . $this->counter, 'name' => $this->context->title, 'mainEntityOfPage' => [ '@id' => $this->get_main_schema_id() ], 'description' => '', ]; $json_description = strip_tags( $block['attrs']['jsonDescription'], '


        • ' ); if ( isset( $json_description ) ) { $data['description'] = $json_description; } $this->add_duration( $data, $block['attrs'] ); $this->add_steps( $data, $block['attrs']['steps'] ); $graph[] = $data; return $graph; } /** * Adds the duration of the task to the Schema. * * @param array $data Our How-To schema data. * @param array $attributes The block data attributes. * * @return array $data Our schema data. */ private function add_duration( &$data, $attributes ) { if ( ! empty( $attributes['hasDuration'] ) && $attributes['hasDuration'] ) { $days = empty( $attributes['days'] ) ? 0 : $attributes['days']; $hours = empty( $attributes['hours'] ) ? 0 : $attributes['hours']; $minutes = empty( $attributes['minutes'] ) ? 0 : $attributes['minutes']; if ( ( $days + $hours + $minutes ) > 0 ) { $data['totalTime'] = esc_attr( 'P' . $days . 'DT' . $hours . 'H' . $minutes . 'M' ); } } return $data; } /** * Determines whether we're part of an article or a webpage. * * @return string A reference URL. */ protected function get_main_schema_id() { if ( $this->context->site_represents !== false && WPSEO_Schema_Article::is_article_post_type() ) { return $this->context->canonical . WPSEO_Schema_IDs::ARTICLE_HASH; } return $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH; } /** * Determines whether or not a piece should be added to the graph. * * @return bool */ public function is_needed() { return $this->is_needed; } /** * Adds the steps to our How-To output. * * @param array $data Our How-To schema data. * @param array $steps Our How-To block's steps. */ private function add_steps( &$data, $steps ) { foreach ( $steps as $step ) { $schema_id = $this->context->canonical . '#' . esc_attr( $step['id'] ); $schema_step = [ '@type' => 'HowToStep', 'url' => $schema_id, ]; $json_text = strip_tags( $step['jsonText'], $this->allowed_json_text_tags ); $json_name = wp_strip_all_tags( $step['jsonName'] ); if ( empty( $json_name ) ) { if ( empty( $step['text'] ) ) { continue; } $schema_step['text'] = ''; $this->add_step_image( $schema_step, $step ); // If there is no text and no image, don't output the step. if ( empty( $json_text ) && empty( $schema_step['image'] ) ) { continue; } if ( ! empty( $json_text ) ) { $schema_step['text'] = $json_text; } } elseif ( empty( $json_text ) ) { $schema_step['text'] = $json_name; } else { $schema_step['name'] = $json_name; $this->add_step_description( $schema_step, $step ); $this->add_step_image( $schema_step, $step ); } $data['step'][] = $schema_step; } } /** * Checks if we have a step description, if we do, add it. * * @param array $schema_step Our Schema output for the Step. * @param array $step The step block data. */ private function add_step_description( &$schema_step, $step ) { $json_text = strip_tags( $step['jsonText'], $this->allowed_json_text_tags ); if ( empty( $json_text ) ) { return; } $schema_step['itemListElement'] = []; $schema_step['itemListElement'][] = [ '@type' => 'HowToDirection', 'text' => $json_text, ]; } /** * Checks if we have a step image, if we do, add it. * * @param array $schema_step Our Schema output for the Step. * @param array $step The step block data. */ private function add_step_image( &$schema_step, $step ) { foreach ( $step['text'] as $line ) { if ( is_array( $line ) && isset( $line['type'] ) && $line['type'] === 'img' ) { $schema_step['image'] = $this->get_image_schema( esc_url( $line['props']['src'] ) ); } } } /** * Generates the image schema from the attachment $url. * * @param string $url Attachment url. * * @return array Image schema. * * @codeCoverageIgnore */ protected function get_image_schema( $url ) { $image = new WPSEO_Schema_Image( $this->context->canonical . '#schema-image-' . md5( $url ) ); return $image->generate_from_url( $url ); } }