説明なし

class.jetpack-keyring-service-helper.php 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. use Automattic\Jetpack\Connection\Secrets;
  3. class Jetpack_Keyring_Service_Helper {
  4. /**
  5. * @var Jetpack_Keyring_Service_Helper
  6. **/
  7. private static $instance = null;
  8. /**
  9. * Whether the `sharing` page is registered.
  10. *
  11. * @var bool
  12. */
  13. private static $is_sharing_page_registered = false;
  14. static function init() {
  15. if ( is_null( self::$instance ) ) {
  16. self::$instance = new Jetpack_Keyring_Service_Helper;
  17. }
  18. return self::$instance;
  19. }
  20. public static $SERVICES = array(
  21. 'facebook' => array(
  22. 'for' => 'publicize'
  23. ),
  24. 'twitter' => array(
  25. 'for' => 'publicize'
  26. ),
  27. 'linkedin' => array(
  28. 'for' => 'publicize'
  29. ),
  30. 'tumblr' => array(
  31. 'for' => 'publicize'
  32. ),
  33. 'path' => array(
  34. 'for' => 'publicize'
  35. ),
  36. 'google_plus' => array(
  37. 'for' => 'publicize'
  38. ),
  39. 'google_site_verification' => array(
  40. 'for' => 'other'
  41. )
  42. );
  43. /**
  44. * Constructor
  45. */
  46. private function __construct() {
  47. add_action( 'admin_menu', array( __CLASS__, 'register_sharing_page' ) );
  48. add_action( 'load-settings_page_sharing', array( __CLASS__, 'admin_page_load' ), 9 );
  49. }
  50. /**
  51. * We need a `sharing` page to be able to connect and disconnect services.
  52. */
  53. public static function register_sharing_page() {
  54. if ( self::$is_sharing_page_registered ) {
  55. return;
  56. }
  57. self::$is_sharing_page_registered = true;
  58. if ( ! current_user_can( 'manage_options' ) ) {
  59. return;
  60. }
  61. global $_registered_pages;
  62. require_once ABSPATH . 'wp-admin/includes/plugin.php';
  63. $hookname = get_plugin_page_hookname( 'sharing', 'options-general.php' );
  64. add_action( $hookname, array( __CLASS__, 'admin_page_load' ) );
  65. $_registered_pages[ $hookname ] = true; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
  66. }
  67. function get_services( $filter = 'all' ) {
  68. $services = array();
  69. if ( 'all' === $filter ) {
  70. return $services;
  71. } else {
  72. $connected_services = array();
  73. foreach ( $services as $service => $empty ) {
  74. $connections = $this->get_connections( $service );
  75. if ( $connections ) {
  76. $connected_services[ $service ] = $connections;
  77. }
  78. }
  79. return $connected_services;
  80. }
  81. }
  82. /**
  83. * Gets a URL to the public-api actions. Works like WP's admin_url
  84. *
  85. * @param string $service Shortname of a specific service.
  86. *
  87. * @return URL to specific public-api process
  88. */
  89. // on WordPress.com this is/calls Keyring::admin_url
  90. static function api_url( $service = false, $params = array() ) {
  91. /**
  92. * Filters the API URL used to interact with WordPress.com.
  93. *
  94. * @since 2.0.0
  95. *
  96. * @param string https://public-api.wordpress.com/connect/?jetpack=publicize Default Publicize API URL.
  97. */
  98. $url = apply_filters( 'publicize_api_url', 'https://public-api.wordpress.com/connect/?jetpack=publicize' );
  99. if ( $service ) {
  100. $url = add_query_arg( array( 'service' => $service ), $url );
  101. }
  102. if ( count( $params ) ) {
  103. $url = add_query_arg( $params, $url );
  104. }
  105. return $url;
  106. }
  107. static function connect_url( $service_name, $for ) {
  108. return add_query_arg(
  109. array(
  110. 'action' => 'request',
  111. 'service' => $service_name,
  112. 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
  113. 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
  114. 'for' => $for,
  115. ),
  116. admin_url( 'options-general.php?page=sharing' )
  117. );
  118. }
  119. static function refresh_url( $service_name, $for ) {
  120. return add_query_arg(
  121. array(
  122. 'action' => 'request',
  123. 'service' => $service_name,
  124. 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
  125. 'refresh' => 1,
  126. 'for' => $for,
  127. 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
  128. ),
  129. admin_url( 'options-general.php?page=sharing' )
  130. );
  131. }
  132. static function disconnect_url( $service_name, $id ) {
  133. return add_query_arg(
  134. array(
  135. 'action' => 'delete',
  136. 'service' => $service_name,
  137. 'id' => $id,
  138. 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
  139. 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
  140. ),
  141. admin_url( 'options-general.php?page=sharing' )
  142. );
  143. }
  144. static function admin_page_load() {
  145. if ( isset( $_GET['action'] ) ) {
  146. if ( isset( $_GET['service'] ) ) {
  147. $service_name = $_GET['service'];
  148. }
  149. switch ( $_GET['action'] ) {
  150. case 'request':
  151. check_admin_referer( 'keyring-request', 'kr_nonce' );
  152. check_admin_referer( "keyring-request-$service_name", 'nonce' );
  153. $verification = ( new Secrets() )->generate( 'publicize' );
  154. if ( ! $verification ) {
  155. $url = Jetpack::admin_url( 'jetpack#/settings' );
  156. wp_die( sprintf( __( "Jetpack is not connected. Please connect Jetpack by visiting <a href='%s'>Settings</a>.", 'jetpack' ), $url ) );
  157. }
  158. $stats_options = get_option( 'stats_options' );
  159. $wpcom_blog_id = Jetpack_Options::get_option( 'id' );
  160. $wpcom_blog_id = ! empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
  161. $user = wp_get_current_user();
  162. $redirect = Jetpack_Keyring_Service_Helper::api_url( $service_name, urlencode_deep( array(
  163. 'action' => 'request',
  164. 'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
  165. 'for' => 'publicize',
  166. // required flag that says this connection is intended for publicize
  167. 'siteurl' => site_url(),
  168. 'state' => $user->ID,
  169. 'blog_id' => $wpcom_blog_id,
  170. 'secret_1' => $verification['secret_1'],
  171. 'secret_2' => $verification['secret_2'],
  172. 'eol' => $verification['exp'],
  173. ) ) );
  174. wp_redirect( $redirect );
  175. exit;
  176. break;
  177. case 'completed':
  178. $xml = new Jetpack_IXR_Client();
  179. $xml->query( 'jetpack.fetchPublicizeConnections' );
  180. if ( ! $xml->isError() ) {
  181. $response = $xml->getResponse();
  182. Jetpack_Options::update_option( 'publicize_connections', $response );
  183. }
  184. break;
  185. case 'delete':
  186. $id = $_GET['id'];
  187. check_admin_referer( 'keyring-request', 'kr_nonce' );
  188. check_admin_referer( "keyring-request-$service_name", 'nonce' );
  189. Jetpack_Keyring_Service_Helper::disconnect( $service_name, $id );
  190. do_action( 'connection_disconnected', $service_name );
  191. break;
  192. }
  193. }
  194. }
  195. /**
  196. * Remove a Publicize connection
  197. */
  198. static function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
  199. $xml = new Jetpack_IXR_Client();
  200. $xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
  201. if ( ! $xml->isError() ) {
  202. Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() );
  203. } else {
  204. return false;
  205. }
  206. }
  207. }