| @@ -32,12 +32,9 @@ | ||
| 32 | 32 | * |
| 33 | 33 | * @param Helpers_Surface $helpers The helpers surface. |
| 34 | 34 | * @param Replace_Vars_Helper $schema_replace_vars_helper The replace vars helper. |
| 35 | 35 | */ |
| 36 | - public function __construct( | |
| 37 | - Helpers_Surface $helpers, | |
| 38 | - Replace_Vars_Helper $schema_replace_vars_helper | |
| 39 | - ) { | |
| 36 | + public function __construct( Helpers_Surface $helpers, Replace_Vars_Helper $schema_replace_vars_helper ) { | |
| 40 | 37 | $this->helpers = $helpers; |
| 41 | 38 | $this->schema_replace_vars_helper = $schema_replace_vars_helper; |
| 42 | 39 | } |
| 43 | 40 | |
| @@ -56,9 +53,8 @@ | ||
| 56 | 53 | foreach ( \array_keys( $context->blocks ) as $block_type ) { |
| 57 | 54 | /** |
| 58 | 55 | * Filter: 'wpseo_pre_schema_block_type_<block-type>' - Allows hooking things to change graph output based on the blocks on the page. |
| 59 | 56 | * |
| 60 | - * @param string $block_type The block type. | |
| 61 | 57 | * @param WP_Block_Parser_Block[] $blocks All the blocks of this block type. |
| 62 | 58 | * @param Meta_Tags_Context $context A value object with context variables. |
| 63 | 59 | */ |
| 64 | 60 | \do_action( 'wpseo_pre_schema_block_type_' . $block_type, $context->blocks[ $block_type ], $context ); |
| @@ -74,8 +70,9 @@ | ||
| 74 | 70 | |
| 75 | 71 | $pieces_to_generate = $this->filter_graph_pieces_to_generate( $pieces ); |
| 76 | 72 | $graph = $this->generate_graph( $pieces_to_generate, $context ); |
| 77 | 73 | $graph = $this->add_schema_blocks_graph_pieces( $graph, $context ); |
| 74 | + $graph = $this->finalize_graph( $graph, $context ); | |
| 78 | 75 | |
| 79 | 76 | return [ |
| 80 | 77 | '@context' => 'https://schema.org', |
| 81 | 78 | '@graph' => $graph, |
| @@ -93,9 +90,9 @@ | ||
| 93 | 90 | protected function filter_graph_pieces_to_generate( $graph_pieces ) { |
| 94 | 91 | $pieces_to_generate = []; |
| 95 | 92 | foreach ( $graph_pieces as $piece ) { |
| 96 | 93 | $identifier = \strtolower( \str_replace( 'Yoast\WP\SEO\Generators\Schema\\', '', \get_class( $piece ) ) ); |
| 97 | - if ( \property_exists( $piece, 'identifier' ) ) { | |
| 94 | + if ( isset( $piece->identifier ) ) { | |
| 98 | 95 | $identifier = $piece->identifier; |
| 99 | 96 | } |
| 100 | 97 | |
| 101 | 98 | /** |
| @@ -100,9 +97,9 @@ | ||
| 100 | 97 | |
| 101 | 98 | /** |
| 102 | 99 | * Filter: 'wpseo_schema_needs_<identifier>' - Allows changing which graph pieces we output. |
| 103 | 100 | * |
| 104 | - * @api bool $is_needed Whether or not to show a graph piece. | |
| 101 | + * @param bool $is_needed Whether or not to show a graph piece. | |
| 105 | 102 | */ |
| 106 | 103 | $is_needed = \apply_filters( 'wpseo_schema_needs_' . $identifier, $piece->is_needed() ); |
| 107 | 104 | if ( ! $is_needed ) { |
| 108 | 105 | continue; |
| @@ -139,12 +136,11 @@ | ||
| 139 | 136 | /** |
| 140 | 137 | * Filter: 'wpseo_schema_<identifier>' - Allows changing graph piece output. |
| 141 | 138 | * This filter can be called with either an identifier or a block type (see `add_schema_blocks_graph_pieces()`). |
| 142 | 139 | * |
| 143 | - * @api array $graph_piece The graph piece to filter. | |
| 144 | - * | |
| 145 | - * @param Meta_Tags_Context $context A value object with context variables. | |
| 146 | - * @param Abstract_Schema_Piece $graph_piece_generator A value object with context variables. | |
| 140 | + * @param array $graph_piece The graph piece to filter. | |
| 141 | + * @param Meta_Tags_Context $context A value object with context variables. | |
| 142 | + * @param Abstract_Schema_Piece $graph_piece_generator A value object with context variables. | |
| 147 | 143 | * @param Abstract_Schema_Piece[] $graph_piece_generators A value object with context variables. |
| 148 | 144 | */ |
| 149 | 145 | $graph_piece = \apply_filters( 'wpseo_schema_' . $identifier, $graph_piece, $context, $graph_piece_generator, $graph_piece_generators ); |
| 150 | 146 | $graph_piece = $this->type_filter( $graph_piece, $identifier, $context, $graph_piece_generator, $graph_piece_generators ); |
| @@ -155,8 +151,16 @@ | ||
| 155 | 151 | } |
| 156 | 152 | } |
| 157 | 153 | } |
| 158 | 154 | |
| 155 | + /** | |
| 156 | + * Filter: 'wpseo_schema_graph' - Allows changing graph output. | |
| 157 | + * | |
| 158 | + * @param array $graph The graph to filter. | |
| 159 | + * @param Meta_Tags_Context $context A value object with context variables. | |
| 160 | + */ | |
| 161 | + $graph = \apply_filters( 'wpseo_schema_graph', $graph, $context ); | |
| 162 | + | |
| 159 | 163 | return $graph; |
| 160 | 164 | } |
| 161 | 165 | |
| 162 | 166 | /** |
| @@ -173,8 +177,9 @@ | ||
| 173 | 177 | protected function add_schema_blocks_graph_pieces( $graph, $context ) { |
| 174 | 178 | foreach ( $context->blocks as $block_type => $blocks ) { |
| 175 | 179 | foreach ( $blocks as $block ) { |
| 176 | 180 | $block_type = \strtolower( $block['blockName'] ); |
| 181 | + | |
| 177 | 182 | /** |
| 178 | 183 | * Filter: 'wpseo_schema_block_<block-type>'. |
| 179 | 184 | * This filter is documented in the `generate_graph()` function in this class. |
| 180 | 185 | */ |
| @@ -189,8 +194,64 @@ | ||
| 189 | 194 | return $graph; |
| 190 | 195 | } |
| 191 | 196 | |
| 192 | 197 | /** |
| 198 | + * Finalizes the schema graph after all filtering is done. | |
| 199 | + * | |
| 200 | + * @param array $graph The current schema graph. | |
| 201 | + * @param Meta_Tags_Context $context The meta tags context. | |
| 202 | + * | |
| 203 | + * @return array The schema graph. | |
| 204 | + */ | |
| 205 | + protected function finalize_graph( $graph, $context ) { | |
| 206 | + $graph = $this->remove_empty_breadcrumb( $graph, $context ); | |
| 207 | + | |
| 208 | + return $graph; | |
| 209 | + } | |
| 210 | + | |
| 211 | + /** | |
| 212 | + * Removes the breadcrumb schema if empty. | |
| 213 | + * | |
| 214 | + * @param array $graph The current schema graph. | |
| 215 | + * @param Meta_Tags_Context $context The meta tags context. | |
| 216 | + * | |
| 217 | + * @return array The schema graph with empty breadcrumbs taken out. | |
| 218 | + */ | |
| 219 | + protected function remove_empty_breadcrumb( $graph, $context ) { | |
| 220 | + if ( $this->helpers->current_page->is_home_static_page() || $this->helpers->current_page->is_home_posts_page() ) { | |
| 221 | + return $graph; | |
| 222 | + } | |
| 223 | + | |
| 224 | + // Remove the breadcrumb piece, if it's empty. | |
| 225 | + $index_to_remove = 0; | |
| 226 | + foreach ( $graph as $key => $piece ) { | |
| 227 | + if ( \in_array( 'BreadcrumbList', $this->get_type_from_piece( $piece ), true ) ) { | |
| 228 | + if ( isset( $piece['itemListElement'] ) && \is_array( $piece['itemListElement'] ) && \count( $piece['itemListElement'] ) === 1 ) { | |
| 229 | + $index_to_remove = $key; | |
| 230 | + break; | |
| 231 | + } | |
| 232 | + } | |
| 233 | + } | |
| 234 | + | |
| 235 | + // If the breadcrumb piece has been removed, we should remove its reference from the WebPage node. | |
| 236 | + if ( $index_to_remove !== 0 ) { | |
| 237 | + \array_splice( $graph, $index_to_remove, 1 ); | |
| 238 | + | |
| 239 | + // Get the type of the WebPage node. | |
| 240 | + $webpage_types = \is_array( $context->schema_page_type ) ? $context->schema_page_type : [ $context->schema_page_type ]; | |
| 241 | + | |
| 242 | + foreach ( $graph as $key => $piece ) { | |
| 243 | + if ( ! empty( \array_intersect( $webpage_types, $this->get_type_from_piece( $piece ) ) ) && isset( $piece['breadcrumb'] ) ) { | |
| 244 | + unset( $piece['breadcrumb'] ); | |
| 245 | + $graph[ $key ] = $piece; | |
| 246 | + } | |
| 247 | + } | |
| 248 | + } | |
| 249 | + | |
| 250 | + return $graph; | |
| 251 | + } | |
| 252 | + | |
| 253 | + /** | |
| 193 | 254 | * Adapts the WebPage graph piece for password-protected posts. |
| 194 | 255 | * |
| 195 | 256 | * It should only have certain whitelisted properties. |
| 196 | 257 | * The type should always be WebPage. |
| @@ -210,9 +271,9 @@ | ||
| 210 | 271 | 'inLanguage', |
| 211 | 272 | 'datePublished', |
| 212 | 273 | 'dateModified', |
| 213 | 274 | 'breadcrumb', |
| 214 | - ] | |
| 275 | + ], | |
| 215 | 276 | ); |
| 216 | 277 | |
| 217 | 278 | $graph_piece = \array_intersect_key( $graph_piece, $properties_to_show ); |
| 218 | 279 | $graph_piece['@type'] = 'WebPage'; |
| @@ -229,11 +290,11 @@ | ||
| 229 | 290 | */ |
| 230 | 291 | protected function get_graph_pieces( $context ) { |
| 231 | 292 | if ( $context->indexable->object_type === 'post' && \post_password_required( $context->post ) ) { |
| 232 | 293 | $schema_pieces = [ |
| 294 | + new Schema\WebPage(), | |
| 295 | + new Schema\Website(), | |
| 233 | 296 | new Schema\Organization(), |
| 234 | - new Schema\Website(), | |
| 235 | - new Schema\WebPage(), | |
| 236 | 297 | ]; |
| 237 | 298 | |
| 238 | 299 | \add_filter( 'wpseo_schema_webpage', [ $this, 'protected_webpage_schema' ], 1 ); |
| 239 | 300 | } |
| @@ -238,15 +299,15 @@ | ||
| 238 | 299 | \add_filter( 'wpseo_schema_webpage', [ $this, 'protected_webpage_schema' ], 1 ); |
| 239 | 300 | } |
| 240 | 301 | else { |
| 241 | 302 | $schema_pieces = [ |
| 303 | + new Schema\Article(), | |
| 304 | + new Schema\WebPage(), | |
| 305 | + new Schema\Main_Image(), | |
| 306 | + new Schema\Breadcrumb(), | |
| 307 | + new Schema\Website(), | |
| 242 | 308 | new Schema\Organization(), |
| 243 | 309 | new Schema\Person(), |
| 244 | - new Schema\Website(), | |
| 245 | - new Schema\Main_Image(), | |
| 246 | - new Schema\WebPage(), | |
| 247 | - new Schema\Breadcrumb(), | |
| 248 | - new Schema\Article(), | |
| 249 | 310 | new Schema\Author(), |
| 250 | 311 | new Schema\FAQ(), |
| 251 | 312 | new Schema\HowTo(), |
| 252 | 313 | ]; |
| @@ -254,11 +315,10 @@ | ||
| 254 | 315 | |
| 255 | 316 | /** |
| 256 | 317 | * Filter: 'wpseo_schema_graph_pieces' - Allows adding pieces to the graph. |
| 257 | 318 | * |
| 319 | + * @param array $pieces The schema pieces. | |
| 258 | 320 | * @param Meta_Tags_Context $context An object with context variables. |
| 259 | - * | |
| 260 | - * @api array $pieces The schema pieces. | |
| 261 | 321 | */ |
| 262 | 322 | return \apply_filters( 'wpseo_schema_graph_pieces', $schema_pieces, $context ); |
| 263 | 323 | } |
| 264 | 324 | |
| @@ -285,12 +345,11 @@ | ||
| 285 | 345 | if ( $type && $type !== $identifier ) { |
| 286 | 346 | /** |
| 287 | 347 | * Filter: 'wpseo_schema_<type>' - Allows changing graph piece output by @type. |
| 288 | 348 | * |
| 289 | - * @api array $graph_piece The graph piece to filter. | |
| 290 | - * | |
| 291 | - * @param Meta_Tags_Context $context A value object with context variables. | |
| 292 | - * @param Abstract_Schema_Piece $graph_piece_generator A value object with context variables. | |
| 349 | + * @param array $graph_piece The graph piece to filter. | |
| 350 | + * @param Meta_Tags_Context $context A value object with context variables. | |
| 351 | + * @param Abstract_Schema_Piece $graph_piece_generator A value object with context variables. | |
| 293 | 352 | * @param Abstract_Schema_Piece[] $graph_piece_generators A value object with context variables. |
| 294 | 353 | */ |
| 295 | 354 | $graph_piece = \apply_filters( 'wpseo_schema_' . $type, $graph_piece, $context, $graph_piece_generator, $graph_piece_generators ); |
| 296 | 355 | } |