class-schema-article.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Frontend\Schema
  6. */
  7. /**
  8. * Returns schema Article data.
  9. *
  10. * @since 10.2
  11. */
  12. class WPSEO_Schema_Article implements WPSEO_Graph_Piece {
  13. /**
  14. * The date helper.
  15. *
  16. * @var WPSEO_Date_Helper
  17. */
  18. protected $date;
  19. /**
  20. * A value object with context variables.
  21. *
  22. * @var WPSEO_Schema_Context
  23. */
  24. private $context;
  25. /**
  26. * WPSEO_Schema_Article constructor.
  27. *
  28. * @param WPSEO_Schema_Context $context A value object with context variables.
  29. */
  30. public function __construct( WPSEO_Schema_Context $context ) {
  31. $this->context = $context;
  32. $this->date = new WPSEO_Date_Helper();
  33. }
  34. /**
  35. * Determines whether or not a piece should be added to the graph.
  36. *
  37. * @return bool
  38. */
  39. public function is_needed() {
  40. if ( ! is_singular() ) {
  41. return false;
  42. }
  43. if ( $this->context->site_represents === false ) {
  44. return false;
  45. }
  46. return self::is_article_post_type( get_post_type() );
  47. }
  48. /**
  49. * Returns Article data.
  50. *
  51. * @return array $data Article data.
  52. */
  53. public function generate() {
  54. $post = get_post( $this->context->id );
  55. $comment_count = get_comment_count( $this->context->id );
  56. $data = [
  57. '@type' => 'Article',
  58. '@id' => $this->context->canonical . WPSEO_Schema_IDs::ARTICLE_HASH,
  59. 'isPartOf' => [ '@id' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH ],
  60. 'author' => [ '@id' => WPSEO_Schema_Utils::get_user_schema_id( $post->post_author, $this->context ) ],
  61. 'headline' => get_the_title(),
  62. 'datePublished' => $this->date->format( $post->post_date_gmt ),
  63. 'dateModified' => $this->date->format( $post->post_modified_gmt ),
  64. 'commentCount' => $comment_count['approved'],
  65. 'mainEntityOfPage' => [ '@id' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH ],
  66. ];
  67. if ( $this->context->site_represents_reference ) {
  68. $data['publisher'] = $this->context->site_represents_reference;
  69. }
  70. $data = $this->add_image( $data );
  71. $data = $this->add_keywords( $data );
  72. $data = $this->add_sections( $data );
  73. return $data;
  74. }
  75. /**
  76. * Determines whether a given post type should have Article schema.
  77. *
  78. * @param string $post_type Post type to check.
  79. *
  80. * @return bool True if it has article schema, false if not.
  81. */
  82. public static function is_article_post_type( $post_type = null ) {
  83. if ( is_null( $post_type ) ) {
  84. $post_type = get_post_type();
  85. }
  86. /**
  87. * Filter: 'wpseo_schema_article_post_types' - Allow changing for which post types we output Article schema.
  88. *
  89. * @api string[] $post_types The post types for which we output Article.
  90. */
  91. $post_types = apply_filters( 'wpseo_schema_article_post_types', [ 'post' ] );
  92. return in_array( $post_type, $post_types );
  93. }
  94. /**
  95. * Adds tags as keywords, if tags are assigned.
  96. *
  97. * @param array $data Article data.
  98. *
  99. * @return array $data Article data.
  100. */
  101. private function add_keywords( $data ) {
  102. /**
  103. * Filter: 'wpseo_schema_article_keywords_taxonomy' - Allow changing the taxonomy used to assign keywords to a post type Article data.
  104. *
  105. * @api string $taxonomy The chosen taxonomy.
  106. */
  107. $taxonomy = apply_filters( 'wpseo_schema_article_keywords_taxonomy', 'post_tag' );
  108. return $this->add_terms( $data, 'keywords', $taxonomy );
  109. }
  110. /**
  111. * Adds categories as sections, if categories are assigned.
  112. *
  113. * @param array $data Article data.
  114. *
  115. * @return array $data Article data.
  116. */
  117. private function add_sections( $data ) {
  118. /**
  119. * Filter: 'wpseo_schema_article_sections_taxonomy' - Allow changing the taxonomy used to assign keywords to a post type Article data.
  120. *
  121. * @api string $taxonomy The chosen taxonomy.
  122. */
  123. $taxonomy = apply_filters( 'wpseo_schema_article_sections_taxonomy', 'category' );
  124. return $this->add_terms( $data, 'articleSection', $taxonomy );
  125. }
  126. /**
  127. * Adds a term or multiple terms, comma separated, to a field.
  128. *
  129. * @param array $data Article data.
  130. * @param string $key The key in data to save the terms in.
  131. * @param string $taxonomy The taxonomy to retrieve the terms from.
  132. *
  133. * @return mixed array $data Article data.
  134. */
  135. private function add_terms( $data, $key, $taxonomy ) {
  136. $terms = get_the_terms( $this->context->id, $taxonomy );
  137. if ( is_array( $terms ) ) {
  138. $keywords = [];
  139. foreach ( $terms as $term ) {
  140. // We are checking against the WordPress internal translation.
  141. // @codingStandardsIgnoreLine
  142. if ( $term->name !== __( 'Uncategorized', 'default' ) ) {
  143. $keywords[] = $term->name;
  144. }
  145. }
  146. $data[ $key ] = implode( ',', $keywords );
  147. }
  148. return $data;
  149. }
  150. /**
  151. * Adds an image node if the post has a featured image.
  152. *
  153. * @param array $data The Article data.
  154. *
  155. * @return array $data The Article data.
  156. */
  157. private function add_image( $data ) {
  158. if ( $this->context->has_image ) {
  159. $data['image'] = [
  160. '@id' => $this->context->canonical . WPSEO_Schema_IDs::PRIMARY_IMAGE_HASH,
  161. ];
  162. }
  163. return $data;
  164. }
  165. }