WPSEO_Twitter

This class handles the Twitter card functionality.

Defined (1)

The class is defined in the following location(s).

/frontend/class-twitter.php  
  1. class WPSEO_Twitter { 
  2.  
  3. /** 
  4. * @var object Instance of this class 
  5. */ 
  6. public static $instance; 
  7.  
  8. /** 
  9. * @var array Images 
  10. */ 
  11. private $images = array(); 
  12.  
  13. /** 
  14. * @var array Images 
  15. */ 
  16. public $shown_images = array(); 
  17.  
  18. /** 
  19. * @var array $options Holds the options for the Twitter Card functionality 
  20. */ 
  21. public $options; 
  22.  
  23. /** 
  24. * Will hold the Twitter card type being created 
  25. * @var string 
  26. */ 
  27. private $type; 
  28.  
  29. /** 
  30. * Class constructor 
  31. */ 
  32. public function __construct() { 
  33. $this->options = WPSEO_Options::get_option( 'wpseo_social' ); 
  34. $this->twitter(); 
  35.  
  36. /** 
  37. * Outputs the Twitter Card code on singular pages. 
  38. */ 
  39. public function twitter() { 
  40. wp_reset_query(); 
  41.  
  42. $this->type(); 
  43. $this->description(); 
  44. $this->title(); 
  45. $this->site_twitter(); 
  46. $this->image(); 
  47. if ( is_singular() ) { 
  48. $this->author(); 
  49.  
  50. /** 
  51. * Action: 'wpseo_twitter' - Hook to add all Yoast SEO Twitter output to so they're close together. 
  52. */ 
  53. do_action( 'wpseo_twitter' ); 
  54.  
  55. /** 
  56. * Display the Twitter card type. 
  57. * This defaults to summary but can be filtered using the <code>wpseo_twitter_card_type</code> filter. 
  58. * @link https://dev.twitter.com/docs/cards 
  59. */ 
  60. protected function type() { 
  61. $this->determine_card_type(); 
  62. $this->sanitize_card_type(); 
  63.  
  64. $this->output_metatag( 'card', $this->type ); 
  65.  
  66. /** 
  67. * Determines the twitter card type for the current page 
  68. */ 
  69. private function determine_card_type() { 
  70. $this->type = $this->options['twitter_card_type']; 
  71.  
  72. // TODO this should be reworked to use summary_large_image for any fitting image R. 
  73. if ( is_singular() && has_shortcode( $GLOBALS['post']->post_content, 'gallery' ) ) { 
  74.  
  75. $this->images = get_post_gallery_images(); 
  76.  
  77. if ( count( $this->images ) > 0 ) { 
  78. $this->type = 'summary_large_image'; 
  79.  
  80. /** 
  81. * Filter: 'wpseo_twitter_card_type' - Allow changing the Twitter Card type as output in the Twitter card by Yoast SEO 
  82. * @api string $unsigned The type string 
  83. */ 
  84. $this->type = apply_filters( 'wpseo_twitter_card_type', $this->type ); 
  85.  
  86. /** 
  87. * Determines whether the card type is of a type currently allowed by Twitter 
  88. * @link https://dev.twitter.com/cards/types 
  89. */ 
  90. private function sanitize_card_type() { 
  91. if ( ! in_array( $this->type, array( 
  92. 'summary',  
  93. 'summary_large_image',  
  94. 'app',  
  95. 'player',  
  96. ) ) 
  97. ) { 
  98. $this->type = 'summary'; 
  99.  
  100. /** 
  101. * Output the metatag 
  102. * @param string $name Tag name string. 
  103. * @param string $value Tag value string. 
  104. * @param bool $escaped Force escape flag. 
  105. */ 
  106. private function output_metatag( $name, $value, $escaped = false ) { 
  107.  
  108. // Escape the value if not escaped. 
  109. if ( false === $escaped ) { 
  110. $value = esc_attr( $value ); 
  111.  
  112. /** 
  113. * Filter: 'wpseo_twitter_metatag_key' - Make the Twitter metatag key filterable 
  114. * @api string $key The Twitter metatag key 
  115. */ 
  116. $metatag_key = apply_filters( 'wpseo_twitter_metatag_key', 'name' ); 
  117.  
  118. // Output meta. 
  119. echo '<meta ', esc_attr( $metatag_key ), '="twitter:', esc_attr( $name ), '" content="', $value, '" />', "\n"; 
  120.  
  121. /** 
  122. * Displays the description for Twitter. 
  123. * Only used when OpenGraph is inactive. 
  124. */ 
  125. protected function description() { 
  126. if ( is_singular() ) { 
  127. $meta_desc = $this->single_description(); 
  128. elseif ( WPSEO_Frontend::get_instance()->is_posts_page() ) { 
  129. $meta_desc = $this->single_description( get_option( 'page_for_posts' ) ); 
  130. elseif ( is_category() || is_tax() || is_tag() ) { 
  131. $meta_desc = $this->taxonomy_description(); 
  132. else { 
  133. $meta_desc = $this->fallback_description(); 
  134.  
  135. /** 
  136. * Filter: 'wpseo_twitter_description' - Allow changing the Twitter description as output in the Twitter card by Yoast SEO 
  137. * @api string $twitter The description string 
  138. */ 
  139. $meta_desc = apply_filters( 'wpseo_twitter_description', $meta_desc ); 
  140. if ( is_string( $meta_desc ) && $meta_desc !== '' ) { 
  141. $this->output_metatag( 'description', $meta_desc ); 
  142.  
  143. /** 
  144. * Returns the description for a singular page 
  145. * @param int $post_id Post ID. 
  146. * @return string 
  147. */ 
  148. private function single_description( $post_id = 0 ) { 
  149. $meta_desc = trim( WPSEO_Meta::get_value( 'twitter-description', $post_id ) ); 
  150.  
  151. if ( is_string( $meta_desc ) && '' !== $meta_desc ) { 
  152. return $meta_desc; 
  153.  
  154. $meta_desc = $this->fallback_description(); 
  155. if ( is_string( $meta_desc ) && '' !== $meta_desc ) { 
  156. return $meta_desc; 
  157.  
  158. return strip_tags( get_the_excerpt() ); 
  159.  
  160.  
  161. /** 
  162. * Getting the description for the taxonomy 
  163. * @return bool|mixed|string 
  164. */ 
  165. private function taxonomy_description() { 
  166. $meta_desc = WPSEO_Taxonomy_Meta::get_meta_without_term( 'twitter-description' ); 
  167.  
  168. if ( ! is_string( $meta_desc ) || $meta_desc === '' ) { 
  169. $meta_desc = $this->fallback_description(); 
  170.  
  171. if ( is_string( $meta_desc ) || $meta_desc !== '' ) { 
  172. return $meta_desc; 
  173.  
  174. return trim( strip_tags( term_description() ) ); 
  175.  
  176.  
  177. /** 
  178. * Returns a fallback description 
  179. * @return string 
  180. */ 
  181. private function fallback_description() { 
  182. return trim( WPSEO_Frontend::get_instance()->metadesc( false ) ); 
  183.  
  184. /** 
  185. * Displays the title for Twitter. 
  186. * Only used when OpenGraph is inactive. 
  187. */ 
  188. protected function title() { 
  189. if ( is_singular() ) { 
  190. $title = $this->single_title(); 
  191. elseif ( WPSEO_Frontend::get_instance()->is_posts_page() ) { 
  192. $title = $this->single_title( get_option( 'page_for_posts' ) ); 
  193. elseif ( is_category() || is_tax() || is_tag() ) { 
  194. $title = $this->taxonomy_title(); 
  195. else { 
  196. $title = $this->fallback_title(); 
  197.  
  198. /** 
  199. * Filter: 'wpseo_twitter_title' - Allow changing the Twitter title as output in the Twitter card by Yoast SEO 
  200. * @api string $twitter The title string 
  201. */ 
  202. $title = apply_filters( 'wpseo_twitter_title', $title ); 
  203. if ( is_string( $title ) && $title !== '' ) { 
  204. $this->output_metatag( 'title', $title ); 
  205.  
  206. /** 
  207. * Returns the Twitter title for a single post 
  208. * @param int $post_id Post ID. 
  209. * @return string 
  210. */ 
  211. private function single_title( $post_id = 0 ) { 
  212. $title = WPSEO_Meta::get_value( 'twitter-title', $post_id ); 
  213. if ( ! is_string( $title ) || $title === '' ) { 
  214. return $this->fallback_title(); 
  215.  
  216. return $title; 
  217.  
  218. /** 
  219. * Getting the title for the taxonomy 
  220. * @return bool|mixed|string 
  221. */ 
  222. private function taxonomy_title() { 
  223. $title = WPSEO_Taxonomy_Meta::get_meta_without_term( 'twitter-title' ); 
  224.  
  225. if ( ! is_string( $title ) || $title === '' ) { 
  226. return $this->fallback_title(); 
  227.  
  228. return $title; 
  229.  
  230. /** 
  231. * Returns the Twitter title for any page 
  232. * @return string 
  233. */ 
  234. private function fallback_title() { 
  235. return WPSEO_Frontend::get_instance()->title( '' ); 
  236.  
  237. /** 
  238. * Displays the Twitter account for the site. 
  239. */ 
  240. protected function site_twitter() { 
  241. /** 
  242. * Filter: 'wpseo_twitter_site' - Allow changing the Twitter site account as output in the Twitter card by Yoast SEO 
  243. * @api string $unsigned Twitter site account string 
  244. */ 
  245. $site = apply_filters( 'wpseo_twitter_site', $this->options['twitter_site'] ); 
  246. $site = $this->get_twitter_id( $site ); 
  247.  
  248. if ( is_string( $site ) && $site !== '' ) { 
  249. $this->output_metatag( 'site', '@' . $site ); 
  250.  
  251. /** 
  252. * Checks if the given id is actually an id or a url and if url, distills the id from it. 
  253. * Solves issues with filters returning urls and theme's/other plugins also adding a user meta 
  254. * twitter field which expects url rather than an id (which is what we expect). 
  255. * @param string $id Twitter ID or url. 
  256. * @return string|bool Twitter ID or false if it failed to get a valid Twitter ID. 
  257. */ 
  258. private function get_twitter_id( $id ) { 
  259. if ( preg_match( '`([A-Za-z0-9_]{1, 25})$`', $id, $match ) ) { 
  260. return $match[1]; 
  261. else { 
  262. return false; 
  263.  
  264. /** 
  265. * Displays the image for Twitter 
  266. * Only used when OpenGraph is inactive or Summary Large Image card is chosen. 
  267. */ 
  268. protected function image() { 
  269.  
  270. if ( is_category() || is_tax() || is_tag() ) { 
  271. $this->taxonomy_image_output(); 
  272. else { 
  273. $this->single_image_output(); 
  274.  
  275. if ( count( $this->shown_images ) === 0 && $this->options['og_default_image'] !== '' ) { 
  276. $this->image_output( $this->options['og_default_image'] ); 
  277.  
  278. /** 
  279. * Outputs the first image of a gallery. 
  280. */ 
  281. private function gallery_images_output() { 
  282.  
  283. $this->image_output( reset( $this->images ) ); 
  284.  
  285. /** 
  286. * @return bool 
  287. */ 
  288. private function taxonomy_image_output() { 
  289. foreach ( array( 'twitter-image', 'opengraph-image' ) as $tag ) { 
  290. $img = WPSEO_Taxonomy_Meta::get_meta_without_term( $tag ); 
  291. if ( $img !== '' ) { 
  292. $this->image_output( $img ); 
  293.  
  294. return true; 
  295.  
  296. return false; 
  297.  
  298. /** 
  299. * Takes care of image output when we only need to display a single image. 
  300. */ 
  301. private function single_image_output() { 
  302. if ( $this->homepage_image_output() ) { 
  303. return; 
  304. elseif ( $this->posts_page_image_output() ) { // Posts page, which won't be caught by is_singular() below. 
  305. return; 
  306.  
  307. if ( is_singular() ) { 
  308. if ( $this->image_from_meta_values_output() ) { 
  309. return; 
  310.  
  311. $post_id = get_the_ID(); 
  312.  
  313. if ( $this->image_of_attachment_page_output( $post_id ) ) { 
  314. return; 
  315. if ( $this->image_thumbnail_output() ) { 
  316. return; 
  317. if ( count( $this->images ) > 0 ) { 
  318. $this->gallery_images_output(); 
  319. return; 
  320. if ( $this->image_from_content_output() ) { 
  321. return; 
  322.  
  323. /** 
  324. * Show the front page image 
  325. * @return bool 
  326. */ 
  327. private function homepage_image_output() { 
  328. if ( is_front_page() ) { 
  329. if ( $this->options['og_frontpage_image'] !== '' ) { 
  330. $this->image_output( $this->options['og_frontpage_image'] ); 
  331.  
  332. return true; 
  333.  
  334. return false; 
  335.  
  336. /** 
  337. * Show the posts page image. 
  338. * @return bool 
  339. */ 
  340. private function posts_page_image_output() { 
  341.  
  342. if ( is_front_page() || ! is_home() ) { 
  343. return false; 
  344.  
  345. $post_id = get_option( 'page_for_posts' ); 
  346.  
  347. if ( $this->image_from_meta_values_output( $post_id ) ) { 
  348. return true; 
  349.  
  350. if ( $this->image_thumbnail_output( $post_id ) ) { 
  351. return true; 
  352.  
  353. return false; 
  354.  
  355. /** 
  356. * Outputs a Twitter image tag for a given image 
  357. * @param string $img The source URL to the image. 
  358. * @param boolean $tag Deprecated argument, previously used for gallery images. 
  359. * @return bool 
  360. */ 
  361. protected function image_output( $img, $tag = false ) { 
  362.  
  363. if ( $tag ) { 
  364. _deprecated_argument( __METHOD__, 'WPSEO 2.4' ); 
  365.  
  366. /** 
  367. * Filter: 'wpseo_twitter_image' - Allow changing the Twitter Card image 
  368. * @api string $img Image URL string 
  369. */ 
  370. $img = apply_filters( 'wpseo_twitter_image', $img ); 
  371.  
  372. if ( WPSEO_Utils::is_url_relative( $img ) === true && $img[0] === '/' ) { 
  373. $parsed_url = wp_parse_url( home_url() ); 
  374. $img = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $img; 
  375.  
  376. $escaped_img = esc_url( $img ); 
  377.  
  378. if ( in_array( $escaped_img, $this->shown_images ) ) { 
  379. return false; 
  380.  
  381. if ( is_string( $escaped_img ) && $escaped_img !== '' ) { 
  382. $this->output_metatag( 'image', $escaped_img, true ); 
  383. array_push( $this->shown_images, $escaped_img ); 
  384.  
  385. return true; 
  386.  
  387. return false; 
  388.  
  389. /** 
  390. * Retrieve images from the post meta values 
  391. * @param int $post_id Optional post ID to use. 
  392. * @return bool 
  393. */ 
  394. private function image_from_meta_values_output( $post_id = 0 ) { 
  395. foreach ( array( 'twitter-image', 'opengraph-image' ) as $tag ) { 
  396. $img = WPSEO_Meta::get_value( $tag, $post_id ); 
  397. if ( $img !== '' ) { 
  398. $this->image_output( $img ); 
  399.  
  400. return true; 
  401.  
  402. return false; 
  403.  
  404. /** 
  405. * Retrieve an attachment page's attachment 
  406. * @param string $attachment_id The ID of the attachment for which to retrieve the image. 
  407. * @return bool 
  408. */ 
  409. private function image_of_attachment_page_output( $attachment_id ) { 
  410. if ( get_post_type( $attachment_id ) === 'attachment' ) { 
  411. $mime_type = get_post_mime_type( $attachment_id ); 
  412. switch ( $mime_type ) { 
  413. case 'image/jpeg': 
  414. case 'image/png': 
  415. case 'image/gif': 
  416. $this->image_output( wp_get_attachment_url( $attachment_id ) ); 
  417. return true; 
  418.  
  419. return false; 
  420.  
  421. /** 
  422. * Retrieve the featured image 
  423. * @param int $post_id Optional post ID to use. 
  424. * @return bool 
  425. */ 
  426. private function image_thumbnail_output( $post_id = 0 ) { 
  427.  
  428. if ( empty( $post_id ) ) { 
  429. $post_id = get_the_ID(); 
  430.  
  431. if ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail( $post_id ) ) { 
  432. /** 
  433. * Filter: 'wpseo_twitter_image_size' - Allow changing the Twitter Card image size 
  434. * @api string $featured_img Image size string 
  435. */ 
  436. $featured_img = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), apply_filters( 'wpseo_twitter_image_size', 'full' ) ); 
  437.  
  438. if ( $featured_img ) { 
  439. $this->image_output( $featured_img[0] ); 
  440.  
  441. return true; 
  442.  
  443. return false; 
  444.  
  445. /** 
  446. * Retrieve the image from the content 
  447. * @return bool 
  448. */ 
  449. private function image_from_content_output() { 
  450. /** 
  451. * Filter: 'wpseo_pre_analysis_post_content' - Allow filtering the content before analysis 
  452. * @api string $post_content The Post content string 
  453. * @param object $post - The post object. 
  454. */ 
  455. global $post; 
  456. $content = apply_filters( 'wpseo_pre_analysis_post_content', $post->post_content, $post ); 
  457.  
  458. if ( preg_match_all( '`<img [^>]+>`', $content, $matches ) ) { 
  459. foreach ( $matches[0] as $img ) { 
  460. if ( preg_match( '`src=(["\'])(.*?)\1`', $img, $match ) ) { 
  461. $this->image_output( $match[2] ); 
  462.  
  463. return true; 
  464.  
  465. return false; 
  466.  
  467. /** 
  468. * Displays the authors Twitter account. 
  469. */ 
  470. protected function author() { 
  471. $twitter = ltrim( trim( get_the_author_meta( 'twitter', get_post()->post_author ) ), '@' ); 
  472. /** 
  473. * Filter: 'wpseo_twitter_creator_account' - Allow changing the Twitter account as output in the Twitter card by Yoast SEO 
  474. * @api string $twitter The twitter account name string 
  475. */ 
  476. $twitter = apply_filters( 'wpseo_twitter_creator_account', $twitter ); 
  477. $twitter = $this->get_twitter_id( $twitter ); 
  478.  
  479. if ( is_string( $twitter ) && $twitter !== '' ) { 
  480. $this->output_metatag( 'creator', '@' . $twitter ); 
  481. elseif ( $this->options['twitter_site'] !== '' ) { 
  482. if ( is_string( $this->options['twitter_site'] ) && $this->options['twitter_site'] !== '' ) { 
  483. $this->output_metatag( 'creator', '@' . $this->options['twitter_site'] ); 
  484.  
  485. /** 
  486. * Get the singleton instance of this class 
  487. * @return object 
  488. */ 
  489. public static function get_instance() { 
  490. if ( ! ( self::$instance instanceof self ) ) { 
  491. self::$instance = new self(); 
  492.  
  493. return self::$instance; 
  494.  
  495. /** 
  496. * Displays the domain tag for the site. 
  497. * @deprecated 3.0 
  498. * @codeCoverageIgnore 
  499. */ 
  500. protected function site_domain() { 
  501. _deprecated_function( __METHOD__, 'WPSEO 3.0' ); 
  502. } /** End of class */