/** * Remove 'validate_callback' item from options available for module. * Fetch current option value and add to array of module options. * Prepare values of module options that need special handling, like those saved in wpcom. * * @since 4.3.0 * * @param string $module Module slug. * @return array */ public static function prepare_options_for_response($module = '') { $options = self::get_module_available_options($module); if (!is_array($options) || empty($options)) { return $options; } foreach ($options as $key => $value) { if (isset($options[$key]['validate_callback'])) { unset($options[$key]['validate_callback']); } $default_value = isset($options[$key]['default']) ? $options[$key]['default'] : ''; $current_value = get_option($key, $default_value); $options[$key]['current_value'] = self::cast_value($current_value, $options[$key]); } // Some modules need special treatment. switch ($module) { case 'monitor': // Status of user notifications $options['monitor_receive_notifications']['current_value'] = self::cast_value(self::get_remote_value('monitor', 'monitor_receive_notifications'), $options['monitor_receive_notifications']); break; case 'post-by-email': // Email address $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']); break; case 'protect': // Protect $options['jetpack_protect_key']['current_value'] = get_site_option('jetpack_protect_key', false); if (!function_exists('jetpack_protect_format_whitelist')) { @(include JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php'); } $options['jetpack_protect_global_whitelist']['current_value'] = jetpack_protect_format_whitelist(); break; case 'related-posts': // It's local, but it must be broken apart since it's saved as an array. $options = self::split_options($options, Jetpack_Options::get_option('relatedposts')); break; case 'verification-tools': // It's local, but it must be broken apart since it's saved as an array. $options = self::split_options($options, get_option('verification_services_codes')); break; case 'sharedaddy': // It's local, but it must be broken apart since it's saved as an array. if (!class_exists('Sharing_Service') && !@(include JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php')) { break; } $sharer = new Sharing_Service(); $options = self::split_options($options, $sharer->get_global_options()); $options['sharing_services']['current_value'] = $sharer->get_blog_services(); break; case 'site-icon': // Return site icon ID and URL to make it more complete. $options['site_icon_id']['current_value'] = Jetpack_Options::get_option('site_icon_id'); if (!function_exists('jetpack_site_icon_url')) { @(include JETPACK__PLUGIN_DIR . 'modules/site-icon/site-icon-functions.php'); } $options['site_icon_url']['current_value'] = jetpack_site_icon_url(); break; case 'after-the-deadline': if (!function_exists('AtD_get_options')) { @(include JETPACK__PLUGIN_DIR . 'modules/after-the-deadline.php'); } $atd_options = array_merge(AtD_get_options(get_current_user_id(), 'AtD_options'), AtD_get_options(get_current_user_id(), 'AtD_check_when')); unset($atd_options['name']); foreach ($atd_options as $key => $value) { $options[$key]['current_value'] = self::cast_value($value, $options[$key]); } $atd_options = AtD_get_options(get_current_user_id(), 'AtD_guess_lang'); $options['guess_lang']['current_value'] = self::cast_value(isset($atd_options['true']), $options['guess_lang']); $options['ignored_phrases']['current_value'] = AtD_get_setting(get_current_user_id(), 'AtD_ignored_phrases'); unset($options['unignore_phrase']); break; case 'minileven': $options['wp_mobile_excerpt']['current_value'] = 1 === intval($options['wp_mobile_excerpt']['current_value']) ? 'enabled' : 'disabled'; $options['wp_mobile_featured_images']['current_value'] = 1 === intval($options['wp_mobile_featured_images']['current_value']) ? 'enabled' : 'disabled'; break; case 'stats': // It's local, but it must be broken apart since it's saved as an array. if (!function_exists('stats_get_options')) { @(include JETPACK__PLUGIN_DIR . 'modules/stats.php'); } $options = self::split_options($options, stats_get_options()); break; } return $options; }
function AtD_display_options_form() { /* grab our user and validate their existence */ $user = wp_get_current_user(); if (!$user || $user->ID == 0) { return; } $options_show_types = AtD_get_options($user->ID, 'AtD_options'); $options_check_when = AtD_get_options($user->ID, 'AtD_check_when'); $options_guess_lang = AtD_get_options($user->ID, 'AtD_guess_lang'); ?> <table class="form-table"> <tr valign="top"> <th scope="row"> <a name="atd"></a> <?php _e('Proofreading', 'jetpack'); ?> </th> <td> <p><?php _e('Automatically proofread content when:', 'jetpack'); ?> <p><?php AtD_print_option('onpublish', __('a post or page is first published', 'jetpack'), $options_check_when); echo '<br />'; AtD_print_option('onupdate', __('a post or page is updated', 'jetpack'), $options_check_when); ?> </p> <p style="font-weight: bold"><?php _e('English Options', 'jetpack'); ?> </font> <p><?php _e('Enable proofreading for the following grammar and style rules when writing posts and pages:', 'jetpack'); ?> </p> <p><?php AtD_print_option('Bias Language', __('Bias Language', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Cliches', __('Clichés', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Complex Expression', __('Complex Phrases', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Diacritical Marks', __('Diacritical Marks', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Double Negative', __('Double Negatives', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Hidden Verbs', __('Hidden Verbs', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Jargon Language', __('Jargon', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Passive voice', __('Passive Voice', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Phrases to Avoid', __('Phrases to Avoid', 'jetpack'), $options_show_types); echo '<br />'; AtD_print_option('Redundant Expression', __('Redundant Phrases', 'jetpack'), $options_show_types); ?> </p> <p><?php printf(__('<a href="%s">Learn more</a> about these options.', 'jetpack'), 'http://support.wordpress.com/proofreading/'); ?> </p> <p style="font-weight: bold"><?php _e('Language', 'jetpack'); ?> </font> <p><?php printf(__('The proofreader supports English, French, German, Portuguese, and Spanish. Your <a href="%s">WPLANG</a> value is the default proofreading language.', 'jetpack'), 'http://codex.wordpress.org/Installing_WordPress_in_Your_Language'); ?> </p> <p><?php AtD_print_option('true', __('Use automatically detected language to proofread posts and pages', 'jetpack'), $options_guess_lang); ?> </p> <?php }
/** * If it's a valid Jetpack module and configuration parameters have been sent, update it. * * @since 4.3.0 * * @param WP_REST_Request $data { * Array of parameters received by request. * * @type string $slug Module slug. * } * * @return bool|WP_Error True if module was updated. Otherwise, a WP_Error instance with the corresponding error. */ public function update_data($data) { // If it's null, we're trying to update many module options from different modules. if (is_null($data['slug'])) { // Value admitted by Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list that will make it return all module options. // It will not be passed. It's just checked in this method to pass that method a string or array. $data['slug'] = 'any'; } else { if (!Jetpack::is_module($data['slug'])) { return new WP_Error('not_found', esc_html__('The requested Jetpack module was not found.', 'jetpack'), array('status' => 404)); } if (!Jetpack::is_module_active($data['slug'])) { return new WP_Error('inactive', esc_html__('The requested Jetpack module is inactive.', 'jetpack'), array('status' => 409)); } } // Get parameters to update the module. $params = $data->get_json_params(); // Exit if no parameters were passed. if (!is_array($params)) { return new WP_Error('missing_options', esc_html__('Missing options.', 'jetpack'), array('status' => 404)); } // Get available module options. $options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list('any' === $data['slug'] ? $params : $data['slug']); // Prepare to toggle module if needed $toggle_module = new Jetpack_Core_API_Module_Toggle_Endpoint(new Jetpack_IXR_Client()); // Options that are invalid or failed to update. $invalid = array_keys(array_diff_key($params, $options)); $not_updated = array(); // Remove invalid options $params = array_intersect_key($params, $options); // Used if response is successful. The message can be overwritten and additional data can be added here. $response = array('code' => 'success', 'message' => esc_html__('The requested Jetpack data updates were successful.', 'jetpack')); // If there are modules to activate, activate them first so they're ready when their options are set. foreach ($params as $option => $value) { if ('modules' === $options[$option]['jp_group']) { // Used if there was an error. Can be overwritten with specific error messages. $error = ''; // Set to true if the module toggling was successful. $updated = false; // Check if user can toggle the module. if ($toggle_module->can_request()) { // Activate or deactivate the module according to the value passed. $toggle_result = $value ? $toggle_module->activate_module($option) : $toggle_module->deactivate_module($option); if (is_wp_error($toggle_result)) { $error = $toggle_result->get_error_message(); } else { $updated = true; } } else { $error = Jetpack_Core_Json_Api_Endpoints::$user_permissions_error_msg; } // The module was not toggled. if (!$updated) { $not_updated[$option] = $error; } // Remove module from list so we don't go through it again. unset($params[$option]); } } foreach ($params as $option => $value) { // Used if there was an error. Can be overwritten with specific error messages. $error = ''; // Set to true if the option update was successful. $updated = false; // Get option attributes, including the group it belongs to. $option_attrs = $options[$option]; // If this is a module option and the related module isn't active for any reason, continue with the next one. if ('settings' !== $option_attrs['jp_group']) { if (!Jetpack::is_module($option_attrs['jp_group'])) { $not_updated[$option] = esc_html__('The requested Jetpack module was not found.', 'jetpack'); continue; } if (!Jetpack::is_module_active($option_attrs['jp_group'])) { $not_updated[$option] = esc_html__('The requested Jetpack module is inactive.', 'jetpack'); continue; } } // Properly cast value based on its type defined in endpoint accepted args. $value = Jetpack_Core_Json_Api_Endpoints::cast_value($value, $option_attrs); switch ($option) { case 'monitor_receive_notifications': $monitor = new Jetpack_Monitor(); // If we got true as response, consider it done. $updated = true === $monitor->update_option_receive_jetpack_monitor_notification($value); break; case 'post_by_email_address': if ('create' == $value) { $result = $this->_process_post_by_email('jetpack.createPostByEmailAddress', esc_html__('Unable to create the Post by Email address. Please try again later.', 'jetpack')); } elseif ('regenerate' == $value) { $result = $this->_process_post_by_email('jetpack.regeneratePostByEmailAddress', esc_html__('Unable to regenerate the Post by Email address. Please try again later.', 'jetpack')); } elseif ('delete' == $value) { $result = $this->_process_post_by_email('jetpack.deletePostByEmailAddress', esc_html__('Unable to delete the Post by Email address. Please try again later.', 'jetpack')); } else { $result = false; } // If we got an email address (create or regenerate) or 1 (delete), consider it done. if (preg_match('/[a-z0-9]+@post.wordpress.com/', $result)) { $response[$option] = $result; $updated = true; } elseif (1 == $result) { $updated = true; } elseif (is_array($result) && isset($result['message'])) { $error = $result['message']; } break; case 'jetpack_protect_key': $protect = Jetpack_Protect_Module::instance(); if ('create' == $value) { $result = $protect->get_protect_key(); } else { $result = false; } // If we got one of Protect keys, consider it done. if (preg_match('/[a-z0-9]{40,}/i', $result)) { $response[$option] = $result; $updated = true; } break; case 'jetpack_protect_global_whitelist': $updated = jetpack_protect_save_whitelist(explode(PHP_EOL, str_replace(array(' ', ','), array('', "\n"), $value))); if (is_wp_error($updated)) { $error = $updated->get_error_message(); } break; case 'show_headline': case 'show_thumbnails': $grouped_options = $grouped_options_current = (array) Jetpack_Options::get_option('relatedposts'); $grouped_options[$option] = $value; // If option value was the same, consider it done. $updated = $grouped_options_current != $grouped_options ? Jetpack_Options::update_option('relatedposts', $grouped_options) : true; break; case 'google': case 'bing': case 'pinterest': case 'yandex': $grouped_options = $grouped_options_current = (array) get_option('verification_services_codes'); $grouped_options[$option] = $value; // If option value was the same, consider it done. $updated = $grouped_options_current != $grouped_options ? update_option('verification_services_codes', $grouped_options) : true; break; case 'sharing_services': if (!class_exists('Sharing_Service') && !@(include JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php')) { break; } $sharer = new Sharing_Service(); // If option value was the same, consider it done. $updated = $value != $sharer->get_blog_services() ? $sharer->set_blog_services($value['visible'], $value['hidden']) : true; break; case 'button_style': case 'sharing_label': case 'show': if (!class_exists('Sharing_Service') && !@(include JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php')) { break; } $sharer = new Sharing_Service(); $grouped_options = $sharer->get_global_options(); $grouped_options[$option] = $value; $updated = $sharer->set_global_options($grouped_options); break; case 'custom': if (!class_exists('Sharing_Service') && !@(include JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php')) { break; } $sharer = new Sharing_Service(); $updated = $sharer->new_service(stripslashes($value['sharing_name']), stripslashes($value['sharing_url']), stripslashes($value['sharing_icon'])); // Return new custom service $response[$option] = $updated; break; case 'sharing_delete_service': if (!class_exists('Sharing_Service') && !@(include JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php')) { break; } $sharer = new Sharing_Service(); $updated = $sharer->delete_service($value); break; case 'jetpack-twitter-cards-site-tag': $value = trim(ltrim(strip_tags($value), '@')); $updated = get_option($option) !== $value ? update_option($option, $value) : true; break; case 'onpublish': case 'onupdate': case 'Bias Language': case 'Cliches': case 'Complex Expression': case 'Diacritical Marks': case 'Double Negative': case 'Hidden Verbs': case 'Jargon Language': case 'Passive voice': case 'Phrases to Avoid': case 'Redundant Expression': case 'guess_lang': if (in_array($option, array('onpublish', 'onupdate'))) { $atd_option = 'AtD_check_when'; } elseif ('guess_lang' == $option) { $atd_option = 'AtD_guess_lang'; $option = 'true'; } else { $atd_option = 'AtD_options'; } $user_id = get_current_user_id(); $grouped_options_current = AtD_get_options($user_id, $atd_option); unset($grouped_options_current['name']); $grouped_options = $grouped_options_current; if ($value && !isset($grouped_options[$option])) { $grouped_options[$option] = $value; } elseif (!$value && isset($grouped_options[$option])) { unset($grouped_options[$option]); } // If option value was the same, consider it done, otherwise try to update it. $options_to_save = implode(',', array_keys($grouped_options)); $updated = $grouped_options != $grouped_options_current ? AtD_update_setting($user_id, $atd_option, $options_to_save) : true; break; case 'ignored_phrases': case 'unignore_phrase': $user_id = get_current_user_id(); $atd_option = 'AtD_ignored_phrases'; $grouped_options = $grouped_options_current = explode(',', AtD_get_setting($user_id, $atd_option)); if ('ignored_phrases' == $option) { $grouped_options = explode(',', $value); } else { $index = array_search($value, $grouped_options); if (false !== $index) { unset($grouped_options[$index]); $grouped_options = array_values($grouped_options); } } $ignored_phrases = implode(',', array_filter(array_map('strip_tags', $grouped_options))); $updated = $grouped_options != $grouped_options_current ? AtD_update_setting($user_id, $atd_option, $ignored_phrases) : true; break; case 'admin_bar': case 'roles': case 'count_roles': case 'blog_id': case 'do_not_track': case 'hide_smile': case 'version': $grouped_options = $grouped_options_current = (array) get_option('stats_options'); $grouped_options[$option] = $value; // If option value was the same, consider it done. $updated = $grouped_options_current != $grouped_options ? update_option('stats_options', $grouped_options) : true; break; case Jetpack_Core_Json_Api_Endpoints::holiday_snow_option_name(): $updated = get_option($option) != $value ? update_option($option, (bool) $value ? 'letitsnow' : '') : true; break; case 'wp_mobile_featured_images': case 'wp_mobile_excerpt': $value = 'enabled' === $value ? '1' : '0'; // break intentionally omitted // break intentionally omitted default: // If option value was the same, consider it done. $updated = get_option($option) != $value ? update_option($option, $value) : true; break; } // The option was not updated. if (!$updated) { $not_updated[$option] = $error; } } if (empty($invalid) && empty($not_updated)) { // The option was updated. return rest_ensure_response($response); } else { $invalid_count = count($invalid); $not_updated_count = count($not_updated); $error = ''; if ($invalid_count > 0) { $error = sprintf(_n('Invalid option: %s.', 'Invalid options: %s.', $invalid_count, 'jetpack'), join(', ', $invalid)); } if ($not_updated_count > 0) { $not_updated_messages = array(); foreach ($not_updated as $not_updated_option => $not_updated_message) { if (!empty($not_updated_message)) { $not_updated_messages[] = sprintf(__('Extra info for %1$s: %2$s', 'jetpack'), $not_updated_option, $not_updated_message); } } if (!empty($error)) { $error .= ' '; } $error .= sprintf(_n('Option not updated: %s.', 'Options not updated: %s.', $not_updated_count, 'jetpack'), join(', ', array_keys($not_updated))); if (!empty($not_updated_messages)) { $error .= ' ' . join('. ', $not_updated_messages); } } // There was an error because some options were updated but others were invalid or failed to update. return new WP_Error('some_updated', esc_html($error), array('status' => 400)); } }