Completed
Push — e2e/slack-notification ( d43a76...5a846a )
by
unknown
177:22 queued 165:42
created

jetpack_xmlrpc_server_event()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 4
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Jetpack XMLRPC Methods.
4
 *
5
 * Registers the Jetpack specific XMLRPC methods
6
 *
7
 * @package jetpack
8
 */
9
10
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11
use Automattic\Jetpack\Connection\Tokens;
12
13
/**
14
 * XMLRPC Methods registration and callbacks
15
 */
16
class Jetpack_XMLRPC_Methods {
17
18
	/**
19
	 * Initialize the main hooks.
20
	 */
21
	public static function init() {
22
		add_filter( 'jetpack_xmlrpc_unauthenticated_methods', array( __CLASS__, 'xmlrpc_methods' ) );
23
		add_filter( 'jetpack_xmlrpc_test_connection_response', array( __CLASS__, 'test_connection' ) );
24
		add_action( 'jetpack_xmlrpc_server_event', array( __CLASS__, 'jetpack_xmlrpc_server_event' ), 10, 4 );
25
		add_action( 'jetpack_remote_connect_end', array( __CLASS__, 'remote_connect_end' ) );
26
	}
27
28
	/**
29
	 * Adds Jetpack specific methods to the methods added by the Connection package.
30
	 *
31
	 * @param array $methods Methods added by the Connection package.
32
	 */
33
	public static function xmlrpc_methods( $methods ) {
34
35
		$methods['jetpack.featuresAvailable'] = array( __CLASS__, 'features_available' );
36
		$methods['jetpack.featuresEnabled']   = array( __CLASS__, 'features_enabled' );
37
		$methods['jetpack.disconnectBlog']    = array( __CLASS__, 'disconnect_blog' );
38
		$methods['jetpack.jsonAPI']           = array( __CLASS__, 'json_api' );
39
40
		return $methods;
41
	}
42
43
	/**
44
	 * Returns what features are available. Uses the slug of the module files.
45
	 *
46
	 * @return array
47
	 */
48 View Code Duplication
	public static function features_available() {
49
		$raw_modules = Jetpack::get_available_modules();
50
		$modules     = array();
51
		foreach ( $raw_modules as $module ) {
52
			$modules[] = Jetpack::get_module_slug( $module );
53
		}
54
55
		return $modules;
56
	}
57
58
	/**
59
	 * Returns what features are enabled. Uses the slug of the modules files.
60
	 *
61
	 * @return array
62
	 */
63 View Code Duplication
	public static function features_enabled() {
64
		$raw_modules = Jetpack::get_active_modules();
65
		$modules     = array();
66
		foreach ( $raw_modules as $module ) {
67
			$modules[] = Jetpack::get_module_slug( $module );
68
		}
69
70
		return $modules;
71
	}
72
73
	/**
74
	 * Filters the result of test_connection XMLRPC method
75
	 *
76
	 * @return string The current Jetpack version number
77
	 */
78
	public static function test_connection() {
79
		return JETPACK__VERSION;
80
	}
81
82
	/**
83
	 * Disconnect this blog from the connected wordpress.com account
84
	 *
85
	 * @return boolean
86
	 */
87
	public static function disconnect_blog() {
88
89
		/**
90
		 * Fired when we want to log an event to the Jetpack event log.
91
		 *
92
		 * @since 7.7.0
93
		 *
94
		 * @param string $code Unique name for the event.
95
		 * @param string $data Optional data about the event.
96
		 */
97
		do_action( 'jetpack_event_log', 'disconnect' );
98
		Jetpack::disconnect();
99
100
		return true;
101
	}
102
103
	/**
104
	 * Serve a JSON API request.
105
	 *
106
	 * @param array $args request arguments.
107
	 */
108
	public static function json_api( $args = array() ) {
109
		$json_api_args        = $args[0];
110
		$verify_api_user_args = $args[1];
111
112
		$method       = (string) $json_api_args[0];
113
		$url          = (string) $json_api_args[1];
114
		$post_body    = is_null( $json_api_args[2] ) ? null : (string) $json_api_args[2];
115
		$user_details = (array) $json_api_args[4];
116
		$locale       = (string) $json_api_args[5];
117
118
		if ( ! $verify_api_user_args ) {
119
			$user_id = 0;
120
		} elseif ( 'internal' === $verify_api_user_args[0] ) {
121
			$user_id = (int) $verify_api_user_args[1];
122
			if ( $user_id ) {
123
				$user = get_user_by( 'id', $user_id );
124
				if ( ! $user || is_wp_error( $user ) ) {
125
					return false;
126
				}
127
			}
128
		} else {
129
			$user_id = call_user_func( array( new Jetpack_XMLRPC_Server(), 'test_api_user_code' ), $verify_api_user_args );
130
			if ( ! $user_id ) {
131
				return false;
132
			}
133
		}
134
135
		if ( 'en' !== $locale ) {
136
			// .org mo files are named slightly different from .com, and all we have is this the locale -- try to guess them.
137
			$new_locale = $locale;
138
			if ( strpos( $locale, '-' ) !== false ) {
139
				$locale_pieces = explode( '-', $locale );
140
				$new_locale    = $locale_pieces[0];
141
				$new_locale   .= ( ! empty( $locale_pieces[1] ) ) ? '_' . strtoupper( $locale_pieces[1] ) : '';
142
			} else {
143
				// .com might pass 'fr' because thats what our language files are named as, where core seems
144
				// to do fr_FR - so try that if we don't think we can load the file.
145
				if ( ! file_exists( WP_LANG_DIR . '/' . $locale . '.mo' ) ) {
146
					$new_locale = $locale . '_' . strtoupper( $locale );
147
				}
148
			}
149
150
			if ( file_exists( WP_LANG_DIR . '/' . $new_locale . '.mo' ) ) {
151
				unload_textdomain( 'default' );
152
				load_textdomain( 'default', WP_LANG_DIR . '/' . $new_locale . '.mo' );
153
			}
154
		}
155
156
		$old_user = wp_get_current_user();
157
		wp_set_current_user( $user_id );
158
159
		if ( $user_id ) {
160
			$token_key = false;
161
		} else {
162
			$verified  = ( new Connection_Manager() )->verify_xml_rpc_signature();
163
			$token_key = $verified['token_key'];
164
		}
165
166
		$token = ( new Tokens() )->get_access_token( $user_id, $token_key );
167
		if ( ! $token || is_wp_error( $token ) ) {
168
			return false;
169
		}
170
171
		define( 'REST_API_REQUEST', true );
172
		define( 'WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1' );
173
174
		// needed?
175
		require_once ABSPATH . 'wp-admin/includes/admin.php';
176
177
		require_once JETPACK__PLUGIN_DIR . 'class.json-api.php';
178
		$api                        = WPCOM_JSON_API::init( $method, $url, $post_body );
179
		$api->token_details['user'] = $user_details;
180
		require_once JETPACK__PLUGIN_DIR . 'class.json-api-endpoints.php';
181
182
		$display_errors = ini_set( 'display_errors', 0 ); // phpcs:ignore WordPress.PHP.IniSet
183
		ob_start();
184
		$api->serve( false );
185
		$output = ob_get_clean();
186
		ini_set( 'display_errors', $display_errors ); // phpcs:ignore WordPress.PHP.IniSet
187
188
		$nonce = wp_generate_password( 10, false );
189
		$hmac  = hash_hmac( 'md5', $nonce . $output, $token->secret );
190
191
		wp_set_current_user( isset( $old_user->ID ) ? $old_user->ID : 0 );
192
193
		return array(
194
			(string) $output,
195
			(string) $nonce,
196
			(string) $hmac,
197
		);
198
	}
199
200
	/**
201
	 * Runs Jetpack specific action in xmlrpc server events
202
	 *
203
	 * @param String  $action the action name, i.e., 'remote_authorize'.
204
	 * @param String  $stage  the execution stage, can be 'begin', 'success', 'error', etc.
205
	 * @param array   $parameters extra parameters from the event.
206
	 * @param WP_User $user the acting user.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user not be WP_User|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
207
	 * @return void
208
	 */
209
	public static function jetpack_xmlrpc_server_event( $action, $stage, $parameters = array(), $user = null ) { //phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
210
		if ( 'remote_register' === $action && 'begin' === $stage ) {
211
			Jetpack::maybe_set_version_option();
212
		}
213
	}
214
215
	/**
216
	 * Hooks into the remote_connect XMLRPC endpoint and triggers Jetpack::handle_post_authorization_actions
217
	 *
218
	 * @since 9.8.0
219
	 * @return void
220
	 */
221
	public static function remote_connect_end() {
222
		/** This filter is documented in class.jetpack-cli.php */
223
		$enable_sso = apply_filters( 'jetpack_start_enable_sso', true );
224
		Jetpack::handle_post_authorization_actions( $enable_sso, false, false );
225
	}
226
}
227