class-social-admin.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Admin
  6. */
  7. /**
  8. * This class adds the Social tab to the Yoast SEO metabox and makes sure the settings are saved.
  9. */
  10. class WPSEO_Social_Admin extends WPSEO_Metabox {
  11. /**
  12. * Class constructor.
  13. */
  14. public function __construct() {
  15. self::translate_meta_boxes();
  16. add_filter( 'wpseo_save_metaboxes', [ $this, 'save_meta_boxes' ], 10, 1 );
  17. add_action( 'wpseo_save_compare_data', [ $this, 'og_data_compare' ], 10, 1 );
  18. }
  19. /**
  20. * Translate text strings for use in the meta box.
  21. *
  22. * IMPORTANT: if you want to add a new string (option) somewhere, make sure you add that array key to
  23. * the main meta box definition array in the class WPSEO_Meta() as well!!!!
  24. */
  25. public static function translate_meta_boxes() {
  26. /* translators: %s expands to the social network's name. */
  27. $title_text = __( 'If you don\'t want to use the post title for sharing the post on %s but instead want another title there, write it here.', 'wordpress-seo' );
  28. /* translators: %s expands to the social network's name. */
  29. $description_text = __( 'If you don\'t want to use the meta description for sharing the post on %s but want another description there, write it here.', 'wordpress-seo' );
  30. /* translators: %s expands to the social network's name. */
  31. $image_text = __( 'If you want to override the image used on %s for this post, upload / choose an image here.', 'wordpress-seo' );
  32. /* translators: %1$s expands to the social network, %2$s to the recommended image size. */
  33. $image_size_text = __( 'The recommended image size for %1$s is %2$s pixels.', 'wordpress-seo' );
  34. $social_networks = [
  35. 'opengraph' => __( 'Facebook', 'wordpress-seo' ),
  36. 'twitter' => __( 'Twitter', 'wordpress-seo' ),
  37. ];
  38. // Source: https://blog.bufferapp.com/ideal-image-sizes-social-media-posts.
  39. $recommended_image_sizes = [
  40. /* translators: %1$s expands to the image recommended width, %2$s to its height. */
  41. 'opengraph' => sprintf( __( '%1$s by %2$s', 'wordpress-seo' ), '1200', '630' ),
  42. // Source: https://developers.facebook.com/docs/sharing/best-practices#images.
  43. /* translators: %1$s expands to the image recommended width, %2$s to its height. */
  44. 'twitter' => sprintf( __( '%1$s by %2$s', 'wordpress-seo' ), '1024', '512' ),
  45. ];
  46. foreach ( $social_networks as $network => $label ) {
  47. if ( true === WPSEO_Options::get( $network, false ) ) {
  48. /* translators: %s expands to the name of a social network. */
  49. WPSEO_Meta::$meta_fields['social'][ $network . '-title' ]['title'] = sprintf( __( '%s Title', 'wordpress-seo' ), $label );
  50. WPSEO_Meta::$meta_fields['social'][ $network . '-title' ]['description'] = sprintf( $title_text, $label );
  51. /* translators: %s expands to the name of a social network. */
  52. WPSEO_Meta::$meta_fields['social'][ $network . '-description' ]['title'] = sprintf( __( '%s Description', 'wordpress-seo' ), $label );
  53. WPSEO_Meta::$meta_fields['social'][ $network . '-description' ]['description'] = sprintf( $description_text, $label );
  54. /* translators: %s expands to the name of a social network. */
  55. WPSEO_Meta::$meta_fields['social'][ $network . '-image' ]['title'] = sprintf( __( '%s Image', 'wordpress-seo' ), $label );
  56. WPSEO_Meta::$meta_fields['social'][ $network . '-image' ]['description'] = sprintf( $image_text, $label ) . ' ' . sprintf( $image_size_text, $label, $recommended_image_sizes[ $network ] );
  57. }
  58. }
  59. }
  60. /**
  61. * Returns the metabox section for the social settings.
  62. *
  63. * @return WPSEO_Metabox_Collapsibles_Sections
  64. */
  65. public function get_meta_section() {
  66. $tabs = [];
  67. $social_meta_fields = WPSEO_Meta::get_meta_field_defs( 'social' );
  68. $opengraph = WPSEO_Options::get( 'opengraph' );
  69. $twitter = WPSEO_Options::get( 'twitter' );
  70. if ( $opengraph === true && $twitter === true ) {
  71. $single = null;
  72. }
  73. wp_nonce_field( 'yoast_free_metabox_social', 'yoast_free_metabox_social_nonce' );
  74. if ( $opengraph === true ) {
  75. $tabs[] = new WPSEO_Metabox_Collapsible(
  76. 'facebook',
  77. $this->get_social_tab_content( 'opengraph', $social_meta_fields ),
  78. __( 'Facebook', 'wordpress-seo' )
  79. );
  80. }
  81. if ( $twitter === true ) {
  82. $tabs[] = new WPSEO_Metabox_Collapsible(
  83. 'twitter',
  84. $this->get_social_tab_content( 'twitter', $social_meta_fields ),
  85. __( 'Twitter', 'wordpress-seo' )
  86. );
  87. }
  88. return new WPSEO_Metabox_Collapsibles_Sections(
  89. 'social',
  90. '<span class="dashicons dashicons-share"></span>' . __( 'Social', 'wordpress-seo' ),
  91. $tabs
  92. );
  93. }
  94. /**
  95. * Generates the html for a social settings tab for one of the supported social media.
  96. *
  97. * @param string $medium Medium. Can be 'opengraph' or 'twitter'.
  98. * @param array $meta_field_defs The social meta field definitions.
  99. *
  100. * @return string
  101. */
  102. private function get_social_tab_content( $medium, $meta_field_defs ) {
  103. $field_names = [
  104. $medium . '-title',
  105. $medium . '-description',
  106. $medium . '-image',
  107. $medium . '-image-id',
  108. ];
  109. $tab_content = $this->get_premium_notice( $medium );
  110. foreach ( $field_names as $field_name ) {
  111. $tab_content .= $this->do_meta_box( $meta_field_defs[ $field_name ], $field_name );
  112. }
  113. /**
  114. * If premium hide the form to show the social preview instead, we still need the fields to be output because
  115. * the values of the social preview are saved in the hidden field.
  116. */
  117. $features = new WPSEO_Features();
  118. if ( $features->is_premium() ) {
  119. return $this->hide_form( $tab_content );
  120. }
  121. return $tab_content;
  122. }
  123. /**
  124. * Hides the given output when rendered to HTML.
  125. *
  126. * @param string $tab_content The social tab content.
  127. *
  128. * @return string The content.
  129. */
  130. private function hide_form( $tab_content ) {
  131. return '<div class="hidden">' . $tab_content . '</div>';
  132. }
  133. /**
  134. * Returns the Upgrade to Premium notice.
  135. *
  136. * @param string $network The social network.
  137. *
  138. * @return string The notice HTML on the free version, empty string on premium.
  139. */
  140. public function get_premium_notice( $network ) {
  141. $features = new WPSEO_Features();
  142. if ( $features->is_premium() ) {
  143. return '';
  144. }
  145. $network_name = __( 'Facebook', 'wordpress-seo' );
  146. if ( 'twitter' === $network ) {
  147. $network_name = __( 'Twitter', 'wordpress-seo' );
  148. }
  149. return sprintf(
  150. '<div class="notice inline yoast-notice yoast-notice-go-premium">
  151. <p>%1$s</p>
  152. <p><a href="%2$s" target="_blank">%3$s</a></p>
  153. </div>',
  154. sprintf(
  155. /* translators: %1$s expands to the social network's name, %2$s to Yoast SEO Premium. */
  156. esc_html__( 'Do you want to preview what it will look like if people share this post on %1$s? You can, with %2$s.', 'wordpress-seo' ),
  157. esc_html( $network_name ),
  158. '<strong>Yoast SEO Premium</strong>'
  159. ),
  160. esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/179' ) ),
  161. sprintf(
  162. /* translators: %s expands to Yoast SEO Premium. */
  163. esc_html__( 'Find out why you should upgrade to %s', 'wordpress-seo' ),
  164. 'Yoast SEO Premium'
  165. )
  166. );
  167. }
  168. /**
  169. * Filter over the meta boxes to save, this function adds the Social meta boxes.
  170. *
  171. * @param array $field_defs Array of metaboxes to save.
  172. *
  173. * @return array
  174. */
  175. public function save_meta_boxes( $field_defs ) {
  176. if ( ! isset( $_POST['yoast_free_metabox_social_nonce'] ) || ! wp_verify_nonce( $_POST['yoast_free_metabox_social_nonce'], 'yoast_free_metabox_social' ) ) {
  177. return $field_defs;
  178. }
  179. return array_merge( $field_defs, WPSEO_Meta::get_meta_field_defs( 'social' ) );
  180. }
  181. /**
  182. * This method will compare opengraph fields with the posted values.
  183. *
  184. * When fields are changed, the facebook cache will be purged.
  185. *
  186. * @param WP_Post $post Post instance.
  187. */
  188. public function og_data_compare( $post ) {
  189. if ( empty( $_POST ) ) {
  190. return;
  191. }
  192. if ( empty( $post->ID ) || $post->post_status !== 'publish' ) {
  193. return;
  194. }
  195. if ( ! isset( $_POST['yoast_free_metabox_social_nonce'] ) || ! wp_verify_nonce( $_POST['yoast_free_metabox_social_nonce'], 'yoast_free_metabox_social' ) ) {
  196. return;
  197. }
  198. if ( ! isset( $_POST['original_post_status'] ) || $_POST['original_post_status'] !== 'publish' ) {
  199. return;
  200. }
  201. $fields_to_compare = [
  202. 'opengraph-title',
  203. 'opengraph-description',
  204. 'opengraph-image',
  205. ];
  206. $reset_facebook_cache = false;
  207. foreach ( $fields_to_compare as $field_to_compare ) {
  208. $old_value = WPSEO_Meta::get_value( $field_to_compare, $post->ID );
  209. $new_value = '';
  210. $post_key = WPSEO_Meta::$form_prefix . $field_to_compare;
  211. if ( isset( $_POST[ $post_key ] ) ) {
  212. $new_value = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
  213. }
  214. if ( $old_value !== $new_value ) {
  215. $reset_facebook_cache = true;
  216. break;
  217. }
  218. }
  219. unset( $old_value, $new_value );
  220. if ( $reset_facebook_cache ) {
  221. wp_remote_get(
  222. 'https://graph.facebook.com/?id=' . get_permalink( $post->ID ) . '&scrape=true&method=post'
  223. );
  224. }
  225. }
  226. } /* End of class */