Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | use Automattic\Jetpack\Connection\Client; |
||
| 4 | use Automattic\Jetpack\Jetpack_CRM_Data; |
||
| 5 | use Automattic\Jetpack\Connection\Manager as Connection_Manager; |
||
| 6 | use Automattic\Jetpack\Connection\REST_Connector; |
||
| 7 | use Automattic\Jetpack\JITMS\JITM; |
||
| 8 | use Automattic\Jetpack\Licensing; |
||
| 9 | use Automattic\Jetpack\Tracking; |
||
| 10 | |||
| 11 | |||
| 12 | /** |
||
| 13 | * Register WP REST API endpoints for Jetpack. |
||
| 14 | * |
||
| 15 | * @author Automattic |
||
| 16 | */ |
||
| 17 | |||
| 18 | /** |
||
| 19 | * Disable direct access. |
||
| 20 | */ |
||
| 21 | if ( ! defined( 'ABSPATH' ) ) { |
||
| 22 | exit; |
||
| 23 | } |
||
| 24 | |||
| 25 | // Load WP_Error for error messages. |
||
| 26 | require_once ABSPATH . '/wp-includes/class-wp-error.php'; |
||
| 27 | |||
| 28 | // Register endpoints when WP REST API is initialized. |
||
| 29 | add_action( 'rest_api_init', array( 'Jetpack_Core_Json_Api_Endpoints', 'register_endpoints' ) ); |
||
| 30 | // Load API endpoints that are synced with WP.com |
||
| 31 | // Each of these is a class that will register its own routes on 'rest_api_init'. |
||
| 32 | require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/load-wpcom-endpoints.php'; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * Class Jetpack_Core_Json_Api_Endpoints |
||
| 36 | * |
||
| 37 | * @since 4.3.0 |
||
| 38 | */ |
||
| 39 | class Jetpack_Core_Json_Api_Endpoints { |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var string Generic error message when user is not allowed to perform an action. |
||
| 43 | * |
||
| 44 | * @deprecated 8.8.0 Use `REST_Connector::get_user_permissions_error_msg()` instead. |
||
| 45 | */ |
||
| 46 | public static $user_permissions_error_msg; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @var array Roles that can access Stats once they're granted access. |
||
| 50 | */ |
||
| 51 | public static $stats_roles; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Declare the Jetpack REST API endpoints. |
||
| 55 | * |
||
| 56 | * @since 4.3.0 |
||
| 57 | */ |
||
| 58 | public static function register_endpoints() { |
||
| 59 | |||
| 60 | // Load API endpoint base classes |
||
| 61 | require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php'; |
||
| 62 | |||
| 63 | // Load API endpoints |
||
| 64 | require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php'; |
||
| 65 | require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php'; |
||
| 66 | require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php'; |
||
| 67 | |||
| 68 | self::$user_permissions_error_msg = REST_Connector::get_user_permissions_error_msg(); |
||
| 69 | |||
| 70 | self::$stats_roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' ); |
||
| 71 | |||
| 72 | $ixr_client = new Jetpack_IXR_Client( array( 'user_id' => get_current_user_id() ) ); |
||
| 73 | $core_api_endpoint = new Jetpack_Core_API_Data( $ixr_client ); |
||
| 74 | $module_list_endpoint = new Jetpack_Core_API_Module_List_Endpoint(); |
||
| 75 | $module_data_endpoint = new Jetpack_Core_API_Module_Data_Endpoint(); |
||
| 76 | $module_toggle_endpoint = new Jetpack_Core_API_Module_Toggle_Endpoint( new Jetpack_IXR_Client() ); |
||
| 77 | $site_endpoint = new Jetpack_Core_API_Site_Endpoint(); |
||
| 78 | $widget_endpoint = new Jetpack_Core_API_Widget_Endpoint(); |
||
| 79 | |||
| 80 | register_rest_route( 'jetpack/v4', 'plans', array( |
||
| 81 | 'methods' => WP_REST_Server::READABLE, |
||
| 82 | 'callback' => __CLASS__ . '::get_plans', |
||
| 83 | 'permission_callback' => __CLASS__ . '::connect_url_permission_callback', |
||
| 84 | ) ); |
||
| 85 | |||
| 86 | register_rest_route( 'jetpack/v4', 'products', array( |
||
| 87 | 'methods' => WP_REST_Server::READABLE, |
||
| 88 | 'callback' => __CLASS__ . '::get_products', |
||
| 89 | 'permission_callback' => __CLASS__ . '::connect_url_permission_callback', |
||
| 90 | ) ); |
||
| 91 | |||
| 92 | register_rest_route( 'jetpack/v4', 'marketing/survey', array( |
||
| 93 | 'methods' => WP_REST_Server::CREATABLE, |
||
| 94 | 'callback' => __CLASS__ . '::submit_survey', |
||
| 95 | 'permission_callback' => __CLASS__ . '::disconnect_site_permission_callback', |
||
| 96 | ) ); |
||
| 97 | |||
| 98 | register_rest_route( 'jetpack/v4', '/jitm', array( |
||
| 99 | 'methods' => WP_REST_Server::READABLE, |
||
| 100 | 'callback' => __CLASS__ . '::get_jitm_message', |
||
| 101 | 'permission_callback' => '__return_true', |
||
| 102 | ) ); |
||
| 103 | |||
| 104 | register_rest_route( 'jetpack/v4', '/jitm', array( |
||
| 105 | 'methods' => WP_REST_Server::CREATABLE, |
||
| 106 | 'callback' => __CLASS__ . '::delete_jitm_message', |
||
| 107 | 'permission_callback' => __CLASS__ . '::delete_jitm_message_permission_callback', |
||
| 108 | ) ); |
||
| 109 | |||
| 110 | // Test current connection status of Jetpack |
||
| 111 | register_rest_route( 'jetpack/v4', '/connection/test', array( |
||
| 112 | 'methods' => WP_REST_Server::READABLE, |
||
| 113 | 'callback' => __CLASS__ . '::jetpack_connection_test', |
||
| 114 | 'permission_callback' => __CLASS__ . '::manage_modules_permission_check', |
||
| 115 | ) ); |
||
| 116 | |||
| 117 | // Endpoint specific for privileged servers to request detailed debug information. |
||
| 118 | register_rest_route( 'jetpack/v4', '/connection/test-wpcom/', array( |
||
| 119 | 'methods' => WP_REST_Server::READABLE, |
||
| 120 | 'callback' => __CLASS__ . '::jetpack_connection_test_for_external', |
||
| 121 | 'permission_callback' => __CLASS__ . '::view_jetpack_connection_test_check', |
||
| 122 | ) ); |
||
| 123 | |||
| 124 | register_rest_route( 'jetpack/v4', '/rewind', array( |
||
| 125 | 'methods' => WP_REST_Server::READABLE, |
||
| 126 | 'callback' => __CLASS__ . '::get_rewind_data', |
||
| 127 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 128 | ) ); |
||
| 129 | |||
| 130 | register_rest_route( |
||
| 131 | 'jetpack/v4', |
||
| 132 | '/scan', |
||
| 133 | array( |
||
| 134 | 'methods' => WP_REST_Server::READABLE, |
||
| 135 | 'callback' => __CLASS__ . '::get_scan_state', |
||
| 136 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 137 | ) |
||
| 138 | ); |
||
| 139 | |||
| 140 | // Fetches a fresh connect URL |
||
| 141 | register_rest_route( 'jetpack/v4', '/connection/url', array( |
||
| 142 | 'methods' => WP_REST_Server::READABLE, |
||
| 143 | 'callback' => __CLASS__ . '::build_connect_url', |
||
| 144 | 'permission_callback' => __CLASS__ . '::connect_url_permission_callback', |
||
| 145 | 'args' => array( |
||
| 146 | 'from' => array( 'type' => 'string' ), |
||
| 147 | 'redirect' => array( 'type' => 'string' ), |
||
| 148 | ), |
||
| 149 | ) ); |
||
| 150 | |||
| 151 | // Get current user connection data |
||
| 152 | register_rest_route( 'jetpack/v4', '/connection/data', array( |
||
| 153 | 'methods' => WP_REST_Server::READABLE, |
||
| 154 | 'callback' => __CLASS__ . '::get_user_connection_data', |
||
| 155 | 'permission_callback' => __CLASS__ . '::get_user_connection_data_permission_callback', |
||
| 156 | ) ); |
||
| 157 | |||
| 158 | // Start the connection process by registering the site on WordPress.com servers. |
||
| 159 | register_rest_route( 'jetpack/v4', '/connection/register', array( |
||
| 160 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 161 | 'callback' => __CLASS__ . '::register_site', |
||
| 162 | 'permission_callback' => __CLASS__ . '::connect_url_permission_callback', |
||
| 163 | 'args' => array( |
||
| 164 | 'registration_nonce' => array( 'type' => 'string' ), |
||
| 165 | ), |
||
| 166 | ) ); |
||
| 167 | |||
| 168 | // Set the connection owner |
||
| 169 | register_rest_route( 'jetpack/v4', '/connection/owner', array( |
||
| 170 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 171 | 'callback' => __CLASS__ . '::set_connection_owner', |
||
| 172 | 'permission_callback' => __CLASS__ . '::set_connection_owner_permission_callback', |
||
| 173 | ) ); |
||
| 174 | |||
| 175 | // Current user: get or set tracking settings. |
||
| 176 | register_rest_route( 'jetpack/v4', '/tracking/settings', array( |
||
| 177 | array( |
||
| 178 | 'methods' => WP_REST_Server::READABLE, |
||
| 179 | 'callback' => __CLASS__ . '::get_user_tracking_settings', |
||
| 180 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 181 | ), |
||
| 182 | array( |
||
| 183 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 184 | 'callback' => __CLASS__ . '::update_user_tracking_settings', |
||
| 185 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 186 | 'args' => array( |
||
| 187 | 'tracks_opt_out' => array( 'type' => 'boolean' ), |
||
| 188 | ), |
||
| 189 | ), |
||
| 190 | ) ); |
||
| 191 | |||
| 192 | // Disconnect site from WordPress.com servers |
||
| 193 | register_rest_route( 'jetpack/v4', '/connection', array( |
||
| 194 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 195 | 'callback' => __CLASS__ . '::disconnect_site', |
||
| 196 | 'permission_callback' => __CLASS__ . '::disconnect_site_permission_callback', |
||
| 197 | ) ); |
||
| 198 | |||
| 199 | // Disconnect/unlink user from WordPress.com servers |
||
| 200 | register_rest_route( 'jetpack/v4', '/connection/user', array( |
||
| 201 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 202 | 'callback' => __CLASS__ . '::unlink_user', |
||
| 203 | 'permission_callback' => __CLASS__ . '::unlink_user_permission_callback', |
||
| 204 | ) ); |
||
| 205 | |||
| 206 | // Get current site data |
||
| 207 | register_rest_route( 'jetpack/v4', '/site', array( |
||
| 208 | 'methods' => WP_REST_Server::READABLE, |
||
| 209 | 'callback' => __CLASS__ . '::get_site_data', |
||
| 210 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 211 | ) ); |
||
| 212 | |||
| 213 | // Get current site data |
||
| 214 | register_rest_route( 'jetpack/v4', '/site/features', array( |
||
| 215 | 'methods' => WP_REST_Server::READABLE, |
||
| 216 | 'callback' => array( $site_endpoint, 'get_features' ), |
||
| 217 | 'permission_callback' => array( $site_endpoint , 'can_request' ), |
||
| 218 | ) ); |
||
| 219 | |||
| 220 | register_rest_route( |
||
| 221 | 'jetpack/v4', |
||
| 222 | '/site/products', |
||
| 223 | array( |
||
| 224 | 'methods' => WP_REST_Server::READABLE, |
||
| 225 | 'callback' => array( $site_endpoint, 'get_products' ), |
||
| 226 | 'permission_callback' => array( $site_endpoint, 'can_request' ), |
||
| 227 | ) |
||
| 228 | ); |
||
| 229 | |||
| 230 | // Get current site purchases. |
||
| 231 | register_rest_route( |
||
| 232 | 'jetpack/v4', |
||
| 233 | '/site/purchases', |
||
| 234 | array( |
||
| 235 | 'methods' => WP_REST_Server::READABLE, |
||
| 236 | 'callback' => array( $site_endpoint, 'get_purchases' ), |
||
| 237 | 'permission_callback' => array( $site_endpoint, 'can_request' ), |
||
| 238 | ) |
||
| 239 | ); |
||
| 240 | |||
| 241 | // Get current site benefits |
||
| 242 | register_rest_route( 'jetpack/v4', '/site/benefits', array( |
||
| 243 | 'methods' => WP_REST_Server::READABLE, |
||
| 244 | 'callback' => array( $site_endpoint, 'get_benefits' ), |
||
| 245 | 'permission_callback' => array( $site_endpoint, 'can_request' ), |
||
| 246 | ) ); |
||
| 247 | |||
| 248 | // Get Activity Log data for this site. |
||
| 249 | register_rest_route( 'jetpack/v4', '/site/activity', array( |
||
| 250 | 'methods' => WP_REST_Server::READABLE, |
||
| 251 | 'callback' => __CLASS__ . '::get_site_activity', |
||
| 252 | 'permission_callback' => __CLASS__ . '::manage_modules_permission_check', |
||
| 253 | ) ); |
||
| 254 | |||
| 255 | // Confirm that a site in identity crisis should be in staging mode |
||
| 256 | register_rest_route( 'jetpack/v4', '/identity-crisis/confirm-safe-mode', array( |
||
| 257 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 258 | 'callback' => __CLASS__ . '::confirm_safe_mode', |
||
| 259 | 'permission_callback' => __CLASS__ . '::identity_crisis_mitigation_permission_check', |
||
| 260 | ) ); |
||
| 261 | |||
| 262 | // IDC resolve: create an entirely new shadow site for this URL. |
||
| 263 | register_rest_route( 'jetpack/v4', '/identity-crisis/start-fresh', array( |
||
| 264 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 265 | 'callback' => __CLASS__ . '::start_fresh_connection', |
||
| 266 | 'permission_callback' => __CLASS__ . '::identity_crisis_mitigation_permission_check', |
||
| 267 | ) ); |
||
| 268 | |||
| 269 | // Handles the request to migrate stats and subscribers during an identity crisis. |
||
| 270 | register_rest_route( 'jetpack/v4', 'identity-crisis/migrate', array( |
||
| 271 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 272 | 'callback' => __CLASS__ . '::migrate_stats_and_subscribers', |
||
| 273 | 'permission_callback' => __CLASS__ . '::identity_crisis_mitigation_permission_check', |
||
| 274 | ) ); |
||
| 275 | |||
| 276 | // Return all modules |
||
| 277 | register_rest_route( 'jetpack/v4', '/module/all', array( |
||
| 278 | 'methods' => WP_REST_Server::READABLE, |
||
| 279 | 'callback' => array( $module_list_endpoint, 'process' ), |
||
| 280 | 'permission_callback' => array( $module_list_endpoint, 'can_request' ), |
||
| 281 | ) ); |
||
| 282 | |||
| 283 | // Activate many modules |
||
| 284 | register_rest_route( 'jetpack/v4', '/module/all/active', array( |
||
| 285 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 286 | 'callback' => array( $module_list_endpoint, 'process' ), |
||
| 287 | 'permission_callback' => array( $module_list_endpoint, 'can_request' ), |
||
| 288 | 'args' => array( |
||
| 289 | 'modules' => array( |
||
| 290 | 'default' => '', |
||
| 291 | 'type' => 'array', |
||
| 292 | 'items' => array( |
||
| 293 | 'type' => 'string', |
||
| 294 | ), |
||
| 295 | 'required' => true, |
||
| 296 | 'validate_callback' => __CLASS__ . '::validate_module_list', |
||
| 297 | ), |
||
| 298 | 'active' => array( |
||
| 299 | 'default' => true, |
||
| 300 | 'type' => 'boolean', |
||
| 301 | 'required' => false, |
||
| 302 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 303 | ), |
||
| 304 | ) |
||
| 305 | ) ); |
||
| 306 | |||
| 307 | // Return a single module and update it when needed |
||
| 308 | register_rest_route( 'jetpack/v4', '/module/(?P<slug>[a-z\-]+)', array( |
||
| 309 | 'methods' => WP_REST_Server::READABLE, |
||
| 310 | 'callback' => array( $core_api_endpoint, 'process' ), |
||
| 311 | 'permission_callback' => array( $core_api_endpoint, 'can_request' ), |
||
| 312 | ) ); |
||
| 313 | |||
| 314 | // Activate and deactivate a module |
||
| 315 | register_rest_route( 'jetpack/v4', '/module/(?P<slug>[a-z\-]+)/active', array( |
||
| 316 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 317 | 'callback' => array( $module_toggle_endpoint, 'process' ), |
||
| 318 | 'permission_callback' => array( $module_toggle_endpoint, 'can_request' ), |
||
| 319 | 'args' => array( |
||
| 320 | 'active' => array( |
||
| 321 | 'default' => true, |
||
| 322 | 'type' => 'boolean', |
||
| 323 | 'required' => true, |
||
| 324 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 325 | ), |
||
| 326 | ) |
||
| 327 | ) ); |
||
| 328 | |||
| 329 | // Update a module |
||
| 330 | register_rest_route( 'jetpack/v4', '/module/(?P<slug>[a-z\-]+)', array( |
||
| 331 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 332 | 'callback' => array( $core_api_endpoint, 'process' ), |
||
| 333 | 'permission_callback' => array( $core_api_endpoint, 'can_request' ), |
||
| 334 | 'args' => self::get_updateable_parameters( 'any' ) |
||
| 335 | ) ); |
||
| 336 | |||
| 337 | // Get data for a specific module, i.e. Protect block count, WPCOM stats, |
||
| 338 | // Akismet spam count, etc. |
||
| 339 | register_rest_route( 'jetpack/v4', '/module/(?P<slug>[a-z\-]+)/data', array( |
||
| 340 | 'methods' => WP_REST_Server::READABLE, |
||
| 341 | 'callback' => array( $module_data_endpoint, 'process' ), |
||
| 342 | 'permission_callback' => array( $module_data_endpoint, 'can_request' ), |
||
| 343 | 'args' => array( |
||
| 344 | 'range' => array( |
||
| 345 | 'default' => 'day', |
||
| 346 | 'type' => 'string', |
||
| 347 | 'required' => false, |
||
| 348 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 349 | ), |
||
| 350 | ) |
||
| 351 | ) ); |
||
| 352 | |||
| 353 | // Check if the API key for a specific service is valid or not |
||
| 354 | register_rest_route( 'jetpack/v4', '/module/(?P<service>[a-z\-]+)/key/check', array( |
||
| 355 | 'methods' => WP_REST_Server::READABLE, |
||
| 356 | 'callback' => array( $module_data_endpoint, 'key_check' ), |
||
| 357 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 358 | 'sanitize_callback' => 'sanitize_text_field', |
||
| 359 | ) ); |
||
| 360 | |||
| 361 | register_rest_route( 'jetpack/v4', '/module/(?P<service>[a-z\-]+)/key/check', array( |
||
| 362 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 363 | 'callback' => array( $module_data_endpoint, 'key_check' ), |
||
| 364 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 365 | 'sanitize_callback' => 'sanitize_text_field', |
||
| 366 | 'args' => array( |
||
| 367 | 'api_key' => array( |
||
| 368 | 'default' => '', |
||
| 369 | 'type' => 'string', |
||
| 370 | 'validate_callback' => __CLASS__ . '::validate_alphanum', |
||
| 371 | ), |
||
| 372 | ) |
||
| 373 | ) ); |
||
| 374 | |||
| 375 | // Update any Jetpack module option or setting |
||
| 376 | register_rest_route( 'jetpack/v4', '/settings', array( |
||
| 377 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 378 | 'callback' => array( $core_api_endpoint, 'process' ), |
||
| 379 | 'permission_callback' => array( $core_api_endpoint, 'can_request' ), |
||
| 380 | 'args' => self::get_updateable_parameters( 'any' ) |
||
| 381 | ) ); |
||
| 382 | |||
| 383 | // Update a module |
||
| 384 | register_rest_route( 'jetpack/v4', '/settings/(?P<slug>[a-z\-]+)', array( |
||
| 385 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 386 | 'callback' => array( $core_api_endpoint, 'process' ), |
||
| 387 | 'permission_callback' => array( $core_api_endpoint, 'can_request' ), |
||
| 388 | 'args' => self::get_updateable_parameters() |
||
| 389 | ) ); |
||
| 390 | |||
| 391 | // Return all module settings |
||
| 392 | register_rest_route( 'jetpack/v4', '/settings/', array( |
||
| 393 | 'methods' => WP_REST_Server::READABLE, |
||
| 394 | 'callback' => array( $core_api_endpoint, 'process' ), |
||
| 395 | 'permission_callback' => array( $core_api_endpoint, 'can_request' ), |
||
| 396 | ) ); |
||
| 397 | |||
| 398 | // Reset all Jetpack options |
||
| 399 | register_rest_route( 'jetpack/v4', '/options/(?P<options>[a-z\-]+)', array( |
||
| 400 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 401 | 'callback' => __CLASS__ . '::reset_jetpack_options', |
||
| 402 | 'permission_callback' => __CLASS__ . '::manage_modules_permission_check', |
||
| 403 | ) ); |
||
| 404 | |||
| 405 | // Updates: get number of plugin updates available |
||
| 406 | register_rest_route( 'jetpack/v4', '/updates/plugins', array( |
||
| 407 | 'methods' => WP_REST_Server::READABLE, |
||
| 408 | 'callback' => __CLASS__ . '::get_plugin_update_count', |
||
| 409 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 410 | ) ); |
||
| 411 | |||
| 412 | // Dismiss Jetpack Notices |
||
| 413 | register_rest_route( 'jetpack/v4', '/notice/(?P<notice>[a-z\-_]+)', array( |
||
| 414 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 415 | 'callback' => __CLASS__ . '::dismiss_notice', |
||
| 416 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 417 | ) ); |
||
| 418 | |||
| 419 | /* |
||
| 420 | * Plugins: manage plugins on your site. |
||
| 421 | * |
||
| 422 | * @since 8.9.0 |
||
| 423 | * |
||
| 424 | * @to-do: deprecate and switch to /wp/v2/plugins when WordPress 5.5 is the minimum required version. |
||
| 425 | * Noting that the `source` parameter is Jetpack-specific (not implemented in Core). |
||
| 426 | */ |
||
| 427 | register_rest_route( |
||
| 428 | 'jetpack/v4', |
||
| 429 | '/plugins', |
||
| 430 | array( |
||
| 431 | array( |
||
| 432 | 'methods' => WP_REST_Server::READABLE, |
||
| 433 | 'callback' => __CLASS__ . '::get_plugins', |
||
| 434 | 'permission_callback' => __CLASS__ . '::activate_plugins_permission_check', |
||
| 435 | ), |
||
| 436 | array( |
||
| 437 | 'methods' => WP_REST_Server::CREATABLE, |
||
| 438 | 'callback' => __CLASS__ . '::install_plugin', |
||
| 439 | 'permission_callback' => __CLASS__ . '::activate_plugins_permission_check', |
||
| 440 | 'args' => array( |
||
| 441 | 'slug' => array( |
||
| 442 | 'type' => 'string', |
||
| 443 | 'required' => true, |
||
| 444 | 'description' => __( 'WordPress.org plugin directory slug.', 'jetpack' ), |
||
| 445 | 'pattern' => '[\w\-]+', |
||
| 446 | ), |
||
| 447 | 'status' => array( |
||
| 448 | 'description' => __( 'The plugin activation status.', 'jetpack' ), |
||
| 449 | 'type' => 'string', |
||
| 450 | 'enum' => is_multisite() ? array( 'inactive', 'active', 'network-active' ) : array( 'inactive', 'active' ), |
||
| 451 | 'default' => 'inactive', |
||
| 452 | ), |
||
| 453 | 'source' => array( |
||
| 454 | 'required' => false, |
||
| 455 | 'type' => 'string', |
||
| 456 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 457 | ), |
||
| 458 | ), |
||
| 459 | ), |
||
| 460 | ) |
||
| 461 | ); |
||
| 462 | |||
| 463 | /* |
||
| 464 | * Plugins: activate a specific plugin. |
||
| 465 | * |
||
| 466 | * @since 8.9.0 |
||
| 467 | * |
||
| 468 | * @to-do: deprecate and switch to /wp/v2/plugins when WordPress 5.5 is the minimum required version. |
||
| 469 | * Noting that the `source` parameter is Jetpack-specific (not implemented in Core). |
||
| 470 | */ |
||
| 471 | register_rest_route( |
||
| 472 | 'jetpack/v4', |
||
| 473 | '/plugins/(?P<plugin>[^.\/]+(?:\/[^.\/]+)?)', |
||
| 474 | array( |
||
| 475 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 476 | 'callback' => __CLASS__ . '::activate_plugin', |
||
| 477 | 'permission_callback' => __CLASS__ . '::activate_plugins_permission_check', |
||
| 478 | 'args' => array( |
||
| 479 | 'status' => array( |
||
| 480 | 'required' => true, |
||
| 481 | 'type' => 'string', |
||
| 482 | 'validate_callback' => __CLASS__ . '::validate_activate_plugin', |
||
| 483 | ), |
||
| 484 | 'source' => array( |
||
| 485 | 'required' => false, |
||
| 486 | 'type' => 'string', |
||
| 487 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 488 | ), |
||
| 489 | ), |
||
| 490 | ) |
||
| 491 | ); |
||
| 492 | |||
| 493 | /** |
||
| 494 | * Install and Activate the Akismet plugin. |
||
| 495 | * |
||
| 496 | * @deprecated 8.9.0 Use the /plugins route instead. |
||
| 497 | */ |
||
| 498 | register_rest_route( |
||
| 499 | 'jetpack/v4', |
||
| 500 | '/plugins/akismet/activate', |
||
| 501 | array( |
||
| 502 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 503 | 'callback' => __CLASS__ . '::activate_akismet', |
||
| 504 | 'permission_callback' => __CLASS__ . '::activate_plugins_permission_check', |
||
| 505 | ) |
||
| 506 | ); |
||
| 507 | |||
| 508 | // Plugins: check if the plugin is active. |
||
| 509 | register_rest_route( 'jetpack/v4', '/plugin/(?P<plugin>[a-z\/\.\-_]+)', array( |
||
| 510 | 'methods' => WP_REST_Server::READABLE, |
||
| 511 | 'callback' => __CLASS__ . '::get_plugin', |
||
| 512 | 'permission_callback' => __CLASS__ . '::activate_plugins_permission_check', |
||
| 513 | ) ); |
||
| 514 | |||
| 515 | // Widgets: get information about a widget that supports it. |
||
| 516 | register_rest_route( 'jetpack/v4', '/widgets/(?P<id>[0-9a-z\-_]+)', array( |
||
| 517 | 'methods' => WP_REST_Server::READABLE, |
||
| 518 | 'callback' => array( $widget_endpoint, 'process' ), |
||
| 519 | 'permission_callback' => array( $widget_endpoint, 'can_request' ), |
||
| 520 | ) ); |
||
| 521 | |||
| 522 | // Site Verify: check if the site is verified, and a get verification token if not |
||
| 523 | register_rest_route( 'jetpack/v4', '/verify-site/(?P<service>[a-z\-_]+)', array( |
||
| 524 | 'methods' => WP_REST_Server::READABLE, |
||
| 525 | 'callback' => __CLASS__ . '::is_site_verified_and_token', |
||
| 526 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 527 | ) ); |
||
| 528 | |||
| 529 | register_rest_route( 'jetpack/v4', '/verify-site/(?P<service>[a-z\-_]+)/(?<keyring_id>[0-9]+)', array( |
||
| 530 | 'methods' => WP_REST_Server::READABLE, |
||
| 531 | 'callback' => __CLASS__ . '::is_site_verified_and_token', |
||
| 532 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 533 | ) ); |
||
| 534 | |||
| 535 | // Site Verify: tell a service to verify the site |
||
| 536 | register_rest_route( 'jetpack/v4', '/verify-site/(?P<service>[a-z\-_]+)', array( |
||
| 537 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 538 | 'callback' => __CLASS__ . '::verify_site', |
||
| 539 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 540 | 'args' => array( |
||
| 541 | 'keyring_id' => array( |
||
| 542 | 'required' => true, |
||
| 543 | 'type' => 'integer', |
||
| 544 | 'validate_callback' => __CLASS__ . '::validate_posint', |
||
| 545 | ), |
||
| 546 | ) |
||
| 547 | ) ); |
||
| 548 | |||
| 549 | // Get and set API keys. |
||
| 550 | // Note: permission_callback intentionally omitted from the GET method. |
||
| 551 | // Map block requires open access to API keys on the front end. |
||
| 552 | register_rest_route( |
||
| 553 | 'jetpack/v4', |
||
| 554 | '/service-api-keys/(?P<service>[a-z\-_]+)', |
||
| 555 | array( |
||
| 556 | array( |
||
| 557 | 'methods' => WP_REST_Server::READABLE, |
||
| 558 | 'callback' => __CLASS__ . '::get_service_api_key', |
||
| 559 | 'permission_callback' => '__return_true', |
||
| 560 | ), |
||
| 561 | array( |
||
| 562 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 563 | 'callback' => __CLASS__ . '::update_service_api_key', |
||
| 564 | 'permission_callback' => array( 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys','edit_others_posts_check' ), |
||
| 565 | 'args' => array( |
||
| 566 | 'service_api_key' => array( |
||
| 567 | 'required' => true, |
||
| 568 | 'type' => 'text', |
||
| 569 | ), |
||
| 570 | ), |
||
| 571 | ), |
||
| 572 | array( |
||
| 573 | 'methods' => WP_REST_Server::DELETABLE, |
||
| 574 | 'callback' => __CLASS__ . '::delete_service_api_key', |
||
| 575 | 'permission_callback' => array( 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys','edit_others_posts_check' ), |
||
| 576 | ), |
||
| 577 | ) |
||
| 578 | ); |
||
| 579 | |||
| 580 | register_rest_route( |
||
| 581 | 'jetpack/v4', |
||
| 582 | '/mobile/send-login-email', |
||
| 583 | array( |
||
| 584 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 585 | 'callback' => __CLASS__ . '::send_mobile_magic_link', |
||
| 586 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 587 | ) |
||
| 588 | ); |
||
| 589 | |||
| 590 | /* |
||
| 591 | * Get and update settings from the Jetpack wizard. |
||
| 592 | */ |
||
| 593 | register_rest_route( |
||
| 594 | 'jetpack/v4', |
||
| 595 | '/setup/questionnaire', |
||
| 596 | array( |
||
| 597 | array( |
||
| 598 | 'methods' => WP_REST_Server::READABLE, |
||
| 599 | 'callback' => __CLASS__ . '::get_setup_wizard_questionnaire', |
||
| 600 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 601 | ), |
||
| 602 | array( |
||
| 603 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 604 | 'callback' => __CLASS__ . '::update_setup_wizard_questionnaire', |
||
| 605 | 'permission_callback' => __CLASS__ . '::update_settings_permission_check', |
||
| 606 | 'args' => array( |
||
| 607 | 'questionnaire' => array( |
||
| 608 | 'required' => false, |
||
| 609 | 'type' => 'object', |
||
| 610 | 'validate_callback' => __CLASS__ . '::validate_setup_wizard_questionnaire', |
||
| 611 | ), |
||
| 612 | 'status' => array( |
||
| 613 | 'required' => false, |
||
| 614 | 'type' => 'string', |
||
| 615 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 616 | ), |
||
| 617 | ), |
||
| 618 | ), |
||
| 619 | ) |
||
| 620 | ); |
||
| 621 | |||
| 622 | /* |
||
| 623 | * Get and update the last licensing error message. |
||
| 624 | */ |
||
| 625 | register_rest_route( |
||
| 626 | 'jetpack/v4', |
||
| 627 | '/licensing/error', |
||
| 628 | array( |
||
| 629 | array( |
||
| 630 | 'methods' => WP_REST_Server::READABLE, |
||
| 631 | 'callback' => __CLASS__ . '::get_licensing_error', |
||
| 632 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 633 | ), |
||
| 634 | array( |
||
| 635 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 636 | 'callback' => __CLASS__ . '::update_licensing_error', |
||
| 637 | 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check', |
||
| 638 | 'args' => array( |
||
| 639 | 'error' => array( |
||
| 640 | 'required' => true, |
||
| 641 | 'type' => 'string', |
||
| 642 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 643 | 'sanitize_callback' => 'sanitize_text_field', |
||
| 644 | ), |
||
| 645 | ), |
||
| 646 | ), |
||
| 647 | ) |
||
| 648 | ); |
||
| 649 | |||
| 650 | /* |
||
| 651 | * Manage the Jetpack CRM plugin's integration with Jetpack contact forms. |
||
| 652 | */ |
||
| 653 | register_rest_route( |
||
| 654 | 'jetpack/v4', |
||
| 655 | 'jetpack_crm', |
||
| 656 | array( |
||
| 657 | array( |
||
| 658 | 'methods' => WP_REST_Server::READABLE, |
||
| 659 | 'callback' => __CLASS__ . '::get_jetpack_crm_data', |
||
| 660 | 'permission_callback' => __CLASS__ . '::jetpack_crm_data_permission_check', |
||
| 661 | ), |
||
| 662 | array( |
||
| 663 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 664 | 'callback' => __CLASS__ . '::activate_crm_jetpack_forms_extension', |
||
| 665 | 'permission_callback' => __CLASS__ . '::activate_crm_extensions_permission_check', |
||
| 666 | 'args' => array( |
||
| 667 | 'extension' => array( |
||
| 668 | 'required' => true, |
||
| 669 | 'type' => 'text', |
||
| 670 | ), |
||
| 671 | ), |
||
| 672 | ), |
||
| 673 | ) |
||
| 674 | ); |
||
| 675 | } |
||
| 676 | |||
| 677 | /** |
||
| 678 | * Get the settings for the wizard questionnaire |
||
| 679 | * |
||
| 680 | * @return array Questionnaire settings. |
||
| 681 | */ |
||
| 682 | public static function get_setup_wizard_questionnaire() { |
||
| 683 | return Jetpack_Options::get_option( 'setup_wizard_questionnaire', (object) array() ); |
||
| 684 | } |
||
| 685 | |||
| 686 | /** |
||
| 687 | * Update the settings selected on the wizard questionnaire |
||
| 688 | * |
||
| 689 | * @param WP_REST_Request $request The request. |
||
| 690 | * |
||
| 691 | * @return bool true. |
||
| 692 | */ |
||
| 693 | public static function update_setup_wizard_questionnaire( $request ) { |
||
| 694 | $questionnaire = $request['questionnaire']; |
||
| 695 | if ( ! empty( $questionnaire ) ) { |
||
| 696 | Jetpack_Options::update_option( 'setup_wizard_questionnaire', $questionnaire ); |
||
| 697 | } |
||
| 698 | |||
| 699 | $status = $request['status']; |
||
| 700 | if ( ! empty( $status ) ) { |
||
| 701 | Jetpack_Options::update_option( 'setup_wizard_status', $status ); |
||
| 702 | } |
||
| 703 | |||
| 704 | return true; |
||
| 705 | } |
||
| 706 | |||
| 707 | /** |
||
| 708 | * Validate the answers on the setup wizard questionnaire |
||
| 709 | * |
||
| 710 | * @param array $value Value to check received by request. |
||
| 711 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 712 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 713 | * |
||
| 714 | * @return bool|WP_Error |
||
| 715 | */ |
||
| 716 | public static function validate_setup_wizard_questionnaire( $value, $request, $param ) { |
||
| 717 | View Code Duplication | if ( ! is_array( $value ) ) { |
|
| 718 | /* translators: Name of a parameter that must be an object */ |
||
| 719 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an object.', 'jetpack' ), $param ) ); |
||
| 720 | } |
||
| 721 | |||
| 722 | foreach ( $value as $answer_key => $answer ) { |
||
| 723 | if ( is_string( $answer ) ) { |
||
| 724 | $validate = self::validate_string( $answer, $request, $param ); |
||
| 725 | } else { |
||
| 726 | $validate = self::validate_boolean( $answer, $request, $param ); |
||
| 727 | } |
||
| 728 | |||
| 729 | if ( is_wp_error( $validate ) ) { |
||
| 730 | return $validate; |
||
| 731 | } |
||
| 732 | } |
||
| 733 | |||
| 734 | return true; |
||
| 735 | } |
||
| 736 | |||
| 737 | public static function get_plans( $request ) { |
||
| 738 | $request = Client::wpcom_json_api_request_as_user( |
||
| 739 | '/plans?_locale=' . get_user_locale(), |
||
| 740 | '2', |
||
| 741 | array( |
||
| 742 | 'method' => 'GET', |
||
| 743 | 'headers' => array( |
||
| 744 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 745 | ), |
||
| 746 | ) |
||
| 747 | ); |
||
| 748 | |||
| 749 | $body = json_decode( wp_remote_retrieve_body( $request ) ); |
||
| 750 | if ( 200 === wp_remote_retrieve_response_code( $request ) ) { |
||
| 751 | $data = $body; |
||
| 752 | } else { |
||
| 753 | // something went wrong so we'll just return the response without caching |
||
| 754 | return $body; |
||
| 755 | } |
||
| 756 | |||
| 757 | return $data; |
||
| 758 | } |
||
| 759 | |||
| 760 | /** |
||
| 761 | * Gets the WP.com products that are in use on wpcom. |
||
| 762 | * Similar to the WP.com plans that we currently in user on WPCOM. |
||
| 763 | * |
||
| 764 | * @param WP_REST_Request $request The request. |
||
| 765 | * |
||
| 766 | * @return string|WP_Error A JSON object of wpcom products if the request was successful, or a WP_Error otherwise. |
||
| 767 | */ |
||
| 768 | public static function get_products( $request ) { |
||
| 769 | $wpcom_request = Client::wpcom_json_api_request_as_user( |
||
| 770 | '/products?_locale=' . get_user_locale() . '&type=jetpack', |
||
| 771 | '2', |
||
| 772 | array( |
||
| 773 | 'method' => 'GET', |
||
| 774 | 'headers' => array( |
||
| 775 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 776 | ), |
||
| 777 | ) |
||
| 778 | ); |
||
| 779 | |||
| 780 | $response_code = wp_remote_retrieve_response_code( $wpcom_request ); |
||
| 781 | if ( 200 === $response_code ) { |
||
| 782 | return json_decode( wp_remote_retrieve_body( $wpcom_request ) ); |
||
| 783 | } else { |
||
| 784 | // Something went wrong so we'll just return the response without caching. |
||
| 785 | return new WP_Error( |
||
| 786 | 'failed_to_fetch_data', |
||
| 787 | esc_html__( 'Unable to fetch the requested data.', 'jetpack' ), |
||
| 788 | array( 'status' => $response_code ) |
||
| 789 | ); |
||
| 790 | } |
||
| 791 | } |
||
| 792 | |||
| 793 | public static function submit_survey( $request ) { |
||
| 794 | |||
| 795 | $wpcom_request = Client::wpcom_json_api_request_as_user( |
||
| 796 | '/marketing/survey', |
||
| 797 | 'v2', |
||
| 798 | array( |
||
| 799 | 'method' => 'POST', |
||
| 800 | 'headers' => array( |
||
| 801 | 'Content-Type' => 'application/json', |
||
| 802 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 803 | ), |
||
| 804 | ), |
||
| 805 | $request->get_json_params() |
||
| 806 | ); |
||
| 807 | |||
| 808 | $wpcom_request_body = json_decode( wp_remote_retrieve_body( $wpcom_request ) ); |
||
| 809 | if ( 200 === wp_remote_retrieve_response_code( $wpcom_request ) ) { |
||
| 810 | $data = $wpcom_request_body; |
||
| 811 | } else { |
||
| 812 | // something went wrong so we'll just return the response without caching |
||
| 813 | return $wpcom_request_body; |
||
| 814 | } |
||
| 815 | |||
| 816 | return $data; |
||
| 817 | } |
||
| 818 | |||
| 819 | /** |
||
| 820 | * Asks for a jitm, unless they've been disabled, in which case it returns an empty array |
||
| 821 | * |
||
| 822 | * @param $request WP_REST_Request |
||
| 823 | * |
||
| 824 | * @return array An array of jitms |
||
| 825 | */ |
||
| 826 | public static function get_jitm_message( $request ) { |
||
| 827 | $jitm = JITM::get_instance(); |
||
| 828 | |||
| 829 | if ( ! $jitm->register() ) { |
||
| 830 | return array(); |
||
| 831 | } |
||
| 832 | |||
| 833 | return $jitm->get_messages( $request['message_path'], urldecode_deep( $request['query'] ), 'true' === $request['full_jp_logo_exists'] ? true : false ); |
||
| 834 | } |
||
| 835 | |||
| 836 | /** |
||
| 837 | * Dismisses a jitm. |
||
| 838 | * |
||
| 839 | * @param WP_REST_Request $request The request. |
||
| 840 | * |
||
| 841 | * @return bool Always True |
||
| 842 | */ |
||
| 843 | public static function delete_jitm_message( $request ) { |
||
| 844 | $jitm = JITM::get_instance(); |
||
| 845 | |||
| 846 | if ( ! $jitm->register() ) { |
||
| 847 | return true; |
||
| 848 | } |
||
| 849 | |||
| 850 | return $jitm->dismiss( $request['id'], $request['feature_class'] ); |
||
| 851 | } |
||
| 852 | |||
| 853 | /** |
||
| 854 | * Checks if this site has been verified using a service - only 'google' supported at present - and a specfic |
||
| 855 | * keyring to use to get the token if it is not |
||
| 856 | * |
||
| 857 | * Returns 'verified' = true/false, and a token if 'verified' is false and site is ready for verification |
||
| 858 | * |
||
| 859 | * @since 6.6.0 |
||
| 860 | * |
||
| 861 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 862 | * |
||
| 863 | * @return array|wp-error |
||
| 864 | */ |
||
| 865 | public static function is_site_verified_and_token( $request ) { |
||
| 866 | /** |
||
| 867 | * Return an error if the site uses a Maintenance / Coming Soon plugin |
||
| 868 | * and if the plugin is configured to make the site private. |
||
| 869 | * |
||
| 870 | * We currently handle the following plugins: |
||
| 871 | * - https://github.com/mojoness/mojo-marketplace-wp-plugin (used by bluehost) |
||
| 872 | * - https://wordpress.org/plugins/mojo-under-construction |
||
| 873 | * - https://wordpress.org/plugins/under-construction-page |
||
| 874 | * - https://wordpress.org/plugins/ultimate-under-construction |
||
| 875 | * - https://wordpress.org/plugins/coming-soon |
||
| 876 | * |
||
| 877 | * You can handle this in your own plugin thanks to the `jetpack_is_under_construction_plugin` filter. |
||
| 878 | * If the filter returns true, we will consider the site as under construction. |
||
| 879 | */ |
||
| 880 | $mm_coming_soon = get_option( 'mm_coming_soon', null ); |
||
| 881 | $under_construction_activation_status = get_option( 'underConstructionActivationStatus', null ); |
||
| 882 | $ucp_options = get_option( 'ucp_options', array() ); |
||
| 883 | $uuc_settings = get_option( 'uuc_settings', array() ); |
||
| 884 | $csp4 = get_option( 'seed_csp4_settings_content', array() ); |
||
| 885 | if ( |
||
| 886 | ( Jetpack::is_plugin_active( 'mojo-marketplace-wp-plugin/mojo-marketplace.php' ) && 'true' === $mm_coming_soon ) |
||
| 887 | || Jetpack::is_plugin_active( 'mojo-under-construction/mojo-contruction.php' ) && 1 == $under_construction_activation_status // WPCS: loose comparison ok. |
||
| 888 | || ( Jetpack::is_plugin_active( 'under-construction-page/under-construction.php' ) && isset( $ucp_options['status'] ) && 1 == $ucp_options['status'] ) // WPCS: loose comparison ok. |
||
| 889 | || ( Jetpack::is_plugin_active( 'ultimate-under-construction/ultimate-under-construction.php' ) && isset( $uuc_settings['enable'] ) && 1 == $uuc_settings['enable'] ) // WPCS: loose comparison ok. |
||
| 890 | || ( Jetpack::is_plugin_active( 'coming-soon/coming-soon.php' ) && isset( $csp4['status'] ) && ( 1 == $csp4['status'] || 2 == $csp4['status'] ) ) // WPCS: loose comparison ok. |
||
| 891 | /** |
||
| 892 | * Allow plugins to mark a site as "under construction". |
||
| 893 | * |
||
| 894 | * @since 6.7.0 |
||
| 895 | * |
||
| 896 | * @param false bool Is the site under construction? Default to false. |
||
| 897 | */ |
||
| 898 | || true === apply_filters( 'jetpack_is_under_construction_plugin', false ) |
||
| 899 | ) { |
||
| 900 | return new WP_Error( 'forbidden', __( 'Site is under construction and cannot be verified', 'jetpack' ) ); |
||
| 901 | } |
||
| 902 | |||
| 903 | $xml = new Jetpack_IXR_Client( array( |
||
| 904 | 'user_id' => get_current_user_id(), |
||
| 905 | ) ); |
||
| 906 | |||
| 907 | $args = array( |
||
| 908 | 'user_id' => get_current_user_id(), |
||
| 909 | 'service' => $request[ 'service' ], |
||
| 910 | ); |
||
| 911 | |||
| 912 | if ( isset( $request[ 'keyring_id' ] ) ) { |
||
| 913 | $args[ 'keyring_id' ] = $request[ 'keyring_id' ]; |
||
| 914 | } |
||
| 915 | |||
| 916 | $xml->query( 'jetpack.isSiteVerified', $args ); |
||
| 917 | |||
| 918 | View Code Duplication | if ( $xml->isError() ) { |
|
| 919 | return new WP_Error( 'error_checking_if_site_verified_google', sprintf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() ) ); |
||
| 920 | } else { |
||
| 921 | return $xml->getResponse(); |
||
| 922 | } |
||
| 923 | } |
||
| 924 | |||
| 925 | |||
| 926 | |||
| 927 | public static function verify_site( $request ) { |
||
| 928 | $xml = new Jetpack_IXR_Client( array( |
||
| 929 | 'user_id' => get_current_user_id(), |
||
| 930 | ) ); |
||
| 931 | |||
| 932 | $params = $request->get_json_params(); |
||
| 933 | |||
| 934 | $xml->query( 'jetpack.verifySite', array( |
||
| 935 | 'user_id' => get_current_user_id(), |
||
| 936 | 'service' => $request[ 'service' ], |
||
| 937 | 'keyring_id' => $params[ 'keyring_id' ], |
||
| 938 | ) |
||
| 939 | ); |
||
| 940 | |||
| 941 | if ( $xml->isError() ) { |
||
| 942 | return new WP_Error( 'error_verifying_site_google', sprintf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() ) ); |
||
| 943 | } else { |
||
| 944 | $response = $xml->getResponse(); |
||
| 945 | |||
| 946 | if ( ! empty( $response['errors'] ) ) { |
||
| 947 | $error = new WP_Error; |
||
| 948 | $error->errors = $response['errors']; |
||
| 949 | return $error; |
||
| 950 | } |
||
| 951 | |||
| 952 | return $response; |
||
| 953 | } |
||
| 954 | } |
||
| 955 | |||
| 956 | /** |
||
| 957 | * Handles verification that a site is registered |
||
| 958 | * |
||
| 959 | * @since 5.4.0 |
||
| 960 | * @deprecated 8.8.0 The method is moved to the `REST_Connector` class. |
||
| 961 | * |
||
| 962 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 963 | * |
||
| 964 | * @return array|wp-error |
||
| 965 | */ |
||
| 966 | public static function remote_authorize( $request ) { |
||
| 967 | _deprecated_function( __METHOD__, 'jetpack-8.8.0', '\Automattic\Jetpack\Connection\REST_Connector::remote_authorize' ); |
||
| 968 | return REST_Connector::remote_authorize( $request ); |
||
| 969 | } |
||
| 970 | |||
| 971 | /** |
||
| 972 | * Handles dismissing of Jetpack Notices |
||
| 973 | * |
||
| 974 | * @since 4.3.0 |
||
| 975 | * |
||
| 976 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 977 | * |
||
| 978 | * @return array|wp-error |
||
| 979 | */ |
||
| 980 | public static function dismiss_notice( $request ) { |
||
| 981 | $notice = $request['notice']; |
||
| 982 | |||
| 983 | if ( ! isset( $request['dismissed'] ) || $request['dismissed'] !== true ) { |
||
| 984 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid parameter "dismissed".', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 985 | } |
||
| 986 | |||
| 987 | if ( isset( $notice ) && ! empty( $notice ) ) { |
||
| 988 | switch( $notice ) { |
||
| 989 | case 'feedback_dash_request': |
||
| 990 | case 'welcome': |
||
| 991 | $notices = get_option( 'jetpack_dismissed_notices', array() ); |
||
| 992 | $notices[ $notice ] = true; |
||
| 993 | update_option( 'jetpack_dismissed_notices', $notices ); |
||
| 994 | return rest_ensure_response( get_option( 'jetpack_dismissed_notices', array() ) ); |
||
| 995 | |||
| 996 | default: |
||
| 997 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid parameter "notice".', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 998 | } |
||
| 999 | } |
||
| 1000 | |||
| 1001 | return new WP_Error( 'required_param', esc_html__( 'Missing parameter "notice".', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1002 | } |
||
| 1003 | |||
| 1004 | /** |
||
| 1005 | * Verify that the user can disconnect the site. |
||
| 1006 | * |
||
| 1007 | * @since 4.3.0 |
||
| 1008 | * |
||
| 1009 | * @return bool|WP_Error True if user is able to disconnect the site. |
||
| 1010 | */ |
||
| 1011 | View Code Duplication | public static function disconnect_site_permission_callback() { |
|
| 1012 | if ( current_user_can( 'jetpack_disconnect' ) ) { |
||
| 1013 | return true; |
||
| 1014 | } |
||
| 1015 | |||
| 1016 | return new WP_Error( 'invalid_user_permission_jetpack_disconnect', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1017 | |||
| 1018 | } |
||
| 1019 | |||
| 1020 | /** |
||
| 1021 | * Verify that the user can dismiss JITM messages. |
||
| 1022 | * |
||
| 1023 | * @since 8.8.0 |
||
| 1024 | * |
||
| 1025 | * @return bool|WP_Error True if user is able to dismiss JITM messages. |
||
| 1026 | */ |
||
| 1027 | public static function delete_jitm_message_permission_callback() { |
||
| 1028 | if ( current_user_can( 'read' ) ) { |
||
| 1029 | return true; |
||
| 1030 | } |
||
| 1031 | |||
| 1032 | return new WP_Error( 'invalid_user_permission_jetpack_delete_jitm_message', self::$user_permissions_error_msg, array( 'status' => self::rest_authorization_required_code() ) ); |
||
| 1033 | } |
||
| 1034 | |||
| 1035 | /** |
||
| 1036 | * Verify that the user can get a connect/link URL |
||
| 1037 | * |
||
| 1038 | * @since 4.3.0 |
||
| 1039 | * |
||
| 1040 | * @return bool|WP_Error True if user is able to disconnect the site. |
||
| 1041 | */ |
||
| 1042 | View Code Duplication | public static function connect_url_permission_callback() { |
|
| 1043 | if ( current_user_can( 'jetpack_connect_user' ) ) { |
||
| 1044 | return true; |
||
| 1045 | } |
||
| 1046 | |||
| 1047 | return new WP_Error( 'invalid_user_permission_jetpack_connect', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1048 | |||
| 1049 | } |
||
| 1050 | |||
| 1051 | /** |
||
| 1052 | * Verify that a user can get the data about the current user. |
||
| 1053 | * Only those who can connect. |
||
| 1054 | * |
||
| 1055 | * @since 4.3.0 |
||
| 1056 | * |
||
| 1057 | * @uses Jetpack::is_user_connected(); |
||
| 1058 | * |
||
| 1059 | * @return bool|WP_Error True if user is able to unlink. |
||
| 1060 | */ |
||
| 1061 | View Code Duplication | public static function get_user_connection_data_permission_callback() { |
|
| 1062 | if ( current_user_can( 'jetpack_connect_user' ) ) { |
||
| 1063 | return true; |
||
| 1064 | } |
||
| 1065 | |||
| 1066 | return new WP_Error( 'invalid_user_permission_user_connection_data', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1067 | } |
||
| 1068 | |||
| 1069 | /** |
||
| 1070 | * Check that user has permission to change the master user. |
||
| 1071 | * |
||
| 1072 | * @since 6.2.0 |
||
| 1073 | * @since 7.7.0 Update so that any user with jetpack_disconnect privs can set owner. |
||
| 1074 | * |
||
| 1075 | * @return bool|WP_Error True if user is able to change master user. |
||
| 1076 | */ |
||
| 1077 | View Code Duplication | public static function set_connection_owner_permission_callback() { |
|
| 1078 | if ( current_user_can( 'jetpack_disconnect' ) ) { |
||
| 1079 | return true; |
||
| 1080 | } |
||
| 1081 | |||
| 1082 | return new WP_Error( 'invalid_user_permission_set_connection_owner', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1083 | } |
||
| 1084 | |||
| 1085 | /** |
||
| 1086 | * Verify that a user can use the /connection/user endpoint. Has to be a registered user and be currently linked. |
||
| 1087 | * |
||
| 1088 | * @since 4.3.0 |
||
| 1089 | * |
||
| 1090 | * @uses Jetpack::is_user_connected(); |
||
| 1091 | * |
||
| 1092 | * @return bool|WP_Error True if user is able to unlink. |
||
| 1093 | */ |
||
| 1094 | public static function unlink_user_permission_callback() { |
||
| 1095 | if ( current_user_can( 'jetpack_connect_user' ) && Jetpack::is_user_connected( get_current_user_id() ) ) { |
||
| 1096 | return true; |
||
| 1097 | } |
||
| 1098 | |||
| 1099 | return new WP_Error( 'invalid_user_permission_unlink_user', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1100 | } |
||
| 1101 | |||
| 1102 | /** |
||
| 1103 | * Verify that user can manage Jetpack modules. |
||
| 1104 | * |
||
| 1105 | * @since 4.3.0 |
||
| 1106 | * |
||
| 1107 | * @return bool Whether user has the capability 'jetpack_manage_modules'. |
||
| 1108 | */ |
||
| 1109 | public static function manage_modules_permission_check() { |
||
| 1110 | if ( current_user_can( 'jetpack_manage_modules' ) ) { |
||
| 1111 | return true; |
||
| 1112 | } |
||
| 1113 | |||
| 1114 | return new WP_Error( 'invalid_user_permission_manage_modules', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1115 | } |
||
| 1116 | |||
| 1117 | /** |
||
| 1118 | * Verify that user can update Jetpack modules. |
||
| 1119 | * |
||
| 1120 | * @since 4.3.0 |
||
| 1121 | * |
||
| 1122 | * @return bool Whether user has the capability 'jetpack_configure_modules'. |
||
| 1123 | */ |
||
| 1124 | View Code Duplication | public static function configure_modules_permission_check() { |
|
| 1125 | if ( current_user_can( 'jetpack_configure_modules' ) ) { |
||
| 1126 | return true; |
||
| 1127 | } |
||
| 1128 | |||
| 1129 | return new WP_Error( 'invalid_user_permission_configure_modules', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1130 | } |
||
| 1131 | |||
| 1132 | /** |
||
| 1133 | * Verify that user can view Jetpack admin page. |
||
| 1134 | * |
||
| 1135 | * @since 4.3.0 |
||
| 1136 | * |
||
| 1137 | * @return bool Whether user has the capability 'jetpack_admin_page'. |
||
| 1138 | */ |
||
| 1139 | public static function view_admin_page_permission_check() { |
||
| 1140 | if ( current_user_can( 'jetpack_admin_page' ) ) { |
||
| 1141 | return true; |
||
| 1142 | } |
||
| 1143 | |||
| 1144 | return new WP_Error( 'invalid_user_permission_view_admin', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1145 | } |
||
| 1146 | |||
| 1147 | /** |
||
| 1148 | * Verify that user can mitigate an identity crisis. |
||
| 1149 | * |
||
| 1150 | * @since 4.4.0 |
||
| 1151 | * |
||
| 1152 | * @return bool Whether user has capability 'jetpack_disconnect'. |
||
| 1153 | */ |
||
| 1154 | View Code Duplication | public static function identity_crisis_mitigation_permission_check() { |
|
| 1155 | if ( current_user_can( 'jetpack_disconnect' ) ) { |
||
| 1156 | return true; |
||
| 1157 | } |
||
| 1158 | |||
| 1159 | return new WP_Error( 'invalid_user_permission_identity_crisis', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1160 | } |
||
| 1161 | |||
| 1162 | /** |
||
| 1163 | * Verify that user can update Jetpack general settings. |
||
| 1164 | * |
||
| 1165 | * @since 4.3.0 |
||
| 1166 | * |
||
| 1167 | * @return bool Whether user has the capability 'update_settings_permission_check'. |
||
| 1168 | */ |
||
| 1169 | View Code Duplication | public static function update_settings_permission_check() { |
|
| 1170 | if ( current_user_can( 'jetpack_configure_modules' ) ) { |
||
| 1171 | return true; |
||
| 1172 | } |
||
| 1173 | |||
| 1174 | return new WP_Error( 'invalid_user_permission_manage_settings', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1175 | } |
||
| 1176 | |||
| 1177 | /** |
||
| 1178 | * Verify that user can view Jetpack admin page and can activate plugins. |
||
| 1179 | * |
||
| 1180 | * @since 4.3.0 |
||
| 1181 | * |
||
| 1182 | * @return bool Whether user has the capability 'jetpack_admin_page' and 'activate_plugins'. |
||
| 1183 | */ |
||
| 1184 | public static function activate_plugins_permission_check() { |
||
| 1185 | if ( current_user_can( 'jetpack_admin_page' ) && current_user_can( 'activate_plugins' ) ) { |
||
| 1186 | return true; |
||
| 1187 | } |
||
| 1188 | |||
| 1189 | return new WP_Error( 'invalid_user_permission_activate_plugins', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) ); |
||
| 1190 | } |
||
| 1191 | |||
| 1192 | /** |
||
| 1193 | * Verify that user can edit other's posts (Editors and Administrators). |
||
| 1194 | * |
||
| 1195 | * @return bool Whether user has the capability 'edit_others_posts'. |
||
| 1196 | */ |
||
| 1197 | public static function edit_others_posts_check() { |
||
| 1198 | if ( current_user_can( 'edit_others_posts' ) ) { |
||
| 1199 | return true; |
||
| 1200 | } |
||
| 1201 | |||
| 1202 | return new WP_Error( 'invalid_user_permission_edit_others_posts', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) ); |
||
| 1203 | } |
||
| 1204 | |||
| 1205 | /** |
||
| 1206 | * Deprecated - Contextual HTTP error code for authorization failure. |
||
| 1207 | * |
||
| 1208 | * @deprecated since version 8.8.0. |
||
| 1209 | * |
||
| 1210 | * Taken from rest_authorization_required_code() in WP-API plugin until is added to core. |
||
| 1211 | * @see https://github.com/WP-API/WP-API/commit/7ba0ae6fe4f605d5ffe4ee85b1cd5f9fb46900a6 |
||
| 1212 | * |
||
| 1213 | * @since 4.3.0 |
||
| 1214 | * |
||
| 1215 | * @return int |
||
| 1216 | */ |
||
| 1217 | public static function rest_authorization_required_code() { |
||
| 1218 | _deprecated_function( __METHOD__, 'jetpack-8.8.0', 'rest_authorization_required_code' ); |
||
| 1219 | return rest_authorization_required_code(); |
||
| 1220 | } |
||
| 1221 | |||
| 1222 | /** |
||
| 1223 | * Get connection status for this Jetpack site. |
||
| 1224 | * |
||
| 1225 | * @since 4.3.0 |
||
| 1226 | * |
||
| 1227 | * @return WP_REST_Response Connection information. |
||
| 1228 | */ |
||
| 1229 | public static function jetpack_connection_status() { |
||
| 1230 | _deprecated_function( __METHOD__, 'jetpack-8.8.0', '\Automattic\Jetpack\Connection\REST_Connector::connection_status' ); |
||
| 1231 | return REST_Connector::connection_status(); |
||
| 1232 | } |
||
| 1233 | |||
| 1234 | /** |
||
| 1235 | * Test connection status for this Jetpack site. |
||
| 1236 | * |
||
| 1237 | * @since 6.8.0 |
||
| 1238 | * |
||
| 1239 | * @return array|WP_Error WP_Error returned if connection test does not succeed. |
||
| 1240 | */ |
||
| 1241 | public static function jetpack_connection_test() { |
||
| 1242 | jetpack_require_lib( 'debugger' ); |
||
| 1243 | $cxntests = new Jetpack_Cxn_Tests(); |
||
| 1244 | |||
| 1245 | if ( $cxntests->pass() ) { |
||
| 1246 | return rest_ensure_response( |
||
| 1247 | array( |
||
| 1248 | 'code' => 'success', |
||
| 1249 | 'message' => __( 'All connection tests passed.', 'jetpack' ), |
||
| 1250 | ) |
||
| 1251 | ); |
||
| 1252 | } else { |
||
| 1253 | return $cxntests->output_fails_as_wp_error(); |
||
| 1254 | } |
||
| 1255 | } |
||
| 1256 | |||
| 1257 | /** |
||
| 1258 | * Test connection permission check method. |
||
| 1259 | * |
||
| 1260 | * @since 7.1.0 |
||
| 1261 | * |
||
| 1262 | * @return bool |
||
| 1263 | */ |
||
| 1264 | public static function view_jetpack_connection_test_check() { |
||
| 1265 | if ( ! isset( $_GET['signature'], $_GET['timestamp'], $_GET['url'] ) ) { |
||
| 1266 | return false; |
||
| 1267 | } |
||
| 1268 | $signature = base64_decode( $_GET['signature'] ); |
||
| 1269 | |||
| 1270 | $signature_data = wp_json_encode( |
||
| 1271 | array( |
||
| 1272 | 'rest_route' => $_GET['rest_route'], |
||
| 1273 | 'timestamp' => (int) $_GET['timestamp'], |
||
| 1274 | 'url' => wp_unslash( $_GET['url'] ), |
||
| 1275 | ) |
||
| 1276 | ); |
||
| 1277 | |||
| 1278 | if ( |
||
| 1279 | ! function_exists( 'openssl_verify' ) |
||
| 1280 | || 1 !== openssl_verify( |
||
| 1281 | $signature_data, |
||
| 1282 | $signature, |
||
| 1283 | JETPACK__DEBUGGER_PUBLIC_KEY |
||
| 1284 | ) |
||
| 1285 | ) { |
||
| 1286 | return false; |
||
| 1287 | } |
||
| 1288 | |||
| 1289 | // signature timestamp must be within 5min of current time |
||
| 1290 | if ( abs( time() - (int) $_GET['timestamp'] ) > 300 ) { |
||
| 1291 | return false; |
||
| 1292 | } |
||
| 1293 | |||
| 1294 | return true; |
||
| 1295 | } |
||
| 1296 | |||
| 1297 | /** |
||
| 1298 | * Test connection status for this Jetpack site, encrypt the results for decryption by a third-party. |
||
| 1299 | * |
||
| 1300 | * @since 7.1.0 |
||
| 1301 | * |
||
| 1302 | * @return array|mixed|object|WP_Error |
||
| 1303 | */ |
||
| 1304 | public static function jetpack_connection_test_for_external() { |
||
| 1305 | // Since we are running this test for inclusion in the WP.com testing suite, let's not try to run them as part of these results. |
||
| 1306 | add_filter( 'jetpack_debugger_run_self_test', '__return_false' ); |
||
| 1307 | jetpack_require_lib( 'debugger' ); |
||
| 1308 | $cxntests = new Jetpack_Cxn_Tests(); |
||
| 1309 | |||
| 1310 | if ( $cxntests->pass() ) { |
||
| 1311 | $result = array( |
||
| 1312 | 'code' => 'success', |
||
| 1313 | 'message' => __( 'All connection tests passed.', 'jetpack' ), |
||
| 1314 | ); |
||
| 1315 | } else { |
||
| 1316 | $error = $cxntests->output_fails_as_wp_error(); // Using this so the output is similar both ways. |
||
| 1317 | $errors = array(); |
||
| 1318 | |||
| 1319 | // Borrowed from WP_REST_Server::error_to_response(). |
||
| 1320 | foreach ( (array) $error->errors as $code => $messages ) { |
||
| 1321 | foreach ( (array) $messages as $message ) { |
||
| 1322 | $errors[] = array( |
||
| 1323 | 'code' => $code, |
||
| 1324 | 'message' => $message, |
||
| 1325 | 'data' => $error->get_error_data( $code ), |
||
| 1326 | ); |
||
| 1327 | } |
||
| 1328 | } |
||
| 1329 | |||
| 1330 | $result = ( ! empty( $errors ) ) ? $errors[0] : null; |
||
| 1331 | if ( count( $errors ) > 1 ) { |
||
| 1332 | // Remove the primary error. |
||
| 1333 | array_shift( $errors ); |
||
| 1334 | $result['additional_errors'] = $errors; |
||
| 1335 | } |
||
| 1336 | } |
||
| 1337 | |||
| 1338 | $result = wp_json_encode( $result ); |
||
| 1339 | |||
| 1340 | $encrypted = $cxntests->encrypt_string_for_wpcom( $result ); |
||
|
0 ignored issues
–
show
|
|||
| 1341 | |||
| 1342 | if ( ! $encrypted || ! is_array( $encrypted ) ) { |
||
| 1343 | return rest_ensure_response( |
||
| 1344 | array( |
||
| 1345 | 'code' => 'action_required', |
||
| 1346 | 'message' => 'Please request results from the in-plugin debugger', |
||
| 1347 | ) |
||
| 1348 | ); |
||
| 1349 | } |
||
| 1350 | |||
| 1351 | return rest_ensure_response( |
||
| 1352 | array( |
||
| 1353 | 'code' => 'response', |
||
| 1354 | 'debug' => array( |
||
| 1355 | 'data' => $encrypted['data'], |
||
| 1356 | 'key' => $encrypted['key'], |
||
| 1357 | ), |
||
| 1358 | ) |
||
| 1359 | ); |
||
| 1360 | } |
||
| 1361 | |||
| 1362 | public static function rewind_data() { |
||
| 1363 | $site_id = Jetpack_Options::get_option( 'id' ); |
||
| 1364 | |||
| 1365 | if ( ! $site_id ) { |
||
| 1366 | return new WP_Error( 'site_id_missing' ); |
||
| 1367 | } |
||
| 1368 | |||
| 1369 | if ( ! isset( $_GET['_cacheBuster'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
||
| 1370 | $rewind_state = get_transient( 'jetpack_rewind_state' ); |
||
| 1371 | if ( $rewind_state ) { |
||
| 1372 | return $rewind_state; |
||
| 1373 | } |
||
| 1374 | } |
||
| 1375 | |||
| 1376 | $response = Client::wpcom_json_api_request_as_blog( sprintf( '/sites/%d/rewind', $site_id ) .'?force=wpcom', '2', array(), null, 'wpcom' ); |
||
| 1377 | |||
| 1378 | if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { |
||
| 1379 | return new WP_Error( 'rewind_data_fetch_failed' ); |
||
| 1380 | } |
||
| 1381 | |||
| 1382 | $body = wp_remote_retrieve_body( $response ); |
||
| 1383 | $result = json_decode( $body ); |
||
| 1384 | set_transient( 'jetpack_rewind_state', $result, 30 * MINUTE_IN_SECONDS ); |
||
| 1385 | |||
| 1386 | return $result; |
||
| 1387 | } |
||
| 1388 | |||
| 1389 | /** |
||
| 1390 | * Get rewind data |
||
| 1391 | * |
||
| 1392 | * @since 5.7.0 |
||
| 1393 | * |
||
| 1394 | * @return array Array of rewind properties. |
||
| 1395 | */ |
||
| 1396 | public static function get_rewind_data() { |
||
| 1397 | $rewind_data = self::rewind_data(); |
||
| 1398 | |||
| 1399 | if ( ! is_wp_error( $rewind_data ) ) { |
||
| 1400 | return rest_ensure_response( array( |
||
| 1401 | 'code' => 'success', |
||
| 1402 | 'message' => esc_html__( 'Backup & Scan data correctly received.', 'jetpack' ), |
||
| 1403 | 'data' => wp_json_encode( $rewind_data ), |
||
| 1404 | ) |
||
| 1405 | ); |
||
| 1406 | } |
||
| 1407 | |||
| 1408 | View Code Duplication | if ( $rewind_data->get_error_code() === 'rewind_data_fetch_failed' ) { |
|
| 1409 | return new WP_Error( 'rewind_data_fetch_failed', esc_html__( 'Failed fetching rewind data. Try again later.', 'jetpack' ), array( 'status' => 400 ) ); |
||
| 1410 | } |
||
| 1411 | |||
| 1412 | View Code Duplication | if ( $rewind_data->get_error_code() === 'site_id_missing' ) { |
|
| 1413 | return new WP_Error( 'site_id_missing', esc_html__( 'The ID of this site does not exist.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1414 | } |
||
| 1415 | |||
| 1416 | return new WP_Error( |
||
| 1417 | 'error_get_rewind_data', |
||
| 1418 | esc_html__( 'Could not retrieve Backup & Scan data.', 'jetpack' ), |
||
| 1419 | array( 'status' => 500 ) |
||
| 1420 | ); |
||
| 1421 | } |
||
| 1422 | |||
| 1423 | /** |
||
| 1424 | * Gets Scan state data. |
||
| 1425 | * |
||
| 1426 | * @since 8.5.0 |
||
| 1427 | * |
||
| 1428 | * @return array|WP_Error Result from WPCOM API or error. |
||
| 1429 | */ |
||
| 1430 | public static function scan_state() { |
||
| 1431 | |||
| 1432 | if ( ! isset( $_GET['_cacheBuster'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
||
| 1433 | $scan_state = get_transient( 'jetpack_scan_state' ); |
||
| 1434 | if ( ! empty( $scan_state ) ) { |
||
| 1435 | return $scan_state; |
||
| 1436 | } |
||
| 1437 | } |
||
| 1438 | $site_id = Jetpack_Options::get_option( 'id' ); |
||
| 1439 | |||
| 1440 | if ( ! $site_id ) { |
||
| 1441 | return new WP_Error( 'site_id_missing' ); |
||
| 1442 | } |
||
| 1443 | // The default timeout was too short in come cases. |
||
| 1444 | add_filter( 'http_request_timeout', array( __CLASS__, 'increase_timeout_30' ), PHP_INT_MAX - 1 ); |
||
| 1445 | $response = Client::wpcom_json_api_request_as_blog( sprintf( '/sites/%d/scan', $site_id ) . '?force=wpcom', '2', array(), null, 'wpcom' ); |
||
| 1446 | remove_filter( 'http_request_timeout', array( __CLASS__, 'increase_timeout_30' ), PHP_INT_MAX - 1 ); |
||
| 1447 | |||
| 1448 | if ( wp_remote_retrieve_response_code( $response ) !== 200 ) { |
||
| 1449 | return new WP_Error( 'scan_state_fetch_failed' ); |
||
| 1450 | } |
||
| 1451 | |||
| 1452 | $body = wp_remote_retrieve_body( $response ); |
||
| 1453 | $result = json_decode( $body ); |
||
| 1454 | set_transient( 'jetpack_scan_state', $result, 30 * MINUTE_IN_SECONDS ); |
||
| 1455 | |||
| 1456 | return $result; |
||
| 1457 | } |
||
| 1458 | |||
| 1459 | /** |
||
| 1460 | * Increases the request timeout value to 30 seconds. |
||
| 1461 | * |
||
| 1462 | * @return int Always returns 30. |
||
| 1463 | */ |
||
| 1464 | public static function increase_timeout_30() { |
||
| 1465 | return 30; // 30 Seconds |
||
| 1466 | } |
||
| 1467 | |||
| 1468 | /** |
||
| 1469 | * Get Scan state for API. |
||
| 1470 | * |
||
| 1471 | * @since 8.5.0 |
||
| 1472 | * |
||
| 1473 | * @return WP_REST_Response|WP_Error REST response or error state. |
||
| 1474 | */ |
||
| 1475 | public static function get_scan_state() { |
||
| 1476 | $scan_state = self::scan_state(); |
||
| 1477 | |||
| 1478 | if ( ! is_wp_error( $scan_state ) ) { |
||
| 1479 | if ( jetpack_is_atomic_site() && ! empty( $scan_state->threats ) ) { |
||
| 1480 | $scan_state->threats = array(); |
||
| 1481 | } |
||
| 1482 | return rest_ensure_response( |
||
| 1483 | array( |
||
| 1484 | 'code' => 'success', |
||
| 1485 | 'message' => esc_html__( 'Scan state correctly received.', 'jetpack' ), |
||
| 1486 | 'data' => wp_json_encode( $scan_state ), |
||
| 1487 | ) |
||
| 1488 | ); |
||
| 1489 | } |
||
| 1490 | |||
| 1491 | if ( $scan_state->get_error_code() === 'scan_state_fetch_failed' ) { |
||
| 1492 | return new WP_Error( 'scan_state_fetch_failed', esc_html__( 'Failed fetching rewind data. Try again later.', 'jetpack' ), array( 'status' => 400 ) ); |
||
| 1493 | } |
||
| 1494 | |||
| 1495 | View Code Duplication | if ( $scan_state->get_error_code() === 'site_id_missing' ) { |
|
| 1496 | return new WP_Error( 'site_id_missing', esc_html__( 'The ID of this site does not exist.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1497 | } |
||
| 1498 | |||
| 1499 | return new WP_Error( |
||
| 1500 | 'error_get_rewind_data', |
||
| 1501 | esc_html__( 'Could not retrieve Scan state.', 'jetpack' ), |
||
| 1502 | array( 'status' => 500 ) |
||
| 1503 | ); |
||
| 1504 | } |
||
| 1505 | |||
| 1506 | /** |
||
| 1507 | * Disconnects Jetpack from the WordPress.com Servers |
||
| 1508 | * |
||
| 1509 | * @uses Jetpack::disconnect(); |
||
| 1510 | * @since 4.3.0 |
||
| 1511 | * |
||
| 1512 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1513 | * |
||
| 1514 | * @return bool|WP_Error True if Jetpack successfully disconnected. |
||
| 1515 | */ |
||
| 1516 | View Code Duplication | public static function disconnect_site( $request ) { |
|
| 1517 | |||
| 1518 | if ( ! isset( $request['isActive'] ) || $request['isActive'] !== false ) { |
||
| 1519 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1520 | } |
||
| 1521 | |||
| 1522 | if ( Jetpack::is_active() ) { |
||
| 1523 | Jetpack::disconnect(); |
||
| 1524 | return rest_ensure_response( array( 'code' => 'success' ) ); |
||
| 1525 | } |
||
| 1526 | |||
| 1527 | return new WP_Error( 'disconnect_failed', esc_html__( 'Was not able to disconnect the site. Please try again.', 'jetpack' ), array( 'status' => 400 ) ); |
||
| 1528 | } |
||
| 1529 | |||
| 1530 | /** |
||
| 1531 | * Registers the Jetpack site |
||
| 1532 | * |
||
| 1533 | * @uses Jetpack::try_registration(); |
||
| 1534 | * @since 7.7.0 |
||
| 1535 | * |
||
| 1536 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1537 | * |
||
| 1538 | * @return bool|WP_Error True if Jetpack successfully registered |
||
| 1539 | */ |
||
| 1540 | public static function register_site( $request ) { |
||
| 1541 | if ( ! wp_verify_nonce( $request->get_param( 'registration_nonce' ), 'jetpack-registration-nonce' ) ) { |
||
| 1542 | return new WP_Error( 'invalid_nonce', __( 'Unable to verify your request.', 'jetpack' ), array( 'status' => 403 ) ); |
||
| 1543 | } |
||
| 1544 | |||
| 1545 | $response = Jetpack::try_registration(); |
||
| 1546 | |||
| 1547 | if ( is_wp_error( $response ) ) { |
||
| 1548 | return $response; |
||
| 1549 | } |
||
| 1550 | |||
| 1551 | return rest_ensure_response( |
||
| 1552 | array( |
||
| 1553 | 'authorizeUrl' => Jetpack::build_authorize_url( false, true ) |
||
| 1554 | ) ); |
||
| 1555 | } |
||
| 1556 | |||
| 1557 | /** |
||
| 1558 | * Gets a new connect raw URL with fresh nonce. |
||
| 1559 | * |
||
| 1560 | * @uses Jetpack::disconnect(); |
||
| 1561 | * @since 4.3.0 |
||
| 1562 | * |
||
| 1563 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1564 | * |
||
| 1565 | * @return string|WP_Error A raw URL if the connection URL could be built; error message otherwise. |
||
| 1566 | */ |
||
| 1567 | public static function build_connect_url( $request = array() ) { |
||
| 1568 | $from = isset( $request['from'] ) ? $request['from'] : false; |
||
| 1569 | $redirect = isset( $request['redirect'] ) ? $request['redirect'] : false; |
||
| 1570 | |||
| 1571 | $url = Jetpack::init()->build_connect_url( true, $redirect, $from ); |
||
| 1572 | if ( $url ) { |
||
| 1573 | return rest_ensure_response( $url ); |
||
| 1574 | } |
||
| 1575 | |||
| 1576 | return new WP_Error( 'build_connect_url_failed', esc_html__( 'Unable to build the connect URL. Please reload the page and try again.', 'jetpack' ), array( 'status' => 400 ) ); |
||
| 1577 | } |
||
| 1578 | |||
| 1579 | /** |
||
| 1580 | * Get miscellaneous user data related to the connection. Similar data available in old "My Jetpack". |
||
| 1581 | * Information about the master/primary user. |
||
| 1582 | * Information about the current user. |
||
| 1583 | * |
||
| 1584 | * @since 4.3.0 |
||
| 1585 | * |
||
| 1586 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1587 | * |
||
| 1588 | * @return object |
||
| 1589 | */ |
||
| 1590 | public static function get_user_connection_data() { |
||
| 1591 | require_once( JETPACK__PLUGIN_DIR . '_inc/lib/admin-pages/class.jetpack-react-page.php' ); |
||
| 1592 | |||
| 1593 | $response = array( |
||
| 1594 | // 'othersLinked' => Jetpack::get_other_linked_admins(), |
||
| 1595 | 'currentUser' => jetpack_current_user_data(), |
||
| 1596 | 'connectionOwner' => ( new Connection_Manager() )->get_connection_owner()->data->display_name, |
||
| 1597 | ); |
||
| 1598 | return rest_ensure_response( $response ); |
||
| 1599 | } |
||
| 1600 | |||
| 1601 | /** |
||
| 1602 | * Change the master user. |
||
| 1603 | * |
||
| 1604 | * @since 6.2.0 |
||
| 1605 | * |
||
| 1606 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1607 | * |
||
| 1608 | * @return bool|WP_Error True if owner successfully changed. |
||
| 1609 | */ |
||
| 1610 | public static function set_connection_owner( $request ) { |
||
| 1611 | if ( ! isset( $request['owner'] ) ) { |
||
| 1612 | return new WP_Error( |
||
| 1613 | 'invalid_param', |
||
| 1614 | esc_html__( 'Invalid Parameter', 'jetpack' ), |
||
| 1615 | array( 'status' => 400 ) |
||
| 1616 | ); |
||
| 1617 | } |
||
| 1618 | |||
| 1619 | $new_owner_id = $request['owner']; |
||
| 1620 | if ( ! user_can( $new_owner_id, 'administrator' ) ) { |
||
| 1621 | return new WP_Error( |
||
| 1622 | 'new_owner_not_admin', |
||
| 1623 | esc_html__( 'New owner is not admin', 'jetpack' ), |
||
| 1624 | array( 'status' => 400 ) |
||
| 1625 | ); |
||
| 1626 | } |
||
| 1627 | |||
| 1628 | if ( $new_owner_id === get_current_user_id() ) { |
||
| 1629 | return new WP_Error( |
||
| 1630 | 'new_owner_is_current_user', |
||
| 1631 | esc_html__( 'New owner is same as current user', 'jetpack' ), |
||
| 1632 | array( 'status' => 400 ) |
||
| 1633 | ); |
||
| 1634 | } |
||
| 1635 | |||
| 1636 | if ( ! Jetpack::is_user_connected( $new_owner_id ) ) { |
||
| 1637 | return new WP_Error( |
||
| 1638 | 'new_owner_not_connected', |
||
| 1639 | esc_html__( 'New owner is not connected', 'jetpack' ), |
||
| 1640 | array( 'status' => 400 ) |
||
| 1641 | ); |
||
| 1642 | } |
||
| 1643 | |||
| 1644 | // Update the master user in Jetpack |
||
| 1645 | $updated = Jetpack_Options::update_option( 'master_user', $new_owner_id ); |
||
| 1646 | |||
| 1647 | // Notify WPCOM about the master user change |
||
| 1648 | $xml = new Jetpack_IXR_Client( array( |
||
| 1649 | 'user_id' => get_current_user_id(), |
||
| 1650 | ) ); |
||
| 1651 | $xml->query( 'jetpack.switchBlogOwner', array( |
||
| 1652 | 'new_blog_owner' => $new_owner_id, |
||
| 1653 | ) ); |
||
| 1654 | |||
| 1655 | if ( $updated && ! $xml->isError() ) { |
||
| 1656 | |||
| 1657 | // Track it |
||
| 1658 | if ( class_exists( 'Automattic\Jetpack\Tracking' ) ) { |
||
| 1659 | $tracking = new Tracking(); |
||
| 1660 | $tracking->record_user_event( 'set_connection_owner_success' ); |
||
| 1661 | } |
||
| 1662 | |||
| 1663 | return rest_ensure_response( |
||
| 1664 | array( |
||
| 1665 | 'code' => 'success', |
||
| 1666 | ) |
||
| 1667 | ); |
||
| 1668 | } |
||
| 1669 | return new WP_Error( |
||
| 1670 | 'error_setting_new_owner', |
||
| 1671 | esc_html__( 'Could not confirm new owner.', 'jetpack' ), |
||
| 1672 | array( 'status' => 500 ) |
||
| 1673 | ); |
||
| 1674 | } |
||
| 1675 | |||
| 1676 | /** |
||
| 1677 | * Unlinks current user from the WordPress.com Servers. |
||
| 1678 | * |
||
| 1679 | * @since 4.3.0 |
||
| 1680 | * @uses Automattic\Jetpack\Connection\Manager::disconnect_user |
||
| 1681 | * |
||
| 1682 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1683 | * |
||
| 1684 | * @return bool|WP_Error True if user successfully unlinked. |
||
| 1685 | */ |
||
| 1686 | View Code Duplication | public static function unlink_user( $request ) { |
|
| 1687 | |||
| 1688 | if ( ! isset( $request['linked'] ) || $request['linked'] !== false ) { |
||
| 1689 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1690 | } |
||
| 1691 | |||
| 1692 | if ( Connection_Manager::disconnect_user() ) { |
||
| 1693 | return rest_ensure_response( |
||
| 1694 | array( |
||
| 1695 | 'code' => 'success' |
||
| 1696 | ) |
||
| 1697 | ); |
||
| 1698 | } |
||
| 1699 | |||
| 1700 | return new WP_Error( 'unlink_user_failed', esc_html__( 'Was not able to unlink the user. Please try again.', 'jetpack' ), array( 'status' => 400 ) ); |
||
| 1701 | } |
||
| 1702 | |||
| 1703 | /** |
||
| 1704 | * Gets current user's tracking settings. |
||
| 1705 | * |
||
| 1706 | * @since 6.0.0 |
||
| 1707 | * |
||
| 1708 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1709 | * |
||
| 1710 | * @return WP_REST_Response|WP_Error Response, else error. |
||
| 1711 | */ |
||
| 1712 | View Code Duplication | public static function get_user_tracking_settings( $request ) { |
|
| 1713 | if ( ! Jetpack::is_user_connected() ) { |
||
| 1714 | $response = array( |
||
| 1715 | 'tracks_opt_out' => true, // Default to opt-out if not connected to wp.com. |
||
| 1716 | ); |
||
| 1717 | } else { |
||
| 1718 | $response = Client::wpcom_json_api_request_as_user( |
||
| 1719 | '/jetpack-user-tracking', |
||
| 1720 | 'v2', |
||
| 1721 | array( |
||
| 1722 | 'method' => 'GET', |
||
| 1723 | 'headers' => array( |
||
| 1724 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 1725 | ), |
||
| 1726 | ) |
||
| 1727 | ); |
||
| 1728 | if ( ! is_wp_error( $response ) ) { |
||
| 1729 | $response = json_decode( wp_remote_retrieve_body( $response ), true ); |
||
| 1730 | } |
||
| 1731 | } |
||
| 1732 | |||
| 1733 | return rest_ensure_response( $response ); |
||
| 1734 | } |
||
| 1735 | |||
| 1736 | /** |
||
| 1737 | * Updates current user's tracking settings. |
||
| 1738 | * |
||
| 1739 | * @since 6.0.0 |
||
| 1740 | * |
||
| 1741 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 1742 | * |
||
| 1743 | * @return WP_REST_Response|WP_Error Response, else error. |
||
| 1744 | */ |
||
| 1745 | View Code Duplication | public static function update_user_tracking_settings( $request ) { |
|
| 1746 | if ( ! Jetpack::is_user_connected() ) { |
||
| 1747 | $response = array( |
||
| 1748 | 'tracks_opt_out' => true, // Default to opt-out if not connected to wp.com. |
||
| 1749 | ); |
||
| 1750 | } else { |
||
| 1751 | $response = Client::wpcom_json_api_request_as_user( |
||
| 1752 | '/jetpack-user-tracking', |
||
| 1753 | 'v2', |
||
| 1754 | array( |
||
| 1755 | 'method' => 'PUT', |
||
| 1756 | 'headers' => array( |
||
| 1757 | 'Content-Type' => 'application/json', |
||
| 1758 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 1759 | ), |
||
| 1760 | ), |
||
| 1761 | wp_json_encode( $request->get_params() ) |
||
|
0 ignored issues
–
show
|
|||
| 1762 | ); |
||
| 1763 | if ( ! is_wp_error( $response ) ) { |
||
| 1764 | $response = json_decode( wp_remote_retrieve_body( $response ), true ); |
||
| 1765 | } |
||
| 1766 | } |
||
| 1767 | |||
| 1768 | return rest_ensure_response( $response ); |
||
| 1769 | } |
||
| 1770 | |||
| 1771 | /** |
||
| 1772 | * Fetch site data from .com including the site's current plan and the site's products. |
||
| 1773 | * |
||
| 1774 | * @since 5.5.0 |
||
| 1775 | * |
||
| 1776 | * @return stdClass|WP_Error |
||
| 1777 | */ |
||
| 1778 | public static function site_data() { |
||
| 1779 | $site_id = Jetpack_Options::get_option( 'id' ); |
||
| 1780 | |||
| 1781 | if ( ! $site_id ) { |
||
| 1782 | return new WP_Error( 'site_id_missing', '', array( 'api_error_code' => __( 'site_id_missing', 'jetpack' ) ) ); |
||
| 1783 | } |
||
| 1784 | |||
| 1785 | $args = array( 'headers' => array() ); |
||
| 1786 | |||
| 1787 | // Allow use a store sandbox. Internal ref: PCYsg-IA-p2. |
||
| 1788 | if ( isset( $_COOKIE ) && isset( $_COOKIE['store_sandbox'] ) ) { |
||
| 1789 | $secret = $_COOKIE['store_sandbox']; |
||
| 1790 | $args['headers']['Cookie'] = "store_sandbox=$secret;"; |
||
| 1791 | } |
||
| 1792 | |||
| 1793 | $response = Client::wpcom_json_api_request_as_blog( sprintf( '/sites/%d', $site_id ) .'?force=wpcom', '1.1', $args ); |
||
| 1794 | $body = wp_remote_retrieve_body( $response ); |
||
| 1795 | $data = $body ? json_decode( $body ) : null; |
||
| 1796 | |||
| 1797 | if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { |
||
| 1798 | $error_info = array( |
||
| 1799 | 'api_error_code' => null, |
||
| 1800 | 'api_http_code' => wp_remote_retrieve_response_code( $response ), |
||
| 1801 | ); |
||
| 1802 | |||
| 1803 | if ( is_wp_error( $response ) ) { |
||
| 1804 | $error_info['api_error_code'] = $response->get_error_code() ? wp_strip_all_tags( $response->get_error_code() ) : null; |
||
| 1805 | } elseif ( $data && ! empty( $data->error ) ) { |
||
| 1806 | $error_info['api_error_code'] = $data->error; |
||
| 1807 | } |
||
| 1808 | |||
| 1809 | return new WP_Error( 'site_data_fetch_failed', '', $error_info ); |
||
| 1810 | } |
||
| 1811 | |||
| 1812 | Jetpack_Plan::update_from_sites_response( $response ); |
||
| 1813 | |||
| 1814 | return $data; |
||
| 1815 | } |
||
| 1816 | /** |
||
| 1817 | * Get site data, including for example, the site's current plan. |
||
| 1818 | * |
||
| 1819 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response |
||
| 1820 | * @since 4.3.0 |
||
| 1821 | */ |
||
| 1822 | public static function get_site_data() { |
||
| 1823 | $site_data = self::site_data(); |
||
| 1824 | |||
| 1825 | if ( ! is_wp_error( $site_data ) ) { |
||
| 1826 | /** |
||
| 1827 | * Fires when the site data was successfully returned from the /sites/%d wpcom endpoint. |
||
| 1828 | * |
||
| 1829 | * @since 8.7.0 |
||
| 1830 | */ |
||
| 1831 | do_action( 'jetpack_get_site_data_success' ); |
||
| 1832 | return rest_ensure_response( array( |
||
| 1833 | 'code' => 'success', |
||
| 1834 | 'message' => esc_html__( 'Site data correctly received.', 'jetpack' ), |
||
| 1835 | 'data' => json_encode( $site_data ), |
||
| 1836 | ) |
||
| 1837 | ); |
||
| 1838 | } |
||
| 1839 | |||
| 1840 | $error_data = $site_data->get_error_data(); |
||
| 1841 | |||
| 1842 | if ( empty( $error_data['api_error_code'] ) ) { |
||
| 1843 | $error_message = esc_html__( 'Failed fetching site data from WordPress.com. If the problem persists, try reconnecting Jetpack.', 'jetpack' ); |
||
| 1844 | } else { |
||
| 1845 | /* translators: %s is an error code (e.g. `token_mismatch`) */ |
||
| 1846 | $error_message = sprintf( esc_html__( 'Failed fetching site data from WordPress.com (%s). If the problem persists, try reconnecting Jetpack.', 'jetpack' ), $error_data['api_error_code'] ); |
||
| 1847 | } |
||
| 1848 | |||
| 1849 | return new WP_Error( |
||
| 1850 | $site_data->get_error_code(), |
||
| 1851 | $error_message, |
||
| 1852 | array( |
||
| 1853 | 'status' => 400, |
||
| 1854 | 'api_error_code' => empty( $error_data['api_error_code'] ) ? null : $error_data['api_error_code'], |
||
| 1855 | 'api_http_code' => empty( $error_data['api_http_code'] ) ? null : $error_data['api_http_code'], |
||
| 1856 | ) |
||
| 1857 | ); |
||
| 1858 | } |
||
| 1859 | |||
| 1860 | /** |
||
| 1861 | * Fetch AL data for this site and return it. |
||
| 1862 | * |
||
| 1863 | * @since 7.4 |
||
| 1864 | * |
||
| 1865 | * @return array|WP_Error |
||
| 1866 | */ |
||
| 1867 | public static function get_site_activity() { |
||
| 1868 | $site_id = Jetpack_Options::get_option( 'id' ); |
||
| 1869 | |||
| 1870 | if ( ! $site_id ) { |
||
| 1871 | return new WP_Error( |
||
| 1872 | 'site_id_missing', |
||
| 1873 | esc_html__( 'Site ID is missing.', 'jetpack' ), |
||
| 1874 | array( 'status' => 400 ) |
||
| 1875 | ); |
||
| 1876 | } |
||
| 1877 | |||
| 1878 | $response = Client::wpcom_json_api_request_as_user( "/sites/$site_id/activity", '2', array( |
||
| 1879 | 'method' => 'GET', |
||
| 1880 | 'headers' => array( |
||
| 1881 | 'X-Forwarded-For' => Jetpack::current_user_ip( true ), |
||
| 1882 | ), |
||
| 1883 | ), null, 'wpcom' ); |
||
| 1884 | $response_code = wp_remote_retrieve_response_code( $response ); |
||
| 1885 | |||
| 1886 | View Code Duplication | if ( 200 !== $response_code ) { |
|
| 1887 | return new WP_Error( |
||
| 1888 | 'activity_fetch_failed', |
||
| 1889 | esc_html__( 'Could not retrieve site activity.', 'jetpack' ), |
||
| 1890 | array( 'status' => $response_code ) |
||
| 1891 | ); |
||
| 1892 | } |
||
| 1893 | |||
| 1894 | $data = json_decode( wp_remote_retrieve_body( $response ) ); |
||
| 1895 | |||
| 1896 | if ( ! isset( $data->current->orderedItems ) ) { |
||
| 1897 | return new WP_Error( |
||
| 1898 | 'activity_not_found', |
||
| 1899 | esc_html__( 'No activity found', 'jetpack' ), |
||
| 1900 | array( 'status' => 204 ) // no content |
||
| 1901 | ); |
||
| 1902 | } |
||
| 1903 | |||
| 1904 | return rest_ensure_response( array( |
||
| 1905 | 'code' => 'success', |
||
| 1906 | 'data' => $data->current->orderedItems, |
||
| 1907 | ) |
||
| 1908 | ); |
||
| 1909 | } |
||
| 1910 | |||
| 1911 | /** |
||
| 1912 | * Handles identity crisis mitigation, confirming safe mode for this site. |
||
| 1913 | * |
||
| 1914 | * @since 4.4.0 |
||
| 1915 | * |
||
| 1916 | * @return bool | WP_Error True if option is properly set. |
||
| 1917 | */ |
||
| 1918 | public static function confirm_safe_mode() { |
||
| 1919 | $updated = Jetpack_Options::update_option( 'safe_mode_confirmed', true ); |
||
| 1920 | if ( $updated ) { |
||
| 1921 | return rest_ensure_response( |
||
| 1922 | array( |
||
| 1923 | 'code' => 'success' |
||
| 1924 | ) |
||
| 1925 | ); |
||
| 1926 | } |
||
| 1927 | return new WP_Error( |
||
| 1928 | 'error_setting_jetpack_safe_mode', |
||
| 1929 | esc_html__( 'Could not confirm safe mode.', 'jetpack' ), |
||
| 1930 | array( 'status' => 500 ) |
||
| 1931 | ); |
||
| 1932 | } |
||
| 1933 | |||
| 1934 | /** |
||
| 1935 | * Handles identity crisis mitigation, migrating stats and subscribers from old url to this, new url. |
||
| 1936 | * |
||
| 1937 | * @since 4.4.0 |
||
| 1938 | * |
||
| 1939 | * @return bool | WP_Error True if option is properly set. |
||
| 1940 | */ |
||
| 1941 | public static function migrate_stats_and_subscribers() { |
||
| 1942 | if ( Jetpack_Options::get_option( 'sync_error_idc' ) && ! Jetpack_Options::delete_option( 'sync_error_idc' ) ) { |
||
| 1943 | return new WP_Error( |
||
| 1944 | 'error_deleting_sync_error_idc', |
||
| 1945 | esc_html__( 'Could not delete sync error option.', 'jetpack' ), |
||
| 1946 | array( 'status' => 500 ) |
||
| 1947 | ); |
||
| 1948 | } |
||
| 1949 | |||
| 1950 | if ( Jetpack_Options::get_option( 'migrate_for_idc' ) || Jetpack_Options::update_option( 'migrate_for_idc', true ) ) { |
||
| 1951 | return rest_ensure_response( |
||
| 1952 | array( |
||
| 1953 | 'code' => 'success' |
||
| 1954 | ) |
||
| 1955 | ); |
||
| 1956 | } |
||
| 1957 | return new WP_Error( |
||
| 1958 | 'error_setting_jetpack_migrate', |
||
| 1959 | esc_html__( 'Could not confirm migration.', 'jetpack' ), |
||
| 1960 | array( 'status' => 500 ) |
||
| 1961 | ); |
||
| 1962 | } |
||
| 1963 | |||
| 1964 | /** |
||
| 1965 | * This IDC resolution will disconnect the site and re-connect to a completely new |
||
| 1966 | * and separate shadow site than the original. |
||
| 1967 | * |
||
| 1968 | * It will first will disconnect the site without phoning home as to not disturb the production site. |
||
| 1969 | * It then builds a fresh connection URL and sends it back along with the response. |
||
| 1970 | * |
||
| 1971 | * @since 4.4.0 |
||
| 1972 | * @return bool|WP_Error |
||
| 1973 | */ |
||
| 1974 | public static function start_fresh_connection() { |
||
| 1975 | // First clear the options / disconnect. |
||
| 1976 | Jetpack::disconnect(); |
||
| 1977 | return self::build_connect_url(); |
||
| 1978 | } |
||
| 1979 | |||
| 1980 | /** |
||
| 1981 | * Reset Jetpack options |
||
| 1982 | * |
||
| 1983 | * @since 4.3.0 |
||
| 1984 | * |
||
| 1985 | * @param WP_REST_Request $request { |
||
| 1986 | * Array of parameters received by request. |
||
| 1987 | * |
||
| 1988 | * @type string $options Available options to reset are options|modules |
||
| 1989 | * } |
||
| 1990 | * |
||
| 1991 | * @return bool|WP_Error True if options were reset. Otherwise, a WP_Error instance with the corresponding error. |
||
| 1992 | */ |
||
| 1993 | public static function reset_jetpack_options( $request ) { |
||
| 1994 | |||
| 1995 | if ( ! isset( $request['reset'] ) || $request['reset'] !== true ) { |
||
| 1996 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 1997 | } |
||
| 1998 | |||
| 1999 | if ( isset( $request['options'] ) ) { |
||
| 2000 | $data = $request['options']; |
||
| 2001 | |||
| 2002 | switch( $data ) { |
||
| 2003 | case ( 'options' ) : |
||
| 2004 | $options_to_reset = Jetpack::get_jetpack_options_for_reset(); |
||
| 2005 | |||
| 2006 | // Reset the Jetpack options |
||
| 2007 | foreach ( $options_to_reset['jp_options'] as $option_to_reset ) { |
||
| 2008 | Jetpack_Options::delete_option( $option_to_reset ); |
||
| 2009 | } |
||
| 2010 | |||
| 2011 | foreach ( $options_to_reset['wp_options'] as $option_to_reset ) { |
||
| 2012 | delete_option( $option_to_reset ); |
||
| 2013 | } |
||
| 2014 | |||
| 2015 | // Reset to default modules |
||
| 2016 | $default_modules = Jetpack::get_default_modules(); |
||
| 2017 | Jetpack::update_active_modules( $default_modules ); |
||
| 2018 | |||
| 2019 | return rest_ensure_response( array( |
||
| 2020 | 'code' => 'success', |
||
| 2021 | 'message' => esc_html__( 'Jetpack options reset.', 'jetpack' ), |
||
| 2022 | ) ); |
||
| 2023 | break; |
||
| 2024 | |||
| 2025 | case 'modules': |
||
| 2026 | $default_modules = Jetpack::get_default_modules(); |
||
| 2027 | Jetpack::update_active_modules( $default_modules ); |
||
| 2028 | return rest_ensure_response( array( |
||
| 2029 | 'code' => 'success', |
||
| 2030 | 'message' => esc_html__( 'Modules reset to default.', 'jetpack' ), |
||
| 2031 | ) ); |
||
| 2032 | break; |
||
| 2033 | |||
| 2034 | default: |
||
| 2035 | return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 2036 | } |
||
| 2037 | } |
||
| 2038 | |||
| 2039 | return new WP_Error( 'required_param', esc_html__( 'Missing parameter "type".', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 2040 | } |
||
| 2041 | |||
| 2042 | /** |
||
| 2043 | * Get the query parameters to update module options or general settings. |
||
| 2044 | * |
||
| 2045 | * @since 4.3.0 |
||
| 2046 | * @since 4.4.0 Accepts a $selector parameter. |
||
| 2047 | * |
||
| 2048 | * @param string $selector Selects a set of options to update, Can be empty, a module slug or 'any'. |
||
| 2049 | * |
||
| 2050 | * @return array |
||
| 2051 | */ |
||
| 2052 | public static function get_updateable_parameters( $selector = '' ) { |
||
| 2053 | $parameters = array( |
||
| 2054 | 'context' => array( |
||
| 2055 | 'default' => 'edit', |
||
| 2056 | ), |
||
| 2057 | ); |
||
| 2058 | |||
| 2059 | return array_merge( $parameters, self::get_updateable_data_list( $selector ) ); |
||
| 2060 | } |
||
| 2061 | |||
| 2062 | /** |
||
| 2063 | * Returns a list of module options or general settings that can be updated. |
||
| 2064 | * |
||
| 2065 | * @since 4.3.0 |
||
| 2066 | * @since 4.4.0 Accepts 'any' as a parameter which will make it return the entire list. |
||
| 2067 | * |
||
| 2068 | * @param string|array $selector Module slug, 'any', or an array of parameters. |
||
| 2069 | * If empty, it's assumed we're updating a module and we'll try to get its slug. |
||
| 2070 | * If 'any' the full list is returned. |
||
| 2071 | * If it's an array of parameters, includes the elements by matching keys. |
||
| 2072 | * |
||
| 2073 | * @return array |
||
| 2074 | */ |
||
| 2075 | public static function get_updateable_data_list( $selector = '' ) { |
||
| 2076 | |||
| 2077 | $options = array( |
||
| 2078 | |||
| 2079 | // Carousel |
||
| 2080 | 'carousel_background_color' => array( |
||
| 2081 | 'description' => esc_html__( 'Color scheme.', 'jetpack' ), |
||
| 2082 | 'type' => 'string', |
||
| 2083 | 'default' => 'black', |
||
| 2084 | 'enum' => array( |
||
| 2085 | 'black', |
||
| 2086 | 'white', |
||
| 2087 | ), |
||
| 2088 | 'enum_labels' => array( |
||
| 2089 | 'black' => esc_html__( 'Black', 'jetpack' ), |
||
| 2090 | 'white' => esc_html__( 'White', 'jetpack' ), |
||
| 2091 | ), |
||
| 2092 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2093 | 'jp_group' => 'carousel', |
||
| 2094 | ), |
||
| 2095 | 'carousel_display_exif' => array( |
||
| 2096 | 'description' => wp_kses( sprintf( __( 'Show photo metadata (<a href="https://en.wikipedia.org/wiki/Exchangeable_image_file_format" target="_blank">Exif</a>) in carousel, when available.', 'jetpack' ) ), array( 'a' => array( 'href' => true, 'target' => true ) ) ), |
||
| 2097 | 'type' => 'boolean', |
||
| 2098 | 'default' => 0, |
||
| 2099 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2100 | 'jp_group' => 'carousel', |
||
| 2101 | ), |
||
| 2102 | 'carousel_display_comments' => array( |
||
| 2103 | 'description' => esc_html__( 'Show comments area in carousel', 'jetpack' ), |
||
| 2104 | 'type' => 'boolean', |
||
| 2105 | 'default' => 1, |
||
| 2106 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2107 | 'jp_group' => 'carousel', |
||
| 2108 | ), |
||
| 2109 | |||
| 2110 | // Comments |
||
| 2111 | 'highlander_comment_form_prompt' => array( |
||
| 2112 | 'description' => esc_html__( 'Greeting Text', 'jetpack' ), |
||
| 2113 | 'type' => 'string', |
||
| 2114 | 'default' => esc_html__( 'Leave a Reply', 'jetpack' ), |
||
| 2115 | 'sanitize_callback' => 'sanitize_text_field', |
||
| 2116 | 'jp_group' => 'comments', |
||
| 2117 | ), |
||
| 2118 | 'jetpack_comment_form_color_scheme' => array( |
||
| 2119 | 'description' => esc_html__( "Color scheme", 'jetpack' ), |
||
| 2120 | 'type' => 'string', |
||
| 2121 | 'default' => 'light', |
||
| 2122 | 'enum' => array( |
||
| 2123 | 'light', |
||
| 2124 | 'dark', |
||
| 2125 | 'transparent', |
||
| 2126 | ), |
||
| 2127 | 'enum_labels' => array( |
||
| 2128 | 'light' => esc_html__( 'Light', 'jetpack' ), |
||
| 2129 | 'dark' => esc_html__( 'Dark', 'jetpack' ), |
||
| 2130 | 'transparent' => esc_html__( 'Transparent', 'jetpack' ), |
||
| 2131 | ), |
||
| 2132 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2133 | 'jp_group' => 'comments', |
||
| 2134 | ), |
||
| 2135 | |||
| 2136 | // Custom Content Types |
||
| 2137 | 'jetpack_portfolio' => array( |
||
| 2138 | 'description' => esc_html__( 'Enable or disable Jetpack portfolio post type.', 'jetpack' ), |
||
| 2139 | 'type' => 'boolean', |
||
| 2140 | 'default' => 0, |
||
| 2141 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2142 | 'jp_group' => 'custom-content-types', |
||
| 2143 | ), |
||
| 2144 | 'jetpack_portfolio_posts_per_page' => array( |
||
| 2145 | 'description' => esc_html__( 'Number of entries to show at most in Portfolio pages.', 'jetpack' ), |
||
| 2146 | 'type' => 'integer', |
||
| 2147 | 'default' => 10, |
||
| 2148 | 'validate_callback' => __CLASS__ . '::validate_posint', |
||
| 2149 | 'jp_group' => 'custom-content-types', |
||
| 2150 | ), |
||
| 2151 | 'jetpack_testimonial' => array( |
||
| 2152 | 'description' => esc_html__( 'Enable or disable Jetpack testimonial post type.', 'jetpack' ), |
||
| 2153 | 'type' => 'boolean', |
||
| 2154 | 'default' => 0, |
||
| 2155 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2156 | 'jp_group' => 'custom-content-types', |
||
| 2157 | ), |
||
| 2158 | 'jetpack_testimonial_posts_per_page' => array( |
||
| 2159 | 'description' => esc_html__( 'Number of entries to show at most in Testimonial pages.', 'jetpack' ), |
||
| 2160 | 'type' => 'integer', |
||
| 2161 | 'default' => 10, |
||
| 2162 | 'validate_callback' => __CLASS__ . '::validate_posint', |
||
| 2163 | 'jp_group' => 'custom-content-types', |
||
| 2164 | ), |
||
| 2165 | |||
| 2166 | // Galleries |
||
| 2167 | 'tiled_galleries' => array( |
||
| 2168 | 'description' => esc_html__( 'Display all your gallery pictures in a cool mosaic.', 'jetpack' ), |
||
| 2169 | 'type' => 'boolean', |
||
| 2170 | 'default' => 0, |
||
| 2171 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2172 | 'jp_group' => 'tiled-gallery', |
||
| 2173 | ), |
||
| 2174 | |||
| 2175 | 'gravatar_disable_hovercards' => array( |
||
| 2176 | 'description' => esc_html__( "View people's profiles when you mouse over their Gravatars", 'jetpack' ), |
||
| 2177 | 'type' => 'string', |
||
| 2178 | 'default' => 'enabled', |
||
| 2179 | // Not visible. This is used as the checkbox value. |
||
| 2180 | 'enum' => array( |
||
| 2181 | 'enabled', |
||
| 2182 | 'disabled', |
||
| 2183 | ), |
||
| 2184 | 'enum_labels' => array( |
||
| 2185 | 'enabled' => esc_html__( 'Enabled', 'jetpack' ), |
||
| 2186 | 'disabled' => esc_html__( 'Disabled', 'jetpack' ), |
||
| 2187 | ), |
||
| 2188 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2189 | 'jp_group' => 'gravatar-hovercards', |
||
| 2190 | ), |
||
| 2191 | |||
| 2192 | // Infinite Scroll |
||
| 2193 | 'infinite_scroll' => array( |
||
| 2194 | 'description' => esc_html__( 'To infinity and beyond', 'jetpack' ), |
||
| 2195 | 'type' => 'boolean', |
||
| 2196 | 'default' => 1, |
||
| 2197 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2198 | 'jp_group' => 'infinite-scroll', |
||
| 2199 | ), |
||
| 2200 | 'infinite_scroll_google_analytics' => array( |
||
| 2201 | 'description' => esc_html__( 'Use Google Analytics with Infinite Scroll', 'jetpack' ), |
||
| 2202 | 'type' => 'boolean', |
||
| 2203 | 'default' => 0, |
||
| 2204 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2205 | 'jp_group' => 'infinite-scroll', |
||
| 2206 | ), |
||
| 2207 | |||
| 2208 | // Likes |
||
| 2209 | 'wpl_default' => array( |
||
| 2210 | 'description' => esc_html__( 'WordPress.com Likes are', 'jetpack' ), |
||
| 2211 | 'type' => 'string', |
||
| 2212 | 'default' => 'on', |
||
| 2213 | 'enum' => array( |
||
| 2214 | 'on', |
||
| 2215 | 'off', |
||
| 2216 | ), |
||
| 2217 | 'enum_labels' => array( |
||
| 2218 | 'on' => esc_html__( 'On for all posts', 'jetpack' ), |
||
| 2219 | 'off' => esc_html__( 'Turned on per post', 'jetpack' ), |
||
| 2220 | ), |
||
| 2221 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2222 | 'jp_group' => 'likes', |
||
| 2223 | ), |
||
| 2224 | 'social_notifications_like' => array( |
||
| 2225 | 'description' => esc_html__( 'Send email notification when someone likes a post', 'jetpack' ), |
||
| 2226 | 'type' => 'boolean', |
||
| 2227 | 'default' => 1, |
||
| 2228 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2229 | 'jp_group' => 'likes', |
||
| 2230 | ), |
||
| 2231 | |||
| 2232 | // Markdown |
||
| 2233 | 'wpcom_publish_comments_with_markdown' => array( |
||
| 2234 | 'description' => esc_html__( 'Use Markdown for comments.', 'jetpack' ), |
||
| 2235 | 'type' => 'boolean', |
||
| 2236 | 'default' => 0, |
||
| 2237 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2238 | 'jp_group' => 'markdown', |
||
| 2239 | ), |
||
| 2240 | 'wpcom_publish_posts_with_markdown' => array( |
||
| 2241 | 'description' => esc_html__( 'Use Markdown for posts.', 'jetpack' ), |
||
| 2242 | 'type' => 'boolean', |
||
| 2243 | 'default' => 0, |
||
| 2244 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2245 | 'jp_group' => 'markdown', |
||
| 2246 | ), |
||
| 2247 | |||
| 2248 | // Monitor |
||
| 2249 | 'monitor_receive_notifications' => array( |
||
| 2250 | 'description' => esc_html__( 'Receive Monitor Email Notifications.', 'jetpack' ), |
||
| 2251 | 'type' => 'boolean', |
||
| 2252 | 'default' => 0, |
||
| 2253 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2254 | 'jp_group' => 'monitor', |
||
| 2255 | ), |
||
| 2256 | |||
| 2257 | // Post by Email |
||
| 2258 | 'post_by_email_address' => array( |
||
| 2259 | 'description' => esc_html__( 'Email Address', 'jetpack' ), |
||
| 2260 | 'type' => 'string', |
||
| 2261 | 'default' => 'noop', |
||
| 2262 | 'enum' => array( |
||
| 2263 | 'noop', |
||
| 2264 | 'create', |
||
| 2265 | 'regenerate', |
||
| 2266 | 'delete', |
||
| 2267 | ), |
||
| 2268 | 'enum_labels' => array( |
||
| 2269 | 'noop' => '', |
||
| 2270 | 'create' => esc_html__( 'Create Post by Email address', 'jetpack' ), |
||
| 2271 | 'regenerate' => esc_html__( 'Regenerate Post by Email address', 'jetpack' ), |
||
| 2272 | 'delete' => esc_html__( 'Delete Post by Email address', 'jetpack' ), |
||
| 2273 | ), |
||
| 2274 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2275 | 'jp_group' => 'post-by-email', |
||
| 2276 | ), |
||
| 2277 | |||
| 2278 | // Protect |
||
| 2279 | 'jetpack_protect_key' => array( |
||
| 2280 | 'description' => esc_html__( 'Protect API key', 'jetpack' ), |
||
| 2281 | 'type' => 'string', |
||
| 2282 | 'default' => '', |
||
| 2283 | 'validate_callback' => __CLASS__ . '::validate_alphanum', |
||
| 2284 | 'jp_group' => 'protect', |
||
| 2285 | ), |
||
| 2286 | 'jetpack_protect_global_whitelist' => array( |
||
| 2287 | 'description' => esc_html__( 'Protect global whitelist', 'jetpack' ), |
||
| 2288 | 'type' => 'string', |
||
| 2289 | 'default' => '', |
||
| 2290 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 2291 | 'sanitize_callback' => 'esc_textarea', |
||
| 2292 | 'jp_group' => 'protect', |
||
| 2293 | ), |
||
| 2294 | |||
| 2295 | // Sharing |
||
| 2296 | 'sharing_services' => array( |
||
| 2297 | 'description' => esc_html__( 'Enabled Services and those hidden behind a button', 'jetpack' ), |
||
| 2298 | 'type' => 'object', |
||
| 2299 | 'default' => array( |
||
| 2300 | 'visible' => array( 'twitter', 'facebook' ), |
||
| 2301 | 'hidden' => array(), |
||
| 2302 | ), |
||
| 2303 | 'validate_callback' => __CLASS__ . '::validate_services', |
||
| 2304 | 'jp_group' => 'sharedaddy', |
||
| 2305 | ), |
||
| 2306 | 'button_style' => array( |
||
| 2307 | 'description' => esc_html__( 'Button Style', 'jetpack' ), |
||
| 2308 | 'type' => 'string', |
||
| 2309 | 'default' => 'icon', |
||
| 2310 | 'enum' => array( |
||
| 2311 | 'icon-text', |
||
| 2312 | 'icon', |
||
| 2313 | 'text', |
||
| 2314 | 'official', |
||
| 2315 | ), |
||
| 2316 | 'enum_labels' => array( |
||
| 2317 | 'icon-text' => esc_html__( 'Icon + text', 'jetpack' ), |
||
| 2318 | 'icon' => esc_html__( 'Icon only', 'jetpack' ), |
||
| 2319 | 'text' => esc_html__( 'Text only', 'jetpack' ), |
||
| 2320 | 'official' => esc_html__( 'Official buttons', 'jetpack' ), |
||
| 2321 | ), |
||
| 2322 | 'validate_callback' => __CLASS__ . '::validate_list_item', |
||
| 2323 | 'jp_group' => 'sharedaddy', |
||
| 2324 | ), |
||
| 2325 | 'sharing_label' => array( |
||
| 2326 | 'description' => esc_html__( 'Sharing Label', 'jetpack' ), |
||
| 2327 | 'type' => 'string', |
||
| 2328 | 'default' => '', |
||
| 2329 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 2330 | 'sanitize_callback' => 'esc_html', |
||
| 2331 | 'jp_group' => 'sharedaddy', |
||
| 2332 | ), |
||
| 2333 | 'show' => array( |
||
| 2334 | 'description' => esc_html__( 'Views where buttons are shown', 'jetpack' ), |
||
| 2335 | 'type' => 'array', |
||
| 2336 | 'items' => array( |
||
| 2337 | 'type' => 'string' |
||
| 2338 | ), |
||
| 2339 | 'default' => array( 'post' ), |
||
| 2340 | 'validate_callback' => __CLASS__ . '::validate_sharing_show', |
||
| 2341 | 'jp_group' => 'sharedaddy', |
||
| 2342 | ), |
||
| 2343 | 'jetpack-twitter-cards-site-tag' => array( |
||
| 2344 | 'description' => esc_html__( "The Twitter username of the owner of this site's domain.", 'jetpack' ), |
||
| 2345 | 'type' => 'string', |
||
| 2346 | 'default' => '', |
||
| 2347 | 'validate_callback' => __CLASS__ . '::validate_twitter_username', |
||
| 2348 | 'sanitize_callback' => 'esc_html', |
||
| 2349 | 'jp_group' => 'sharedaddy', |
||
| 2350 | ), |
||
| 2351 | 'sharedaddy_disable_resources' => array( |
||
| 2352 | 'description' => esc_html__( 'Disable CSS and JS', 'jetpack' ), |
||
| 2353 | 'type' => 'boolean', |
||
| 2354 | 'default' => 0, |
||
| 2355 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2356 | 'jp_group' => 'sharedaddy', |
||
| 2357 | ), |
||
| 2358 | 'custom' => array( |
||
| 2359 | 'description' => esc_html__( 'Custom sharing services added by user.', 'jetpack' ), |
||
| 2360 | 'type' => 'object', |
||
| 2361 | 'default' => array( |
||
| 2362 | 'sharing_name' => '', |
||
| 2363 | 'sharing_url' => '', |
||
| 2364 | 'sharing_icon' => '', |
||
| 2365 | ), |
||
| 2366 | 'validate_callback' => __CLASS__ . '::validate_custom_service', |
||
| 2367 | 'jp_group' => 'sharedaddy', |
||
| 2368 | ), |
||
| 2369 | // Not an option, but an action that can be perfomed on the list of custom services passing the service ID. |
||
| 2370 | 'sharing_delete_service' => array( |
||
| 2371 | 'description' => esc_html__( 'Delete custom sharing service.', 'jetpack' ), |
||
| 2372 | 'type' => 'string', |
||
| 2373 | 'default' => '', |
||
| 2374 | 'validate_callback' => __CLASS__ . '::validate_custom_service_id', |
||
| 2375 | 'jp_group' => 'sharedaddy', |
||
| 2376 | ), |
||
| 2377 | |||
| 2378 | // SSO |
||
| 2379 | 'jetpack_sso_require_two_step' => array( |
||
| 2380 | 'description' => esc_html__( 'Require Two-Step Authentication', 'jetpack' ), |
||
| 2381 | 'type' => 'boolean', |
||
| 2382 | 'default' => 0, |
||
| 2383 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2384 | 'jp_group' => 'sso', |
||
| 2385 | ), |
||
| 2386 | 'jetpack_sso_match_by_email' => array( |
||
| 2387 | 'description' => esc_html__( 'Match by Email', 'jetpack' ), |
||
| 2388 | 'type' => 'boolean', |
||
| 2389 | 'default' => 0, |
||
| 2390 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2391 | 'jp_group' => 'sso', |
||
| 2392 | ), |
||
| 2393 | |||
| 2394 | // Subscriptions |
||
| 2395 | 'stb_enabled' => array( |
||
| 2396 | 'description' => esc_html__( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ), |
||
| 2397 | 'type' => 'boolean', |
||
| 2398 | 'default' => 1, |
||
| 2399 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2400 | 'jp_group' => 'subscriptions', |
||
| 2401 | ), |
||
| 2402 | 'stc_enabled' => array( |
||
| 2403 | 'description' => esc_html__( "Show a <em>'follow comments'</em> option in the comment form", 'jetpack' ), |
||
| 2404 | 'type' => 'boolean', |
||
| 2405 | 'default' => 1, |
||
| 2406 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2407 | 'jp_group' => 'subscriptions', |
||
| 2408 | ), |
||
| 2409 | 'social_notifications_subscribe' => array( |
||
| 2410 | 'description' => esc_html__( 'Send email notification when someone follows my blog', 'jetpack' ), |
||
| 2411 | 'type' => 'boolean', |
||
| 2412 | 'default' => 0, |
||
| 2413 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2414 | 'jp_group' => 'subscriptions', |
||
| 2415 | ), |
||
| 2416 | |||
| 2417 | // Related Posts |
||
| 2418 | 'show_headline' => array( |
||
| 2419 | 'description' => esc_html__( 'Highlight related content with a heading', 'jetpack' ), |
||
| 2420 | 'type' => 'boolean', |
||
| 2421 | 'default' => 1, |
||
| 2422 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2423 | 'jp_group' => 'related-posts', |
||
| 2424 | ), |
||
| 2425 | 'show_thumbnails' => array( |
||
| 2426 | 'description' => esc_html__( 'Show a thumbnail image where available', 'jetpack' ), |
||
| 2427 | 'type' => 'boolean', |
||
| 2428 | 'default' => 0, |
||
| 2429 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2430 | 'jp_group' => 'related-posts', |
||
| 2431 | ), |
||
| 2432 | |||
| 2433 | // Search. |
||
| 2434 | 'instant_search_enabled' => array( |
||
| 2435 | 'description' => esc_html__( 'Enable Instant Search', 'jetpack' ), |
||
| 2436 | 'type' => 'boolean', |
||
| 2437 | 'default' => 0, |
||
| 2438 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2439 | 'jp_group' => 'search', |
||
| 2440 | ), |
||
| 2441 | |||
| 2442 | 'has_jetpack_search_product' => array( |
||
| 2443 | 'description' => esc_html__( 'Has an active Jetpack Search product purchase', 'jetpack' ), |
||
| 2444 | 'type' => 'boolean', |
||
| 2445 | 'default' => 0, |
||
| 2446 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2447 | 'jp_group' => 'settings', |
||
| 2448 | ), |
||
| 2449 | |||
| 2450 | 'search_auto_config' => array( |
||
| 2451 | 'description' => esc_html__( 'Trigger an auto config of instant search', 'jetpack' ), |
||
| 2452 | 'type' => 'boolean', |
||
| 2453 | 'default' => 0, |
||
| 2454 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2455 | 'jp_group' => 'search', |
||
| 2456 | ), |
||
| 2457 | |||
| 2458 | // Verification Tools |
||
| 2459 | 'google' => array( |
||
| 2460 | 'description' => esc_html__( 'Google Search Console', 'jetpack' ), |
||
| 2461 | 'type' => 'string', |
||
| 2462 | 'default' => '', |
||
| 2463 | 'validate_callback' => __CLASS__ . '::validate_verification_service', |
||
| 2464 | 'jp_group' => 'verification-tools', |
||
| 2465 | ), |
||
| 2466 | 'bing' => array( |
||
| 2467 | 'description' => esc_html__( 'Bing Webmaster Center', 'jetpack' ), |
||
| 2468 | 'type' => 'string', |
||
| 2469 | 'default' => '', |
||
| 2470 | 'validate_callback' => __CLASS__ . '::validate_verification_service', |
||
| 2471 | 'jp_group' => 'verification-tools', |
||
| 2472 | ), |
||
| 2473 | 'pinterest' => array( |
||
| 2474 | 'description' => esc_html__( 'Pinterest Site Verification', 'jetpack' ), |
||
| 2475 | 'type' => 'string', |
||
| 2476 | 'default' => '', |
||
| 2477 | 'validate_callback' => __CLASS__ . '::validate_verification_service', |
||
| 2478 | 'jp_group' => 'verification-tools', |
||
| 2479 | ), |
||
| 2480 | 'yandex' => array( |
||
| 2481 | 'description' => esc_html__( 'Yandex Site Verification', 'jetpack' ), |
||
| 2482 | 'type' => 'string', |
||
| 2483 | 'default' => '', |
||
| 2484 | 'validate_callback' => __CLASS__ . '::validate_verification_service', |
||
| 2485 | 'jp_group' => 'verification-tools', |
||
| 2486 | ), |
||
| 2487 | |||
| 2488 | // WordAds. |
||
| 2489 | 'enable_header_ad' => array( |
||
| 2490 | 'description' => esc_html__( 'Display an ad unit at the top of each page.', 'jetpack' ), |
||
| 2491 | 'type' => 'boolean', |
||
| 2492 | 'default' => 1, |
||
| 2493 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2494 | 'jp_group' => 'wordads', |
||
| 2495 | ), |
||
| 2496 | 'wordads_approved' => array( |
||
| 2497 | 'description' => esc_html__( 'Is site approved for WordAds?', 'jetpack' ), |
||
| 2498 | 'type' => 'boolean', |
||
| 2499 | 'default' => 0, |
||
| 2500 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2501 | 'jp_group' => 'wordads', |
||
| 2502 | ), |
||
| 2503 | 'wordads_second_belowpost' => array( |
||
| 2504 | 'description' => esc_html__( 'Display second ad below post?', 'jetpack' ), |
||
| 2505 | 'type' => 'boolean', |
||
| 2506 | 'default' => 1, |
||
| 2507 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2508 | 'jp_group' => 'wordads', |
||
| 2509 | ), |
||
| 2510 | 'wordads_display_front_page' => array( |
||
| 2511 | 'description' => esc_html__( 'Display ads on the front page?', 'jetpack' ), |
||
| 2512 | 'type' => 'boolean', |
||
| 2513 | 'default' => 1, |
||
| 2514 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2515 | 'jp_group' => 'wordads', |
||
| 2516 | ), |
||
| 2517 | 'wordads_display_post' => array( |
||
| 2518 | 'description' => esc_html__( 'Display ads on posts?', 'jetpack' ), |
||
| 2519 | 'type' => 'boolean', |
||
| 2520 | 'default' => 1, |
||
| 2521 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2522 | 'jp_group' => 'wordads', |
||
| 2523 | ), |
||
| 2524 | 'wordads_display_page' => array( |
||
| 2525 | 'description' => esc_html__( 'Display ads on pages?', 'jetpack' ), |
||
| 2526 | 'type' => 'boolean', |
||
| 2527 | 'default' => 1, |
||
| 2528 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2529 | 'jp_group' => 'wordads', |
||
| 2530 | ), |
||
| 2531 | 'wordads_display_archive' => array( |
||
| 2532 | 'description' => esc_html__( 'Display ads on archive pages?', 'jetpack' ), |
||
| 2533 | 'type' => 'boolean', |
||
| 2534 | 'default' => 1, |
||
| 2535 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2536 | 'jp_group' => 'wordads', |
||
| 2537 | ), |
||
| 2538 | 'wordads_custom_adstxt_enabled' => array( |
||
| 2539 | 'description' => esc_html__( 'Custom ads.txt', 'jetpack' ), |
||
| 2540 | 'type' => 'boolean', |
||
| 2541 | 'default' => 0, |
||
| 2542 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2543 | 'jp_group' => 'wordads', |
||
| 2544 | ), |
||
| 2545 | 'wordads_custom_adstxt' => array( |
||
| 2546 | 'description' => esc_html__( 'Custom ads.txt entries', 'jetpack' ), |
||
| 2547 | 'type' => 'string', |
||
| 2548 | 'default' => '', |
||
| 2549 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 2550 | 'sanitize_callback' => 'sanitize_textarea_field', |
||
| 2551 | 'jp_group' => 'wordads', |
||
| 2552 | ), |
||
| 2553 | 'wordads_ccpa_enabled' => array( |
||
| 2554 | 'description' => esc_html__( 'Enable support for California Consumer Privacy Act', 'jetpack' ), |
||
| 2555 | 'type' => 'boolean', |
||
| 2556 | 'default' => 0, |
||
| 2557 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2558 | 'jp_group' => 'wordads', |
||
| 2559 | ), |
||
| 2560 | 'wordads_ccpa_privacy_policy_url' => array( |
||
| 2561 | 'description' => esc_html__( 'Privacy Policy URL', 'jetpack' ), |
||
| 2562 | 'type' => 'string', |
||
| 2563 | 'default' => '', |
||
| 2564 | 'validate_callback' => __CLASS__ . '::validate_string', |
||
| 2565 | 'sanitize_callback' => 'sanitize_text_field', |
||
| 2566 | 'jp_group' => 'wordads', |
||
| 2567 | ), |
||
| 2568 | |||
| 2569 | // Google Analytics |
||
| 2570 | 'google_analytics_tracking_id' => array( |
||
| 2571 | 'description' => esc_html__( 'Google Analytics', 'jetpack' ), |
||
| 2572 | 'type' => 'string', |
||
| 2573 | 'default' => '', |
||
| 2574 | 'validate_callback' => __CLASS__ . '::validate_alphanum', |
||
| 2575 | 'jp_group' => 'google-analytics', |
||
| 2576 | ), |
||
| 2577 | |||
| 2578 | // Stats |
||
| 2579 | 'admin_bar' => array( |
||
| 2580 | 'description' => esc_html__( 'Include a small chart in your admin bar with a 48-hour traffic snapshot.', 'jetpack' ), |
||
| 2581 | 'type' => 'boolean', |
||
| 2582 | 'default' => 1, |
||
| 2583 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2584 | 'jp_group' => 'stats', |
||
| 2585 | ), |
||
| 2586 | 'roles' => array( |
||
| 2587 | 'description' => esc_html__( 'Select the roles that will be able to view stats reports.', 'jetpack' ), |
||
| 2588 | 'type' => 'array', |
||
| 2589 | 'items' => array( |
||
| 2590 | 'type' => 'string' |
||
| 2591 | ), |
||
| 2592 | 'default' => array( 'administrator' ), |
||
| 2593 | 'validate_callback' => __CLASS__ . '::validate_stats_roles', |
||
| 2594 | 'sanitize_callback' => __CLASS__ . '::sanitize_stats_allowed_roles', |
||
| 2595 | 'jp_group' => 'stats', |
||
| 2596 | ), |
||
| 2597 | 'count_roles' => array( |
||
| 2598 | 'description' => esc_html__( 'Count the page views of registered users who are logged in.', 'jetpack' ), |
||
| 2599 | 'type' => 'array', |
||
| 2600 | 'items' => array( |
||
| 2601 | 'type' => 'string' |
||
| 2602 | ), |
||
| 2603 | 'default' => array( 'administrator' ), |
||
| 2604 | 'validate_callback' => __CLASS__ . '::validate_stats_roles', |
||
| 2605 | 'jp_group' => 'stats', |
||
| 2606 | ), |
||
| 2607 | 'blog_id' => array( |
||
| 2608 | 'description' => esc_html__( 'Blog ID.', 'jetpack' ), |
||
| 2609 | 'type' => 'boolean', |
||
| 2610 | 'default' => 0, |
||
| 2611 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2612 | 'jp_group' => 'stats', |
||
| 2613 | ), |
||
| 2614 | 'do_not_track' => array( |
||
| 2615 | 'description' => esc_html__( 'Do not track.', 'jetpack' ), |
||
| 2616 | 'type' => 'boolean', |
||
| 2617 | 'default' => 1, |
||
| 2618 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2619 | 'jp_group' => 'stats', |
||
| 2620 | ), |
||
| 2621 | 'hide_smile' => array( |
||
| 2622 | 'description' => esc_html__( 'Hide the stats smiley face image.', 'jetpack' ), |
||
| 2623 | 'type' => 'boolean', |
||
| 2624 | 'default' => 1, |
||
| 2625 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2626 | 'jp_group' => 'stats', |
||
| 2627 | ), |
||
| 2628 | 'version' => array( |
||
| 2629 | 'description' => esc_html__( 'Version.', 'jetpack' ), |
||
| 2630 | 'type' => 'integer', |
||
| 2631 | 'default' => 9, |
||
| 2632 | 'validate_callback' => __CLASS__ . '::validate_posint', |
||
| 2633 | 'jp_group' => 'stats', |
||
| 2634 | ), |
||
| 2635 | |||
| 2636 | // Akismet - Not a module, but a plugin. The options can be passed and handled differently. |
||
| 2637 | 'akismet_show_user_comments_approved' => array( |
||
| 2638 | 'description' => '', |
||
| 2639 | 'type' => 'boolean', |
||
| 2640 | 'default' => 0, |
||
| 2641 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2642 | 'jp_group' => 'settings', |
||
| 2643 | ), |
||
| 2644 | |||
| 2645 | 'wordpress_api_key' => array( |
||
| 2646 | 'description' => '', |
||
| 2647 | 'type' => 'string', |
||
| 2648 | 'default' => '', |
||
| 2649 | 'validate_callback' => __CLASS__ . '::validate_alphanum', |
||
| 2650 | 'jp_group' => 'settings', |
||
| 2651 | ), |
||
| 2652 | |||
| 2653 | // Apps card on dashboard |
||
| 2654 | 'dismiss_dash_app_card' => array( |
||
| 2655 | 'description' => '', |
||
| 2656 | 'type' => 'boolean', |
||
| 2657 | 'default' => 0, |
||
| 2658 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2659 | 'jp_group' => 'settings', |
||
| 2660 | ), |
||
| 2661 | |||
| 2662 | // Empty stats card dismiss |
||
| 2663 | 'dismiss_empty_stats_card' => array( |
||
| 2664 | 'description' => '', |
||
| 2665 | 'type' => 'boolean', |
||
| 2666 | 'default' => 0, |
||
| 2667 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2668 | 'jp_group' => 'settings', |
||
| 2669 | ), |
||
| 2670 | |||
| 2671 | 'lang_id' => array( |
||
| 2672 | 'description' => esc_html__( 'Primary language for the site.', 'jetpack' ), |
||
| 2673 | 'type' => 'string', |
||
| 2674 | 'default' => 'en_US', |
||
| 2675 | 'jp_group' => 'settings', |
||
| 2676 | ), |
||
| 2677 | |||
| 2678 | 'onboarding' => array( |
||
| 2679 | 'description' => '', |
||
| 2680 | 'type' => 'object', |
||
| 2681 | 'default' => array( |
||
| 2682 | 'siteTitle' => '', |
||
| 2683 | 'siteDescription' => '', |
||
| 2684 | 'siteType' => 'personal', |
||
| 2685 | 'homepageFormat' => 'posts', |
||
| 2686 | 'addContactForm' => 0, |
||
| 2687 | 'businessAddress' => array( |
||
| 2688 | 'name' => '', |
||
| 2689 | 'street' => '', |
||
| 2690 | 'city' => '', |
||
| 2691 | 'state' => '', |
||
| 2692 | 'zip' => '', |
||
| 2693 | ), |
||
| 2694 | 'installWooCommerce' => false, |
||
| 2695 | ), |
||
| 2696 | 'validate_callback' => __CLASS__ . '::validate_onboarding', |
||
| 2697 | 'jp_group' => 'settings', |
||
| 2698 | ), |
||
| 2699 | |||
| 2700 | ); |
||
| 2701 | |||
| 2702 | // Add modules to list so they can be toggled |
||
| 2703 | $modules = Jetpack::get_available_modules(); |
||
| 2704 | if ( is_array( $modules ) && ! empty( $modules ) ) { |
||
| 2705 | $module_args = array( |
||
| 2706 | 'description' => '', |
||
| 2707 | 'type' => 'boolean', |
||
| 2708 | 'default' => 0, |
||
| 2709 | 'validate_callback' => __CLASS__ . '::validate_boolean', |
||
| 2710 | 'jp_group' => 'modules', |
||
| 2711 | ); |
||
| 2712 | foreach( $modules as $module ) { |
||
| 2713 | $options[ $module ] = $module_args; |
||
| 2714 | } |
||
| 2715 | } |
||
| 2716 | |||
| 2717 | if ( is_array( $selector ) ) { |
||
| 2718 | |||
| 2719 | // Return only those options whose keys match $selector keys |
||
| 2720 | return array_intersect_key( $options, $selector ); |
||
| 2721 | } |
||
| 2722 | |||
| 2723 | if ( 'any' === $selector ) { |
||
| 2724 | |||
| 2725 | // Toggle module or update any module option or any general setting |
||
| 2726 | return $options; |
||
| 2727 | } |
||
| 2728 | |||
| 2729 | // We're updating the options for a single module. |
||
| 2730 | if ( empty( $selector ) ) { |
||
| 2731 | $selector = self::get_module_requested(); |
||
| 2732 | } |
||
| 2733 | $selected = array(); |
||
| 2734 | foreach ( $options as $option => $attributes ) { |
||
| 2735 | |||
| 2736 | // Not adding an isset( $attributes['jp_group'] ) because if it's not set, it must be fixed, otherwise options will fail. |
||
| 2737 | if ( $selector === $attributes['jp_group'] ) { |
||
| 2738 | $selected[ $option ] = $attributes; |
||
| 2739 | } |
||
| 2740 | } |
||
| 2741 | return $selected; |
||
| 2742 | } |
||
| 2743 | |||
| 2744 | /** |
||
| 2745 | * Validates that the parameters are proper values that can be set during Jetpack onboarding. |
||
| 2746 | * |
||
| 2747 | * @since 5.4.0 |
||
| 2748 | * |
||
| 2749 | * @param array $onboarding_data Values to check. |
||
| 2750 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2751 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2752 | * |
||
| 2753 | * @return bool|WP_Error |
||
| 2754 | */ |
||
| 2755 | public static function validate_onboarding( $onboarding_data, $request, $param ) { |
||
| 2756 | if ( ! is_array( $onboarding_data ) ) { |
||
| 2757 | return new WP_Error( 'invalid_param', esc_html__( 'Not valid onboarding data.', 'jetpack' ) ); |
||
| 2758 | } |
||
| 2759 | foreach ( $onboarding_data as $value ) { |
||
| 2760 | if ( is_string( $value ) ) { |
||
| 2761 | $onboarding_choice = self::validate_string( $value, $request, $param ); |
||
| 2762 | } elseif ( is_array( $value ) ) { |
||
| 2763 | $onboarding_choice = self::validate_onboarding( $value, $request, $param ); |
||
| 2764 | } else { |
||
| 2765 | $onboarding_choice = self::validate_boolean( $value, $request, $param ); |
||
| 2766 | } |
||
| 2767 | if ( is_wp_error( $onboarding_choice ) ) { |
||
| 2768 | return $onboarding_choice; |
||
| 2769 | } |
||
| 2770 | } |
||
| 2771 | return true; |
||
| 2772 | } |
||
| 2773 | |||
| 2774 | /** |
||
| 2775 | * Validates that the parameter is either a pure boolean or a numeric string that can be mapped to a boolean. |
||
| 2776 | * |
||
| 2777 | * @since 4.3.0 |
||
| 2778 | * |
||
| 2779 | * @param string|bool $value Value to check. |
||
| 2780 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2781 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2782 | * |
||
| 2783 | * @return bool|WP_Error |
||
| 2784 | */ |
||
| 2785 | public static function validate_boolean( $value, $request, $param ) { |
||
| 2786 | if ( ! is_bool( $value ) && ! ( ( ctype_digit( $value ) || is_numeric( $value ) ) && in_array( $value, array( 0, 1 ) ) ) ) { |
||
| 2787 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be true, false, 0 or 1.', 'jetpack' ), $param ) ); |
||
| 2788 | } |
||
| 2789 | return true; |
||
| 2790 | } |
||
| 2791 | |||
| 2792 | /** |
||
| 2793 | * Validates that the parameter is a positive integer. |
||
| 2794 | * |
||
| 2795 | * @since 4.3.0 |
||
| 2796 | * |
||
| 2797 | * @param int $value Value to check. |
||
| 2798 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2799 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2800 | * |
||
| 2801 | * @return bool|WP_Error |
||
| 2802 | */ |
||
| 2803 | public static function validate_posint( $value, $request, $param ) { |
||
| 2804 | View Code Duplication | if ( ! is_numeric( $value ) || $value <= 0 ) { |
|
| 2805 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a positive integer.', 'jetpack' ), $param ) ); |
||
| 2806 | } |
||
| 2807 | return true; |
||
| 2808 | } |
||
| 2809 | |||
| 2810 | /** |
||
| 2811 | * Validates that the parameter belongs to a list of admitted values. |
||
| 2812 | * |
||
| 2813 | * @since 4.3.0 |
||
| 2814 | * |
||
| 2815 | * @param string $value Value to check. |
||
| 2816 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2817 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2818 | * |
||
| 2819 | * @return bool|WP_Error |
||
| 2820 | */ |
||
| 2821 | public static function validate_list_item( $value, $request, $param ) { |
||
| 2822 | $attributes = $request->get_attributes(); |
||
| 2823 | if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { |
||
| 2824 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s not recognized', 'jetpack' ), $param ) ); |
||
| 2825 | } |
||
| 2826 | $args = $attributes['args'][ $param ]; |
||
| 2827 | if ( ! empty( $args['enum'] ) ) { |
||
| 2828 | |||
| 2829 | // If it's an associative array, use the keys to check that the value is among those admitted. |
||
| 2830 | $enum = ( count( array_filter( array_keys( $args['enum'] ), 'is_string' ) ) > 0 ) ? array_keys( $args['enum'] ) : $args['enum']; |
||
| 2831 | View Code Duplication | if ( ! in_array( $value, $enum ) ) { |
|
| 2832 | return new WP_Error( 'invalid_param_value', sprintf( |
||
| 2833 | /* Translators: first variable is the parameter passed to endpoint that holds the list item, the second is a list of admitted values. */ |
||
| 2834 | esc_html__( '%1$s must be one of %2$s', 'jetpack' ), $param, implode( ', ', $enum ) |
||
| 2835 | ) ); |
||
| 2836 | } |
||
| 2837 | } |
||
| 2838 | return true; |
||
| 2839 | } |
||
| 2840 | |||
| 2841 | /** |
||
| 2842 | * Validates that the parameter belongs to a list of admitted values. |
||
| 2843 | * |
||
| 2844 | * @since 4.3.0 |
||
| 2845 | * |
||
| 2846 | * @param string $value Value to check. |
||
| 2847 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2848 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2849 | * |
||
| 2850 | * @return bool|WP_Error |
||
| 2851 | */ |
||
| 2852 | public static function validate_module_list( $value, $request, $param ) { |
||
| 2853 | View Code Duplication | if ( ! is_array( $value ) ) { |
|
| 2854 | return new WP_Error( 'invalid_param_value', sprintf( esc_html__( '%s must be an array', 'jetpack' ), $param ) ); |
||
| 2855 | } |
||
| 2856 | |||
| 2857 | $modules = Jetpack::get_available_modules(); |
||
| 2858 | |||
| 2859 | View Code Duplication | if ( count( array_intersect( $value, $modules ) ) != count( $value ) ) { |
|
| 2860 | return new WP_Error( 'invalid_param_value', sprintf( esc_html__( '%s must be a list of valid modules', 'jetpack' ), $param ) ); |
||
| 2861 | } |
||
| 2862 | |||
| 2863 | return true; |
||
| 2864 | } |
||
| 2865 | |||
| 2866 | /** |
||
| 2867 | * Validates that the parameter is an alphanumeric or empty string (to be able to clear the field). |
||
| 2868 | * |
||
| 2869 | * @since 4.3.0 |
||
| 2870 | * |
||
| 2871 | * @param string $value Value to check. |
||
| 2872 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2873 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2874 | * |
||
| 2875 | * @return bool|WP_Error |
||
| 2876 | */ |
||
| 2877 | public static function validate_alphanum( $value, $request, $param ) { |
||
| 2878 | View Code Duplication | if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/^[a-z0-9]+$/i', $value ) ) ) { |
|
| 2879 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an alphanumeric string.', 'jetpack' ), $param ) ); |
||
| 2880 | } |
||
| 2881 | return true; |
||
| 2882 | } |
||
| 2883 | |||
| 2884 | /** |
||
| 2885 | * Validates that the parameter is a tag or id for a verification service, or an empty string (to be able to clear the field). |
||
| 2886 | * |
||
| 2887 | * @since 4.6.0 |
||
| 2888 | * |
||
| 2889 | * @param string $value Value to check. |
||
| 2890 | * @param WP_REST_Request $request |
||
| 2891 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2892 | * |
||
| 2893 | * @return bool|WP_Error |
||
| 2894 | */ |
||
| 2895 | public static function validate_verification_service( $value, $request, $param ) { |
||
| 2896 | if ( ! empty( $value ) && ! ( is_string( $value ) && ( preg_match( '/^[a-z0-9_-]+$/i', $value ) || jetpack_verification_get_code( $value ) !== false ) ) ) { |
||
| 2897 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an alphanumeric string or a verification tag.', 'jetpack' ), $param ) ); |
||
| 2898 | } |
||
| 2899 | return true; |
||
| 2900 | } |
||
| 2901 | |||
| 2902 | /** |
||
| 2903 | * Validates that the parameter is among the roles allowed for Stats. |
||
| 2904 | * |
||
| 2905 | * @since 4.3.0 |
||
| 2906 | * |
||
| 2907 | * @param string|bool $value Value to check. |
||
| 2908 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2909 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2910 | * |
||
| 2911 | * @return bool|WP_Error |
||
| 2912 | */ |
||
| 2913 | public static function validate_stats_roles( $value, $request, $param ) { |
||
| 2914 | if ( ! empty( $value ) && ! array_intersect( self::$stats_roles, $value ) ) { |
||
| 2915 | return new WP_Error( 'invalid_param', sprintf( |
||
| 2916 | /* Translators: first variable is the name of a parameter passed to endpoint holding the role that will be checked, the second is a list of roles allowed to see stats. The parameter is checked against this list. */ |
||
| 2917 | esc_html__( '%1$s must be %2$s.', 'jetpack' ), $param, join( ', ', self::$stats_roles ) |
||
| 2918 | ) ); |
||
| 2919 | } |
||
| 2920 | return true; |
||
| 2921 | } |
||
| 2922 | |||
| 2923 | /** |
||
| 2924 | * Validates that the parameter is among the views where the Sharing can be displayed. |
||
| 2925 | * |
||
| 2926 | * @since 4.3.0 |
||
| 2927 | * |
||
| 2928 | * @param string|bool $value Value to check. |
||
| 2929 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2930 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2931 | * |
||
| 2932 | * @return bool|WP_Error |
||
| 2933 | */ |
||
| 2934 | public static function validate_sharing_show( $value, $request, $param ) { |
||
| 2935 | $views = array( 'index', 'post', 'page', 'attachment', 'jetpack-portfolio' ); |
||
| 2936 | View Code Duplication | if ( ! is_array( $value ) ) { |
|
| 2937 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array of post types.', 'jetpack' ), $param ) ); |
||
| 2938 | } |
||
| 2939 | View Code Duplication | if ( ! array_intersect( $views, $value ) ) { |
|
| 2940 | return new WP_Error( 'invalid_param', sprintf( |
||
| 2941 | /* Translators: first variable is the name of a parameter passed to endpoint holding the post type where Sharing will be displayed, the second is a list of post types where Sharing can be displayed */ |
||
| 2942 | esc_html__( '%1$s must be %2$s.', 'jetpack' ), $param, join( ', ', $views ) |
||
| 2943 | ) ); |
||
| 2944 | } |
||
| 2945 | return true; |
||
| 2946 | } |
||
| 2947 | |||
| 2948 | /** |
||
| 2949 | * Validates that the parameter is among the views where the Sharing can be displayed. |
||
| 2950 | * |
||
| 2951 | * @since 4.3.0 |
||
| 2952 | * |
||
| 2953 | * @param string|bool $value { |
||
| 2954 | * Value to check received by request. |
||
| 2955 | * |
||
| 2956 | * @type array $visible List of slug of services to share to that are displayed directly in the page. |
||
| 2957 | * @type array $hidden List of slug of services to share to that are concealed in a folding menu. |
||
| 2958 | * } |
||
| 2959 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 2960 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 2961 | * |
||
| 2962 | * @return bool|WP_Error |
||
| 2963 | */ |
||
| 2964 | public static function validate_services( $value, $request, $param ) { |
||
| 2965 | View Code Duplication | if ( ! is_array( $value ) || ! isset( $value['visible'] ) || ! isset( $value['hidden'] ) ) { |
|
| 2966 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array with visible and hidden items.', 'jetpack' ), $param ) ); |
||
| 2967 | } |
||
| 2968 | |||
| 2969 | // Allow to clear everything. |
||
| 2970 | if ( empty( $value['visible'] ) && empty( $value['hidden'] ) ) { |
||
| 2971 | return true; |
||
| 2972 | } |
||
| 2973 | |||
| 2974 | View Code Duplication | if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { |
|
| 2975 | return new WP_Error( 'invalid_param', esc_html__( 'Failed loading required dependency Sharing_Service.', 'jetpack' ) ); |
||
| 2976 | } |
||
| 2977 | $sharer = new Sharing_Service(); |
||
| 2978 | $services = array_keys( $sharer->get_all_services() ); |
||
| 2979 | |||
| 2980 | if ( |
||
| 2981 | ( ! empty( $value['visible'] ) && ! array_intersect( $value['visible'], $services ) ) |
||
| 2982 | || |
||
| 2983 | ( ! empty( $value['hidden'] ) && ! array_intersect( $value['hidden'], $services ) ) ) |
||
| 2984 | { |
||
| 2985 | return new WP_Error( 'invalid_param', sprintf( |
||
| 2986 | /* Translators: placeholder 1 is a parameter holding the services passed to endpoint, placeholder 2 is a list of all Jetpack Sharing services */ |
||
| 2987 | esc_html__( '%1$s visible and hidden items must be a list of %2$s.', 'jetpack' ), $param, join( ', ', $services ) |
||
| 2988 | ) ); |
||
| 2989 | } |
||
| 2990 | return true; |
||
| 2991 | } |
||
| 2992 | |||
| 2993 | /** |
||
| 2994 | * Validates that the parameter has enough information to build a custom sharing button. |
||
| 2995 | * |
||
| 2996 | * @since 4.3.0 |
||
| 2997 | * |
||
| 2998 | * @param string|bool $value Value to check. |
||
| 2999 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 3000 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 3001 | * |
||
| 3002 | * @return bool|WP_Error |
||
| 3003 | */ |
||
| 3004 | public static function validate_custom_service( $value, $request, $param ) { |
||
| 3005 | if ( ! is_array( $value ) || ! isset( $value['sharing_name'] ) || ! isset( $value['sharing_url'] ) || ! isset( $value['sharing_icon'] ) ) { |
||
| 3006 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array with sharing name, url and icon.', 'jetpack' ), $param ) ); |
||
| 3007 | } |
||
| 3008 | |||
| 3009 | // Allow to clear everything. |
||
| 3010 | if ( empty( $value['sharing_name'] ) && empty( $value['sharing_url'] ) && empty( $value['sharing_icon'] ) ) { |
||
| 3011 | return true; |
||
| 3012 | } |
||
| 3013 | |||
| 3014 | View Code Duplication | if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { |
|
| 3015 | return new WP_Error( 'invalid_param', esc_html__( 'Failed loading required dependency Sharing_Service.', 'jetpack' ) ); |
||
| 3016 | } |
||
| 3017 | |||
| 3018 | if ( ( ! empty( $value['sharing_name'] ) && ! is_string( $value['sharing_name'] ) ) |
||
| 3019 | || ( ! empty( $value['sharing_url'] ) && ! is_string( $value['sharing_url'] ) ) |
||
| 3020 | || ( ! empty( $value['sharing_icon'] ) && ! is_string( $value['sharing_icon'] ) ) ) { |
||
| 3021 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s needs sharing name, url and icon.', 'jetpack' ), $param ) ); |
||
| 3022 | } |
||
| 3023 | return true; |
||
| 3024 | } |
||
| 3025 | |||
| 3026 | /** |
||
| 3027 | * Validates that the parameter is a custom sharing service ID like 'custom-1461976264'. |
||
| 3028 | * |
||
| 3029 | * @since 4.3.0 |
||
| 3030 | * |
||
| 3031 | * @param string $value Value to check. |
||
| 3032 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 3033 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 3034 | * |
||
| 3035 | * @return bool|WP_Error |
||
| 3036 | */ |
||
| 3037 | public static function validate_custom_service_id( $value, $request, $param ) { |
||
| 3038 | View Code Duplication | if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/custom\-[0-1]+/i', $value ) ) ) { |
|
| 3039 | return new WP_Error( 'invalid_param', sprintf( esc_html__( "%s must be a string prefixed with 'custom-' and followed by a numeric ID.", 'jetpack' ), $param ) ); |
||
| 3040 | } |
||
| 3041 | |||
| 3042 | View Code Duplication | if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { |
|
| 3043 | return new WP_Error( 'invalid_param', esc_html__( 'Failed loading required dependency Sharing_Service.', 'jetpack' ) ); |
||
| 3044 | } |
||
| 3045 | $sharer = new Sharing_Service(); |
||
| 3046 | $services = array_keys( $sharer->get_all_services() ); |
||
| 3047 | |||
| 3048 | View Code Duplication | if ( ! empty( $value ) && ! in_array( $value, $services ) ) { |
|
| 3049 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s is not a registered custom sharing service.', 'jetpack' ), $param ) ); |
||
| 3050 | } |
||
| 3051 | |||
| 3052 | return true; |
||
| 3053 | } |
||
| 3054 | |||
| 3055 | /** |
||
| 3056 | * Validates that the parameter is a Twitter username or empty string (to be able to clear the field). |
||
| 3057 | * |
||
| 3058 | * @since 4.3.0 |
||
| 3059 | * |
||
| 3060 | * @param string $value Value to check. |
||
| 3061 | * @param WP_REST_Request $request |
||
| 3062 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 3063 | * |
||
| 3064 | * @return bool|WP_Error |
||
| 3065 | */ |
||
| 3066 | public static function validate_twitter_username( $value, $request, $param ) { |
||
| 3067 | View Code Duplication | if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/^@?\w{1,15}$/i', $value ) ) ) { |
|
| 3068 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a Twitter username.', 'jetpack' ), $param ) ); |
||
| 3069 | } |
||
| 3070 | return true; |
||
| 3071 | } |
||
| 3072 | |||
| 3073 | /** |
||
| 3074 | * Validates that the parameter is a string. |
||
| 3075 | * |
||
| 3076 | * @since 4.3.0 |
||
| 3077 | * |
||
| 3078 | * @param string $value Value to check. |
||
| 3079 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 3080 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 3081 | * |
||
| 3082 | * @return bool|WP_Error |
||
| 3083 | */ |
||
| 3084 | public static function validate_string( $value, $request, $param ) { |
||
| 3085 | View Code Duplication | if ( ! is_string( $value ) ) { |
|
| 3086 | return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a string.', 'jetpack' ), $param ) ); |
||
| 3087 | } |
||
| 3088 | return true; |
||
| 3089 | } |
||
| 3090 | |||
| 3091 | /** |
||
| 3092 | * If for some reason the roles allowed to see Stats are empty (for example, user tampering with checkboxes), |
||
| 3093 | * return an array with only 'administrator' as the allowed role and save it for 'roles' option. |
||
| 3094 | * |
||
| 3095 | * @since 4.3.0 |
||
| 3096 | * |
||
| 3097 | * @param string|bool $value Value to check. |
||
| 3098 | * |
||
| 3099 | * @return bool|array |
||
| 3100 | */ |
||
| 3101 | public static function sanitize_stats_allowed_roles( $value ) { |
||
| 3102 | if ( empty( $value ) ) { |
||
| 3103 | return array( 'administrator' ); |
||
| 3104 | } |
||
| 3105 | return $value; |
||
| 3106 | } |
||
| 3107 | |||
| 3108 | /** |
||
| 3109 | * Get the currently accessed route and return the module slug in it. |
||
| 3110 | * |
||
| 3111 | * @since 4.3.0 |
||
| 3112 | * |
||
| 3113 | * @param string $route Regular expression for the endpoint with the module slug to return. |
||
| 3114 | * |
||
| 3115 | * @return array|string |
||
| 3116 | */ |
||
| 3117 | public static function get_module_requested( $route = '/module/(?P<slug>[a-z\-]+)' ) { |
||
| 3118 | |||
| 3119 | if ( empty( $GLOBALS['wp']->query_vars['rest_route'] ) ) { |
||
| 3120 | return ''; |
||
| 3121 | } |
||
| 3122 | |||
| 3123 | preg_match( "#$route#", $GLOBALS['wp']->query_vars['rest_route'], $module ); |
||
| 3124 | |||
| 3125 | if ( empty( $module['slug'] ) ) { |
||
| 3126 | return ''; |
||
| 3127 | } |
||
| 3128 | |||
| 3129 | return $module['slug']; |
||
| 3130 | } |
||
| 3131 | |||
| 3132 | /** |
||
| 3133 | * Adds extra information for modules. |
||
| 3134 | * |
||
| 3135 | * @since 4.3.0 |
||
| 3136 | * |
||
| 3137 | * @param string|array $modules Can be a single module or a list of modules. |
||
| 3138 | * @param null|string $slug Slug of the module in the first parameter. |
||
| 3139 | * |
||
| 3140 | * @return array|string |
||
| 3141 | */ |
||
| 3142 | public static function prepare_modules_for_response( $modules = '', $slug = null ) { |
||
| 3143 | global $wp_rewrite; |
||
| 3144 | |||
| 3145 | /** This filter is documented in modules/sitemaps/sitemaps.php */ |
||
| 3146 | $location = apply_filters( 'jetpack_sitemap_location', '' ); |
||
| 3147 | |||
| 3148 | if ( $wp_rewrite->using_index_permalinks() ) { |
||
| 3149 | $sitemap_url = home_url( '/index.php' . $location . '/sitemap.xml' ); |
||
| 3150 | $news_sitemap_url = home_url( '/index.php' . $location . '/news-sitemap.xml' ); |
||
| 3151 | } else if ( $wp_rewrite->using_permalinks() ) { |
||
| 3152 | $sitemap_url = home_url( $location . '/sitemap.xml' ); |
||
| 3153 | $news_sitemap_url = home_url( $location . '/news-sitemap.xml' ); |
||
| 3154 | } else { |
||
| 3155 | $sitemap_url = home_url( $location . '/?jetpack-sitemap=sitemap.xml' ); |
||
| 3156 | $news_sitemap_url = home_url( $location . '/?jetpack-sitemap=news-sitemap.xml' ); |
||
| 3157 | } |
||
| 3158 | |||
| 3159 | if ( is_null( $slug ) && isset( $modules['sitemaps'] ) ) { |
||
| 3160 | // Is a list of modules |
||
| 3161 | $modules['sitemaps']['extra']['sitemap_url'] = $sitemap_url; |
||
| 3162 | $modules['sitemaps']['extra']['news_sitemap_url'] = $news_sitemap_url; |
||
| 3163 | } elseif ( 'sitemaps' == $slug ) { |
||
| 3164 | // It's a single module |
||
| 3165 | $modules['extra']['sitemap_url'] = $sitemap_url; |
||
| 3166 | $modules['extra']['news_sitemap_url'] = $news_sitemap_url; |
||
| 3167 | } |
||
| 3168 | return $modules; |
||
| 3169 | } |
||
| 3170 | |||
| 3171 | /** |
||
| 3172 | * Remove 'validate_callback' item from options available for module. |
||
| 3173 | * Fetch current option value and add to array of module options. |
||
| 3174 | * Prepare values of module options that need special handling, like those saved in wpcom. |
||
| 3175 | * |
||
| 3176 | * @since 4.3.0 |
||
| 3177 | * |
||
| 3178 | * @param string $module Module slug. |
||
| 3179 | * @return array |
||
| 3180 | */ |
||
| 3181 | public static function prepare_options_for_response( $module = '' ) { |
||
| 3182 | $options = self::get_updateable_data_list( $module ); |
||
| 3183 | |||
| 3184 | if ( ! is_array( $options ) || empty( $options ) ) { |
||
| 3185 | return $options; |
||
| 3186 | } |
||
| 3187 | |||
| 3188 | // Some modules need special treatment. |
||
| 3189 | switch ( $module ) { |
||
| 3190 | |||
| 3191 | case 'monitor': |
||
| 3192 | // Status of user notifications |
||
| 3193 | $options['monitor_receive_notifications']['current_value'] = self::cast_value( self::get_remote_value( 'monitor', 'monitor_receive_notifications' ), $options['monitor_receive_notifications'] ); |
||
| 3194 | break; |
||
| 3195 | |||
| 3196 | case 'post-by-email': |
||
| 3197 | // Email address |
||
| 3198 | $options['post_by_email_address']['current_value'] = self::cast_value( self::get_remote_value( 'post-by-email', 'post_by_email_address' ), $options['post_by_email_address'] ); |
||
| 3199 | break; |
||
| 3200 | |||
| 3201 | case 'protect': |
||
| 3202 | // Protect |
||
| 3203 | $options['jetpack_protect_key']['current_value'] = get_site_option( 'jetpack_protect_key', false ); |
||
| 3204 | if ( ! function_exists( 'jetpack_protect_format_whitelist' ) ) { |
||
| 3205 | include_once( JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php' ); |
||
| 3206 | } |
||
| 3207 | $options['jetpack_protect_global_whitelist']['current_value'] = jetpack_protect_format_whitelist(); |
||
| 3208 | break; |
||
| 3209 | |||
| 3210 | case 'related-posts': |
||
| 3211 | // It's local, but it must be broken apart since it's saved as an array. |
||
| 3212 | $options = self::split_options( $options, Jetpack_Options::get_option( 'relatedposts' ) ); |
||
| 3213 | break; |
||
| 3214 | |||
| 3215 | case 'verification-tools': |
||
| 3216 | // It's local, but it must be broken apart since it's saved as an array. |
||
| 3217 | $options = self::split_options( $options, get_option( 'verification_services_codes' ) ); |
||
| 3218 | break; |
||
| 3219 | |||
| 3220 | case 'google-analytics': |
||
| 3221 | $wga = get_option( 'jetpack_wga' ); |
||
| 3222 | $code = ''; |
||
| 3223 | if ( is_array( $wga ) && array_key_exists( 'code', $wga ) ) { |
||
| 3224 | $code = $wga[ 'code' ]; |
||
| 3225 | } |
||
| 3226 | $options[ 'google_analytics_tracking_id' ][ 'current_value' ] = $code; |
||
| 3227 | break; |
||
| 3228 | |||
| 3229 | case 'sharedaddy': |
||
| 3230 | // It's local, but it must be broken apart since it's saved as an array. |
||
| 3231 | if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { |
||
| 3232 | break; |
||
| 3233 | } |
||
| 3234 | $sharer = new Sharing_Service(); |
||
| 3235 | $options = self::split_options( $options, $sharer->get_global_options() ); |
||
| 3236 | $options['sharing_services']['current_value'] = $sharer->get_blog_services(); |
||
| 3237 | $other_sharedaddy_options = array( 'jetpack-twitter-cards-site-tag', 'sharedaddy_disable_resources', 'sharing_delete_service' ); |
||
| 3238 | View Code Duplication | foreach ( $other_sharedaddy_options as $key ) { |
|
| 3239 | $default_value = isset( $options[ $key ]['default'] ) ? $options[ $key ]['default'] : ''; |
||
| 3240 | $current_value = get_option( $key, $default_value ); |
||
| 3241 | $options[ $key ]['current_value'] = self::cast_value( $current_value, $options[ $key ] ); |
||
| 3242 | } |
||
| 3243 | break; |
||
| 3244 | |||
| 3245 | case 'stats': |
||
| 3246 | // It's local, but it must be broken apart since it's saved as an array. |
||
| 3247 | if ( ! function_exists( 'stats_get_options' ) ) { |
||
| 3248 | include_once( JETPACK__PLUGIN_DIR . 'modules/stats.php' ); |
||
| 3249 | } |
||
| 3250 | $options = self::split_options( $options, stats_get_options() ); |
||
| 3251 | break; |
||
| 3252 | default: |
||
| 3253 | // These option are just stored as plain WordPress options. |
||
| 3254 | View Code Duplication | foreach ( $options as $key => $value ) { |
|
| 3255 | $default_value = isset( $options[ $key ]['default'] ) ? $options[ $key ]['default'] : ''; |
||
| 3256 | $current_value = get_option( $key, $default_value ); |
||
| 3257 | $options[ $key ]['current_value'] = self::cast_value( $current_value, $options[ $key ] ); |
||
| 3258 | } |
||
| 3259 | } |
||
| 3260 | // At this point some options have current_value not set because they're options |
||
| 3261 | // that only get written on update, so we set current_value to the default one. |
||
| 3262 | foreach ( $options as $key => $value ) { |
||
| 3263 | // We don't need validate_callback in the response |
||
| 3264 | if ( isset( $options[ $key ]['validate_callback'] ) ) { |
||
| 3265 | unset( $options[ $key ]['validate_callback'] ); |
||
| 3266 | } |
||
| 3267 | $default_value = isset( $options[ $key ]['default'] ) ? $options[ $key ]['default'] : ''; |
||
| 3268 | if ( ! array_key_exists( 'current_value', $options[ $key ] ) ) { |
||
| 3269 | $options[ $key ]['current_value'] = self::cast_value( $default_value, $options[ $key ] ); |
||
| 3270 | } |
||
| 3271 | } |
||
| 3272 | return $options; |
||
| 3273 | } |
||
| 3274 | |||
| 3275 | /** |
||
| 3276 | * Splits module options saved as arrays like relatedposts or verification_services_codes into separate options to be returned in the response. |
||
| 3277 | * |
||
| 3278 | * @since 4.3.0 |
||
| 3279 | * |
||
| 3280 | * @param array $separate_options Array of options admitted by the module. |
||
| 3281 | * @param array $grouped_options Option saved as array to be splitted. |
||
| 3282 | * @param string $prefix Optional prefix for the separate option keys. |
||
| 3283 | * |
||
| 3284 | * @return array |
||
| 3285 | */ |
||
| 3286 | public static function split_options( $separate_options, $grouped_options, $prefix = '' ) { |
||
| 3287 | if ( is_array( $grouped_options ) ) { |
||
| 3288 | foreach ( $grouped_options as $key => $value ) { |
||
| 3289 | $option_key = $prefix . $key; |
||
| 3290 | if ( isset( $separate_options[ $option_key ] ) ) { |
||
| 3291 | $separate_options[ $option_key ]['current_value'] = self::cast_value( $grouped_options[ $key ], $separate_options[ $option_key ] ); |
||
| 3292 | } |
||
| 3293 | } |
||
| 3294 | } |
||
| 3295 | return $separate_options; |
||
| 3296 | } |
||
| 3297 | |||
| 3298 | /** |
||
| 3299 | * Perform a casting to the value specified in the option definition. |
||
| 3300 | * |
||
| 3301 | * @since 4.3.0 |
||
| 3302 | * |
||
| 3303 | * @param mixed $value Value to cast to the proper type. |
||
| 3304 | * @param array $definition Type to cast the value to. |
||
| 3305 | * |
||
| 3306 | * @return bool|float|int|string |
||
| 3307 | */ |
||
| 3308 | public static function cast_value( $value, $definition ) { |
||
| 3309 | if ( $value === 'NULL' ) { |
||
| 3310 | return null; |
||
| 3311 | } |
||
| 3312 | |||
| 3313 | if ( isset( $definition['type'] ) ) { |
||
| 3314 | switch ( $definition['type'] ) { |
||
| 3315 | case 'boolean': |
||
| 3316 | if ( 'true' === $value || 'on' === $value ) { |
||
| 3317 | return true; |
||
| 3318 | } elseif ( 'false' === $value || 'off' === $value ) { |
||
| 3319 | return false; |
||
| 3320 | } |
||
| 3321 | return (bool) $value; |
||
| 3322 | break; |
||
| 3323 | |||
| 3324 | case 'integer': |
||
| 3325 | return (int) $value; |
||
| 3326 | break; |
||
| 3327 | |||
| 3328 | case 'float': |
||
| 3329 | return (float) $value; |
||
| 3330 | break; |
||
| 3331 | |||
| 3332 | case 'string': |
||
| 3333 | return (string) $value; |
||
| 3334 | break; |
||
| 3335 | } |
||
| 3336 | } |
||
| 3337 | return $value; |
||
| 3338 | } |
||
| 3339 | |||
| 3340 | /** |
||
| 3341 | * Get a value not saved locally. |
||
| 3342 | * |
||
| 3343 | * @since 4.3.0 |
||
| 3344 | * |
||
| 3345 | * @param string $module Module slug. |
||
| 3346 | * @param string $option Option name. |
||
| 3347 | * |
||
| 3348 | * @return bool Whether user is receiving notifications or not. |
||
| 3349 | */ |
||
| 3350 | public static function get_remote_value( $module, $option ) { |
||
| 3351 | |||
| 3352 | if ( in_array( $module, array( 'post-by-email' ), true ) ) { |
||
| 3353 | $option .= get_current_user_id(); |
||
| 3354 | } |
||
| 3355 | |||
| 3356 | // If option doesn't exist, 'does_not_exist' will be returned. |
||
| 3357 | $value = get_option( $option, 'does_not_exist' ); |
||
| 3358 | |||
| 3359 | // If option exists, just return it. |
||
| 3360 | if ( 'does_not_exist' !== $value ) { |
||
| 3361 | return $value; |
||
| 3362 | } |
||
| 3363 | |||
| 3364 | // Only check a remote option if Jetpack is connected. |
||
| 3365 | if ( ! Jetpack::is_active() ) { |
||
| 3366 | return false; |
||
| 3367 | } |
||
| 3368 | |||
| 3369 | // Do what is necessary for each module. |
||
| 3370 | switch ( $module ) { |
||
| 3371 | View Code Duplication | case 'monitor': |
|
| 3372 | // Load the class to use the method. If class can't be found, do nothing. |
||
| 3373 | if ( ! class_exists( 'Jetpack_Monitor' ) && ! include_once( Jetpack::get_module_path( $module ) ) ) { |
||
| 3374 | return false; |
||
| 3375 | } |
||
| 3376 | $value = Jetpack_Monitor::user_receives_notifications( false ); |
||
| 3377 | break; |
||
| 3378 | |||
| 3379 | View Code Duplication | case 'post-by-email': |
|
| 3380 | // Load the class to use the method. If class can't be found, do nothing. |
||
| 3381 | if ( ! class_exists( 'Jetpack_Post_By_Email' ) && ! include_once( Jetpack::get_module_path( $module ) ) ) { |
||
| 3382 | return false; |
||
| 3383 | } |
||
| 3384 | $value = Jetpack_Post_By_Email::init()->get_post_by_email_address(); |
||
| 3385 | if ( $value === null ) { |
||
| 3386 | $value = 'NULL'; // sentinel value so it actually gets set |
||
| 3387 | } |
||
| 3388 | break; |
||
| 3389 | } |
||
| 3390 | |||
| 3391 | // Normalize value to boolean. |
||
| 3392 | if ( is_wp_error( $value ) || is_null( $value ) ) { |
||
| 3393 | $value = false; |
||
| 3394 | } |
||
| 3395 | |||
| 3396 | // Save option to use it next time. |
||
| 3397 | update_option( $option, $value ); |
||
| 3398 | |||
| 3399 | return $value; |
||
| 3400 | } |
||
| 3401 | |||
| 3402 | /** |
||
| 3403 | * Get number of plugin updates available. |
||
| 3404 | * |
||
| 3405 | * @since 4.3.0 |
||
| 3406 | * |
||
| 3407 | * @return mixed|WP_Error Number of plugin updates available. Otherwise, a WP_Error instance with the corresponding error. |
||
| 3408 | */ |
||
| 3409 | public static function get_plugin_update_count() { |
||
| 3410 | $updates = wp_get_update_data(); |
||
| 3411 | if ( isset( $updates['counts'] ) && isset( $updates['counts']['plugins'] ) ) { |
||
| 3412 | $count = $updates['counts']['plugins']; |
||
| 3413 | if ( 0 == $count ) { |
||
| 3414 | $response = array( |
||
| 3415 | 'code' => 'success', |
||
| 3416 | 'message' => esc_html__( 'All plugins are up-to-date. Keep up the good work!', 'jetpack' ), |
||
| 3417 | 'count' => 0, |
||
| 3418 | ); |
||
| 3419 | } else { |
||
| 3420 | $response = array( |
||
| 3421 | 'code' => 'updates-available', |
||
| 3422 | 'message' => esc_html( sprintf( _n( '%s plugin need updating.', '%s plugins need updating.', $count, 'jetpack' ), $count ) ), |
||
| 3423 | 'count' => $count, |
||
| 3424 | ); |
||
| 3425 | } |
||
| 3426 | return rest_ensure_response( $response ); |
||
| 3427 | } |
||
| 3428 | |||
| 3429 | return new WP_Error( 'not_found', esc_html__( 'Could not check updates for plugins on this site.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3430 | } |
||
| 3431 | |||
| 3432 | |||
| 3433 | /** |
||
| 3434 | * Deprecated - Get third party plugin API keys. |
||
| 3435 | * @deprecated |
||
| 3436 | * |
||
| 3437 | * @param WP_REST_Request $request { |
||
| 3438 | * Array of parameters received by request. |
||
| 3439 | * |
||
| 3440 | * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. |
||
| 3441 | * } |
||
| 3442 | */ |
||
| 3443 | public static function get_service_api_key( $request ) { |
||
| 3444 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::get_service_api_key' ); |
||
| 3445 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::get_service_api_key( $request ); |
||
| 3446 | } |
||
| 3447 | |||
| 3448 | /** |
||
| 3449 | * Deprecated - Update third party plugin API keys. |
||
| 3450 | * @deprecated |
||
| 3451 | * |
||
| 3452 | * @param WP_REST_Request $request { |
||
| 3453 | * Array of parameters received by request. |
||
| 3454 | * |
||
| 3455 | * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. |
||
| 3456 | * } |
||
| 3457 | */ |
||
| 3458 | public static function update_service_api_key( $request ) { |
||
| 3459 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::update_service_api_key' ); |
||
| 3460 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::update_service_api_key( $request ) ; |
||
| 3461 | } |
||
| 3462 | |||
| 3463 | /** |
||
| 3464 | * Deprecated - Delete a third party plugin API key. |
||
| 3465 | * @deprecated |
||
| 3466 | * |
||
| 3467 | * @param WP_REST_Request $request { |
||
| 3468 | * Array of parameters received by request. |
||
| 3469 | * |
||
| 3470 | * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. |
||
| 3471 | * } |
||
| 3472 | */ |
||
| 3473 | public static function delete_service_api_key( $request ) { |
||
| 3474 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::delete_service_api_key' ); |
||
| 3475 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::delete_service_api_key( $request ); |
||
| 3476 | } |
||
| 3477 | |||
| 3478 | /** |
||
| 3479 | * Deprecated - Validate the service provided in /service-api-keys/ endpoints. |
||
| 3480 | * To add a service to these endpoints, add the service name to $valid_services |
||
| 3481 | * and add '{service name}_api_key' to the non-compact return array in get_option_names(), |
||
| 3482 | * in class-jetpack-options.php |
||
| 3483 | * @deprecated |
||
| 3484 | * |
||
| 3485 | * @param string $service The service the API key is for. |
||
| 3486 | * @return string Returns the service name if valid, null if invalid. |
||
| 3487 | */ |
||
| 3488 | public static function validate_service_api_service( $service = null ) { |
||
| 3489 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_service' ); |
||
| 3490 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_service( $service ); |
||
| 3491 | } |
||
| 3492 | |||
| 3493 | /** |
||
| 3494 | * Error response for invalid service API key requests with an invalid service. |
||
| 3495 | */ |
||
| 3496 | public static function service_api_invalid_service_response() { |
||
| 3497 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::service_api_invalid_service_response' ); |
||
| 3498 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::service_api_invalid_service_response(); |
||
| 3499 | } |
||
| 3500 | |||
| 3501 | /** |
||
| 3502 | * Deprecated - Validate API Key |
||
| 3503 | * @deprecated |
||
| 3504 | * |
||
| 3505 | * @param string $key The API key to be validated. |
||
| 3506 | * @param string $service The service the API key is for. |
||
| 3507 | * |
||
| 3508 | */ |
||
| 3509 | public static function validate_service_api_key( $key = null, $service = null ) { |
||
| 3510 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_key' ); |
||
| 3511 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_key( $key , $service ); |
||
| 3512 | } |
||
| 3513 | |||
| 3514 | /** |
||
| 3515 | * Deprecated - Validate Mapbox API key |
||
| 3516 | * Based loosely on https://github.com/mapbox/geocoding-example/blob/master/php/MapboxTest.php |
||
| 3517 | * @deprecated |
||
| 3518 | * |
||
| 3519 | * @param string $key The API key to be validated. |
||
| 3520 | */ |
||
| 3521 | public static function validate_service_api_key_mapbox( $key ) { |
||
| 3522 | _deprecated_function( __METHOD__, 'jetpack-6.9.0', 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_key' ); |
||
| 3523 | return WPCOM_REST_API_V2_Endpoint_Service_API_Keys::validate_service_api_key_mapbox( $key ); |
||
| 3524 | |||
| 3525 | } |
||
| 3526 | |||
| 3527 | /** |
||
| 3528 | * Get plugins data in site. |
||
| 3529 | * |
||
| 3530 | * @since 4.2.0 |
||
| 3531 | * |
||
| 3532 | * @return WP_REST_Response|WP_Error List of plugins in the site. Otherwise, a WP_Error instance with the corresponding error. |
||
| 3533 | */ |
||
| 3534 | public static function get_plugins() { |
||
| 3535 | jetpack_require_lib( 'plugins' ); |
||
| 3536 | $plugins = Jetpack_Plugins::get_plugins(); |
||
| 3537 | |||
| 3538 | if ( ! empty( $plugins ) ) { |
||
| 3539 | return rest_ensure_response( $plugins ); |
||
| 3540 | } |
||
| 3541 | |||
| 3542 | return new WP_Error( 'not_found', esc_html__( 'Unable to list plugins.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3543 | } |
||
| 3544 | |||
| 3545 | /** |
||
| 3546 | * Ensures that Akismet is installed and activated. |
||
| 3547 | * |
||
| 3548 | * @since 7.7 |
||
| 3549 | * |
||
| 3550 | * @deprecated 8.9.0 Use install_plugin instead. |
||
| 3551 | * |
||
| 3552 | * @return WP_REST_Response A response indicating whether or not the installation was successful. |
||
| 3553 | */ |
||
| 3554 | public static function activate_akismet() { |
||
| 3555 | _deprecated_function( __METHOD__, 'jetpack-8.9.0', 'install_plugin' ); |
||
| 3556 | |||
| 3557 | $args = array( |
||
| 3558 | 'slug' => 'akismet', |
||
| 3559 | 'status' => 'active', |
||
| 3560 | ); |
||
| 3561 | return self::install_plugin( $args ); |
||
| 3562 | } |
||
| 3563 | |||
| 3564 | /** |
||
| 3565 | * Install a specific plugin and optionally activates it. |
||
| 3566 | * |
||
| 3567 | * @since 8.9.0 |
||
| 3568 | * |
||
| 3569 | * @param WP_REST_Request $request { |
||
| 3570 | * Array of parameters received by request. |
||
| 3571 | * |
||
| 3572 | * @type string $slug Plugin slug. |
||
| 3573 | * @type string $status Plugin status. |
||
| 3574 | * @type string $source Where did the plugin installation request originate. |
||
| 3575 | * } |
||
| 3576 | * |
||
| 3577 | * @return WP_REST_Response|WP_Error A response object if the installation and / or activation was successful, or a WP_Error object if it failed. |
||
| 3578 | */ |
||
| 3579 | public static function install_plugin( $request ) { |
||
| 3580 | $plugin = stripslashes( $request['slug'] ); |
||
| 3581 | |||
| 3582 | jetpack_require_lib( 'plugins' ); |
||
| 3583 | |||
| 3584 | // Let's make sure the plugin isn't already installed. |
||
| 3585 | $plugin_id = Jetpack_Plugins::get_plugin_id_by_slug( $plugin ); |
||
| 3586 | |||
| 3587 | // If not installed, let's install now. |
||
| 3588 | if ( ! $plugin_id ) { |
||
| 3589 | $result = Jetpack_Plugins::install_plugin( $plugin ); |
||
| 3590 | |||
| 3591 | if ( is_wp_error( $result ) ) { |
||
| 3592 | return new WP_Error( |
||
| 3593 | 'install_plugin_failed', |
||
| 3594 | sprintf( |
||
| 3595 | /* translators: %1$s: plugin name. -- %2$s: error message. */ |
||
| 3596 | __( 'Unable to install %1$s: %2$s ', 'jetpack' ), |
||
| 3597 | $plugin, |
||
| 3598 | $result->get_error_message() |
||
| 3599 | ), |
||
| 3600 | array( 'status' => 500 ) |
||
| 3601 | ); |
||
| 3602 | } |
||
| 3603 | } |
||
| 3604 | |||
| 3605 | /* |
||
| 3606 | * We may want to activate the plugin as well. |
||
| 3607 | * Let's check for the status parameter in the request to find out. |
||
| 3608 | * If none was passed (or something other than active), let's return now. |
||
| 3609 | */ |
||
| 3610 | if ( empty( $request['status'] ) || 'active' !== $request['status'] ) { |
||
| 3611 | return rest_ensure_response( |
||
| 3612 | array( |
||
| 3613 | 'code' => 'success', |
||
| 3614 | 'message' => esc_html( |
||
| 3615 | sprintf( |
||
| 3616 | /* translators: placeholder is a plugin name. */ |
||
| 3617 | __( 'Installed %s', 'jetpack' ), |
||
| 3618 | $plugin |
||
| 3619 | ) |
||
| 3620 | ), |
||
| 3621 | ) |
||
| 3622 | ); |
||
| 3623 | } |
||
| 3624 | |||
| 3625 | /* |
||
| 3626 | * Proceed with plugin activation. |
||
| 3627 | * Let's check again for the plugin's ID if we don't already have it. |
||
| 3628 | */ |
||
| 3629 | if ( ! $plugin_id ) { |
||
| 3630 | $plugin_id = Jetpack_Plugins::get_plugin_id_by_slug( $plugin ); |
||
| 3631 | if ( ! $plugin_id ) { |
||
| 3632 | return new WP_Error( |
||
| 3633 | 'unable_to_determine_installed_plugin', |
||
| 3634 | __( 'Unable to determine what plugin was installed.', 'jetpack' ), |
||
| 3635 | array( 'status' => 500 ) |
||
| 3636 | ); |
||
| 3637 | } |
||
| 3638 | } |
||
| 3639 | |||
| 3640 | $source = ! empty( $request['source'] ) ? stripslashes( $request['source'] ) : 'rest_api'; |
||
| 3641 | $plugin_args = array( |
||
| 3642 | 'plugin' => substr( $plugin_id, 0, - 4 ), |
||
| 3643 | 'status' => 'active', |
||
| 3644 | 'source' => $source, |
||
| 3645 | ); |
||
| 3646 | return self::activate_plugin( $plugin_args ); |
||
| 3647 | } |
||
| 3648 | |||
| 3649 | /** |
||
| 3650 | * Activate a specific plugin. |
||
| 3651 | * |
||
| 3652 | * @since 8.9.0 |
||
| 3653 | * |
||
| 3654 | * @param WP_REST_Request $request { |
||
| 3655 | * Array of parameters received by request. |
||
| 3656 | * |
||
| 3657 | * @type string $plugin Plugin long slug (slug/index-file) |
||
| 3658 | * @type string $status Plugin status. We only support active in Jetpack. |
||
| 3659 | * @type string $source Where did the plugin installation request originate. |
||
| 3660 | * } |
||
| 3661 | * |
||
| 3662 | * @return WP_REST_Response|WP_Error A response object if the activation was successful, or a WP_Error object if the activation failed. |
||
| 3663 | */ |
||
| 3664 | public static function activate_plugin( $request ) { |
||
| 3665 | /* |
||
| 3666 | * We need an "active" status parameter to be passed to the request |
||
| 3667 | * just like the core plugins endpoind we'll eventually switch to. |
||
| 3668 | */ |
||
| 3669 | if ( empty( $request['status'] ) || 'active' !== $request['status'] ) { |
||
| 3670 | return new WP_Error( |
||
| 3671 | 'missing_status_parameter', |
||
| 3672 | esc_html__( 'Status parameter missing.', 'jetpack' ), |
||
| 3673 | array( 'status' => 403 ) |
||
| 3674 | ); |
||
| 3675 | } |
||
| 3676 | |||
| 3677 | jetpack_require_lib( 'plugins' ); |
||
| 3678 | $plugins = Jetpack_Plugins::get_plugins(); |
||
| 3679 | |||
| 3680 | if ( empty( $plugins ) ) { |
||
| 3681 | return new WP_Error( 'no_plugins_found', esc_html__( 'This site has no plugins.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3682 | } |
||
| 3683 | |||
| 3684 | if ( empty( $request['plugin'] ) ) { |
||
| 3685 | return new WP_Error( 'no_plugin_specified', esc_html__( 'You did not specify a plugin.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3686 | } |
||
| 3687 | |||
| 3688 | $plugin = $request['plugin'] . '.php'; |
||
| 3689 | |||
| 3690 | // Is the plugin installed? |
||
| 3691 | View Code Duplication | if ( ! in_array( $plugin, array_keys( $plugins ), true ) ) { |
|
| 3692 | return new WP_Error( |
||
| 3693 | 'plugin_not_found', |
||
| 3694 | esc_html( |
||
| 3695 | sprintf( |
||
| 3696 | /* translators: placeholder is a plugin slug. */ |
||
| 3697 | __( 'Plugin %s is not installed.', 'jetpack' ), |
||
| 3698 | $plugin |
||
| 3699 | ) |
||
| 3700 | ), |
||
| 3701 | array( 'status' => 404 ) |
||
| 3702 | ); |
||
| 3703 | } |
||
| 3704 | |||
| 3705 | // Is the plugin active already? |
||
| 3706 | $status = Jetpack_Plugins::get_plugin_status( $plugin ); |
||
| 3707 | if ( in_array( $status, array( 'active', 'network-active' ), true ) ) { |
||
| 3708 | return new WP_Error( |
||
| 3709 | 'plugin_already_active', |
||
| 3710 | esc_html( |
||
| 3711 | sprintf( |
||
| 3712 | /* translators: placeholder is a plugin slug. */ |
||
| 3713 | __( 'Plugin %s is already active.', 'jetpack' ), |
||
| 3714 | $plugin |
||
| 3715 | ) |
||
| 3716 | ), |
||
| 3717 | array( 'status' => 404 ) |
||
| 3718 | ); |
||
| 3719 | } |
||
| 3720 | |||
| 3721 | // Now try to activate the plugin. |
||
| 3722 | $activated = activate_plugin( $plugin ); |
||
| 3723 | |||
| 3724 | if ( is_wp_error( $activated ) ) { |
||
| 3725 | return $activated; |
||
| 3726 | } else { |
||
| 3727 | $source = ! empty( $request['source'] ) ? stripslashes( $request['source'] ) : 'rest_api'; |
||
| 3728 | /** |
||
| 3729 | * Fires when Jetpack installs a plugin for you. |
||
| 3730 | * |
||
| 3731 | * @since 8.9.0 |
||
| 3732 | * |
||
| 3733 | * @param string $plugin_file Plugin file. |
||
| 3734 | * @param string $source Where did the plugin installation originate. |
||
| 3735 | */ |
||
| 3736 | do_action( 'jetpack_activated_plugin', $plugin, $source ); |
||
| 3737 | return rest_ensure_response( |
||
| 3738 | array( |
||
| 3739 | 'code' => 'success', |
||
| 3740 | 'message' => sprintf( |
||
| 3741 | /* translators: placeholder is a plugin name. */ |
||
| 3742 | esc_html__( 'Activated %s', 'jetpack' ), |
||
| 3743 | $plugin |
||
| 3744 | ), |
||
| 3745 | ) |
||
| 3746 | ); |
||
| 3747 | } |
||
| 3748 | } |
||
| 3749 | |||
| 3750 | /** |
||
| 3751 | * Check if a plugin can be activated. |
||
| 3752 | * |
||
| 3753 | * @since 8.9.0 |
||
| 3754 | * |
||
| 3755 | * @param string|bool $value Value to check. |
||
| 3756 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 3757 | * @param string $param Name of the parameter passed to endpoint holding $value. |
||
| 3758 | */ |
||
| 3759 | public static function validate_activate_plugin( $value, $request, $param ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable |
||
| 3760 | return 'active' === $value; |
||
| 3761 | } |
||
| 3762 | |||
| 3763 | /** |
||
| 3764 | * Get data about the queried plugin. Currently it only returns whether the plugin is active or not. |
||
| 3765 | * |
||
| 3766 | * @since 4.2.0 |
||
| 3767 | * |
||
| 3768 | * @param WP_REST_Request $request { |
||
| 3769 | * Array of parameters received by request. |
||
| 3770 | * |
||
| 3771 | * @type string $slug Plugin slug with the syntax 'plugin-directory/plugin-main-file.php'. |
||
| 3772 | * } |
||
| 3773 | * |
||
| 3774 | * @return bool|WP_Error True if module was activated. Otherwise, a WP_Error instance with the corresponding error. |
||
| 3775 | */ |
||
| 3776 | public static function get_plugin( $request ) { |
||
| 3777 | jetpack_require_lib( 'plugins' ); |
||
| 3778 | $plugins = Jetpack_Plugins::get_plugins(); |
||
| 3779 | |||
| 3780 | if ( empty( $plugins ) ) { |
||
| 3781 | return new WP_Error( 'no_plugins_found', esc_html__( 'This site has no plugins.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3782 | } |
||
| 3783 | |||
| 3784 | $plugin = stripslashes( $request['plugin'] ); |
||
| 3785 | |||
| 3786 | View Code Duplication | if ( ! in_array( $plugin, array_keys( $plugins ) ) ) { |
|
| 3787 | return new WP_Error( 'plugin_not_found', esc_html( sprintf( __( 'Plugin %s is not installed.', 'jetpack' ), $plugin ) ), array( 'status' => 404 ) ); |
||
| 3788 | } |
||
| 3789 | |||
| 3790 | $plugin_data = $plugins[ $plugin ]; |
||
| 3791 | |||
| 3792 | $plugin_data['active'] = in_array( Jetpack_Plugins::get_plugin_status( $plugin ), array( 'active', 'network-active' ), true ); |
||
| 3793 | |||
| 3794 | return rest_ensure_response( array( |
||
| 3795 | 'code' => 'success', |
||
| 3796 | 'message' => esc_html__( 'Plugin found.', 'jetpack' ), |
||
| 3797 | 'data' => $plugin_data |
||
| 3798 | ) ); |
||
| 3799 | } |
||
| 3800 | |||
| 3801 | /** |
||
| 3802 | * Proxies a request to WordPress.com to request that a magic link be sent to the current user |
||
| 3803 | * to log this user in to the mobile app via email. |
||
| 3804 | * |
||
| 3805 | * @param WP_REST_REQUEST $request The request parameters. |
||
| 3806 | * @return bool|WP_Error |
||
| 3807 | */ |
||
| 3808 | public static function send_mobile_magic_link( $request ) { |
||
| 3809 | $xml = new Jetpack_IXR_Client( |
||
| 3810 | array( |
||
| 3811 | 'user_id' => get_current_user_id(), |
||
| 3812 | ) |
||
| 3813 | ); |
||
| 3814 | |||
| 3815 | $xml->query( 'jetpack.sendMobileMagicLink', array() ); |
||
| 3816 | if ( $xml->isError() ) { |
||
| 3817 | return new WP_Error( |
||
| 3818 | 'error_sending_mobile_magic_link', |
||
| 3819 | sprintf( |
||
| 3820 | '%s: %s', |
||
| 3821 | $xml->getErrorCode(), |
||
| 3822 | $xml->getErrorMessage() |
||
| 3823 | ) |
||
| 3824 | ); |
||
| 3825 | } |
||
| 3826 | |||
| 3827 | $response = $xml->getResponse(); |
||
| 3828 | |||
| 3829 | return rest_ensure_response( |
||
| 3830 | array( |
||
| 3831 | 'code' => 'success', |
||
| 3832 | ) |
||
| 3833 | ); |
||
| 3834 | } |
||
| 3835 | |||
| 3836 | /** |
||
| 3837 | * Get the last licensing error message, if any. |
||
| 3838 | * |
||
| 3839 | * @since 9.0.0 |
||
| 3840 | * |
||
| 3841 | * @return string Licensing error message or empty string. |
||
| 3842 | */ |
||
| 3843 | public static function get_licensing_error() { |
||
| 3844 | return Licensing::instance()->last_error(); |
||
| 3845 | } |
||
| 3846 | |||
| 3847 | /** |
||
| 3848 | * Update the last licensing error message. |
||
| 3849 | * |
||
| 3850 | * @since 9.0.0 |
||
| 3851 | * |
||
| 3852 | * @param WP_REST_Request $request The request. |
||
| 3853 | * |
||
| 3854 | * @return bool true. |
||
| 3855 | */ |
||
| 3856 | public static function update_licensing_error( $request ) { |
||
| 3857 | Licensing::instance()->log_error( $request['error'] ); |
||
| 3858 | |||
| 3859 | return true; |
||
| 3860 | } |
||
| 3861 | |||
| 3862 | /** |
||
| 3863 | * Returns the Jetpack CRM data. |
||
| 3864 | * |
||
| 3865 | * @return WP_REST_Response A response object containing the Jetpack CRM data. |
||
| 3866 | */ |
||
| 3867 | public static function get_jetpack_crm_data() { |
||
| 3868 | $jetpack_crm_data = ( new Automattic\Jetpack\Jetpack_CRM_Data() )->get_crm_data(); |
||
| 3869 | return rest_ensure_response( $jetpack_crm_data ); |
||
| 3870 | } |
||
| 3871 | |||
| 3872 | /** |
||
| 3873 | * Activates Jetpack CRM's Jetpack Forms extension. |
||
| 3874 | * |
||
| 3875 | * @param WP_REST_Request $request The request sent to the WP REST API. |
||
| 3876 | * @return WP_REST_Response|WP_Error A response object if the extension activation was successful, or a WP_Error object if it failed. |
||
| 3877 | */ |
||
| 3878 | public static function activate_crm_jetpack_forms_extension( $request ) { |
||
| 3879 | View Code Duplication | if ( ! isset( $request['extension'] ) || 'jetpackforms' !== $request['extension'] ) { |
|
| 3880 | return new WP_Error( 'invalid_param', esc_html__( 'Missing or invalid extension parameter.', 'jetpack' ), array( 'status' => 404 ) ); |
||
| 3881 | } |
||
| 3882 | |||
| 3883 | $result = ( new Automattic\Jetpack\Jetpack_CRM_Data() )->activate_crm_jetpackforms_extension(); |
||
| 3884 | |||
| 3885 | if ( is_wp_error( $result ) ) { |
||
| 3886 | return $result; |
||
| 3887 | } |
||
| 3888 | |||
| 3889 | return rest_ensure_response( array( 'code' => 'success' ) ); |
||
| 3890 | } |
||
| 3891 | |||
| 3892 | /** |
||
| 3893 | * Verifies that the current user has the required permission for accessing the CRM data. |
||
| 3894 | * |
||
| 3895 | * @return true|WP_Error Returns true if the user has the required capability, else a WP_Error object. |
||
| 3896 | */ |
||
| 3897 | public static function jetpack_crm_data_permission_check() { |
||
| 3898 | if ( current_user_can( 'publish_posts' ) ) { |
||
| 3899 | return true; |
||
| 3900 | } |
||
| 3901 | |||
| 3902 | return new WP_Error( |
||
| 3903 | 'invalid_user_permission_jetpack_crm_data', |
||
| 3904 | self::$user_permissions_error_msg, |
||
| 3905 | array( 'status' => rest_authorization_required_code() ) |
||
| 3906 | ); |
||
| 3907 | } |
||
| 3908 | |||
| 3909 | /** |
||
| 3910 | * Verifies that the current user has the required capability for activating Jetpack CRM extensions. |
||
| 3911 | * |
||
| 3912 | * @return true|WP_Error Returns true if the user has the required capability, else a WP_Error object. |
||
| 3913 | */ |
||
| 3914 | public static function activate_crm_extensions_permission_check() { |
||
| 3915 | if ( current_user_can( 'admin_zerobs_manage_options' ) ) { |
||
| 3916 | return true; |
||
| 3917 | } |
||
| 3918 | |||
| 3919 | return new WP_Error( |
||
| 3920 | 'invalid_user_permission_activate_jetpack_crm_ext', |
||
| 3921 | self::$user_permissions_error_msg, |
||
| 3922 | array( 'status' => rest_authorization_required_code() ) |
||
| 3923 | ); |
||
| 3924 | } |
||
| 3925 | |||
| 3926 | } // class end |
||
| 3927 |
This check looks for type mismatches where the missing type is
false. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTimeobject or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalsebefore passing on the value to another function or method that may not be able to handle afalse.