class-schema-person.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Frontend\Schema
  6. */
  7. /**
  8. * Returns schema Person data.
  9. *
  10. * @since 10.2
  11. */
  12. class WPSEO_Schema_Person implements WPSEO_Graph_Piece {
  13. /**
  14. * A value object with context variables.
  15. *
  16. * @var WPSEO_Schema_Context
  17. */
  18. private $context;
  19. /**
  20. * Array of the social profiles we display for a Person.
  21. *
  22. * @var string[]
  23. */
  24. private $social_profiles = [
  25. 'facebook',
  26. 'instagram',
  27. 'linkedin',
  28. 'pinterest',
  29. 'twitter',
  30. 'myspace',
  31. 'youtube',
  32. 'soundcloud',
  33. 'tumblr',
  34. 'wikipedia',
  35. ];
  36. /**
  37. * The Schema type we use for this class.
  38. *
  39. * @var string[]
  40. */
  41. protected $type = [
  42. 'Person',
  43. 'Organization',
  44. ];
  45. /**
  46. * The hash used for images.
  47. *
  48. * @var string
  49. */
  50. protected $image_hash;
  51. /**
  52. * WPSEO_Schema_Person constructor.
  53. *
  54. * @param WPSEO_Schema_Context $context A value object with context variables.
  55. */
  56. public function __construct( WPSEO_Schema_Context $context ) {
  57. $this->image_hash = WPSEO_Schema_IDs::PERSON_LOGO_HASH;
  58. $this->context = $context;
  59. }
  60. /**
  61. * Determine whether we should return Person schema.
  62. *
  63. * @return bool
  64. */
  65. public function is_needed() {
  66. if ( ( $this->context->site_represents === 'person' ) || is_author() ) {
  67. return true;
  68. }
  69. return false;
  70. }
  71. /**
  72. * Returns Person Schema data.
  73. *
  74. * @return bool|array Person data on success, false on failure.
  75. */
  76. public function generate() {
  77. $user_id = $this->determine_user_id();
  78. if ( ! $user_id ) {
  79. return false;
  80. }
  81. $data = $this->build_person_data( $user_id );
  82. return $data;
  83. }
  84. /**
  85. * Determines a User ID for the Person data.
  86. *
  87. * @return bool|int User ID or false upon return.
  88. */
  89. protected function determine_user_id() {
  90. $user_id = $this->context->site_user_id;
  91. /**
  92. * Filter: 'wpseo_schema_person_user_id' - Allows filtering of user ID used for person output.
  93. *
  94. * @api int|bool $user_id The user ID currently determined.
  95. */
  96. return apply_filters( 'wpseo_schema_person_user_id', $user_id );
  97. }
  98. /**
  99. * Retrieve a list of social profile URLs for Person.
  100. *
  101. * @param int $user_id User ID.
  102. *
  103. * @return string[] $output A list of social profiles.
  104. */
  105. protected function get_social_profiles( $user_id ) {
  106. /**
  107. * Filter: 'wpseo_schema_person_social_profiles' - Allows filtering of social profiles per user.
  108. *
  109. * @param int $user_id The current user we're grabbing social profiles for.
  110. *
  111. * @api string[] $social_profiles The array of social profiles to retrieve. Each should be a user meta field
  112. * key. As they are retrieved using the WordPress function `get_the_author_meta`.
  113. */
  114. $social_profiles = apply_filters( 'wpseo_schema_person_social_profiles', $this->social_profiles, $user_id );
  115. $output = [];
  116. foreach ( $social_profiles as $profile ) {
  117. $social_url = $this->url_social_site( $profile, $user_id );
  118. if ( $social_url ) {
  119. $output[] = $social_url;
  120. }
  121. }
  122. return $output;
  123. }
  124. /**
  125. * Builds our array of Schema Person data for a given user ID.
  126. *
  127. * @param int $user_id The user ID to use.
  128. *
  129. * @return array An array of Schema Person data.
  130. */
  131. protected function build_person_data( $user_id ) {
  132. $user_data = get_userdata( $user_id );
  133. $data = [
  134. '@type' => $this->type,
  135. '@id' => WPSEO_Schema_Utils::get_user_schema_id( $user_id, $this->context ),
  136. 'name' => $user_data->display_name,
  137. ];
  138. $data = $this->add_image( $data, $user_data );
  139. if ( ! empty( $user_data->description ) ) {
  140. $data['description'] = $user_data->description;
  141. }
  142. $social_profiles = $this->get_social_profiles( $user_id );
  143. if ( is_array( $social_profiles ) ) {
  144. $data['sameAs'] = $social_profiles;
  145. }
  146. return $data;
  147. }
  148. /**
  149. * Returns an ImageObject for the persons avatar.
  150. *
  151. * @param array $data The Person schema.
  152. * @param \WP_User $user_data User data.
  153. *
  154. * @return array $data The Person schema.
  155. */
  156. protected function add_image( $data, $user_data ) {
  157. $schema_id = $this->context->site_url . $this->image_hash;
  158. $data = $this->set_image_from_options( $data, $schema_id );
  159. if ( ! isset( $data['image'] ) ) {
  160. $data = $this->set_image_from_avatar( $data, $user_data, $schema_id );
  161. }
  162. if ( is_array( $this->type ) && in_array( 'Organization', $this->type ) ) {
  163. $data['logo'] = [ '@id' => $schema_id ];
  164. }
  165. return $data;
  166. }
  167. /**
  168. * Generate the person image from our settings.
  169. *
  170. * @param array $data The Person schema.
  171. * @param string $schema_id The string used in the `@id` for the schema.
  172. *
  173. * @return array $data The Person schema.
  174. */
  175. private function set_image_from_options( $data, $schema_id ) {
  176. if ( $this->context->site_represents !== 'person' ) {
  177. return $data;
  178. }
  179. $person_logo_id = WPSEO_Image_Utils::get_attachment_id_from_settings( 'person_logo' );
  180. if ( $person_logo_id ) {
  181. $image = new WPSEO_Schema_Image( $schema_id );
  182. $data['image'] = $image->generate_from_attachment_id( $person_logo_id, $data['name'] );
  183. }
  184. return $data;
  185. }
  186. /**
  187. * Generate the person logo from gravatar.
  188. *
  189. * @param array $data The Person schema.
  190. * @param \WP_User $user_data User data.
  191. * @param string $schema_id The string used in the `@id` for the schema.
  192. *
  193. * @return array $data The Person schema.
  194. */
  195. private function set_image_from_avatar( $data, $user_data, $schema_id ) {
  196. // If we don't have an image in our settings, fall back to an avatar, if we're allowed to.
  197. $show_avatars = get_option( 'show_avatars' );
  198. if ( ! $show_avatars ) {
  199. return $data;
  200. }
  201. $url = get_avatar_url( $user_data->user_email );
  202. if ( empty( $url ) ) {
  203. return $data;
  204. }
  205. $schema_image = new WPSEO_Schema_Image( $schema_id );
  206. $data['image'] = $schema_image->simple_image_object( $url, $user_data->display_name );
  207. return $data;
  208. }
  209. /**
  210. * Returns an author's social site URL.
  211. *
  212. * @param string $social_site The social site to retrieve the URL for.
  213. * @param mixed $user_id The user ID to use function outside of the loop.
  214. *
  215. * @return string
  216. */
  217. protected function url_social_site( $social_site, $user_id = false ) {
  218. $url = get_the_author_meta( $social_site, $user_id );
  219. if ( ! empty( $url ) ) {
  220. switch ( $social_site ) {
  221. case 'twitter':
  222. $url = 'https://twitter.com/' . $url;
  223. break;
  224. }
  225. }
  226. return $url;
  227. }
  228. }