summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYury German <blueknight@gentoo.org>2022-06-15 12:08:35 -0400
committerYury German <blueknight@gentoo.org>2022-06-15 12:08:35 -0400
commit36d7691c33cb64ece817246e47a779ec648d10b0 (patch)
tree08f2fb95303a1d8eeba2c8629a24b35a91fb1cac /plugins/jetpack/_inc/lib
parenttwentyfourteen upg 2.7 to 3.2 and twentysixteen from 2.0 to 2.5 (diff)
downloadblogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.tar.gz
blogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.tar.bz2
blogs-gentoo-36d7691c33cb64ece817246e47a779ec648d10b0.zip
Openid-3.6.1 and jetpack-11.0 upgrade
Signed-off-by: Yury German <blueknight@gentoo.org>
Diffstat (limited to 'plugins/jetpack/_inc/lib')
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class-jetpack-about-page.php12
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class-jetpack-redux-state-helper.php38
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class-jetpack-search-dashboard-page.php137
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php112
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class.jetpack-landing-page.php7
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php108
-rw-r--r--plugins/jetpack/_inc/lib/admin-pages/class.jetpack-settings-page.php114
-rw-r--r--plugins/jetpack/_inc/lib/class-jetpack-recommendations.php290
-rw-r--r--plugins/jetpack/_inc/lib/class.color.php633
-rw-r--r--plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php977
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-automatic-install-skin.php114
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-iframe-embed.php74
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-keyring-service-helper.php165
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-password-checker.php2
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-photon-image-sizes.php20
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-photon-image.php54
-rw-r--r--plugins/jetpack/_inc/lib/class.jetpack-search-performance-logger.php87
-rw-r--r--plugins/jetpack/_inc/lib/class.media.php224
-rw-r--r--plugins/jetpack/_inc/lib/core-api/class-wpcom-rest-field-controller.php221
-rw-r--r--plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php637
-rw-r--r--plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php32
-rw-r--r--plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php18
-rw-r--r--plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php12
-rw-r--r--plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php25
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php31
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-external-media.php2
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php9
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-videopress.php28
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php40
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/hello.php40
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php107
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php20
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php25
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php21
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php36
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/sites-posts-featured-media-url.php39
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php43
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php10
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-fields/class-wpcom-rest-api-v2-attachment-videopress-data.php7
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php123
-rw-r--r--plugins/jetpack/_inc/lib/debugger.php10
-rw-r--r--plugins/jetpack/_inc/lib/debugger/0-load.php21
-rw-r--r--plugins/jetpack/_inc/lib/debugger/class-jetpack-debug-data.php2
-rw-r--r--plugins/jetpack/_inc/lib/debugger/class-jetpack-debugger.php4
-rw-r--r--plugins/jetpack/_inc/lib/functions.wp-notify.php25
-rw-r--r--plugins/jetpack/_inc/lib/icalendar-reader.php608
-rw-r--r--plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-builder.php400
-rw-r--r--plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-parser.php691
-rw-r--r--plugins/jetpack/_inc/lib/markdown/0-load.php6
-rw-r--r--plugins/jetpack/_inc/lib/plans.php2
-rw-r--r--plugins/jetpack/_inc/lib/plugins.php205
-rw-r--r--plugins/jetpack/_inc/lib/tonesque.php195
-rw-r--r--plugins/jetpack/_inc/lib/tracks/tracks-ajax.js62
-rw-r--r--plugins/jetpack/_inc/lib/tracks/tracks-callables.js79
-rw-r--r--plugins/jetpack/_inc/lib/widgets.php179
55 files changed, 3587 insertions, 3596 deletions
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-about-page.php b/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-about-page.php
index 6cd1faf6..1dcf8edd 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-about-page.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-about-page.php
@@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
-require_once 'class.jetpack-admin-page.php';
+require_once __DIR__ . '/class.jetpack-admin-page.php';
/**
* Builds the landing page and its menu.
@@ -53,10 +53,12 @@ class Jetpack_About_Page extends Jetpack_Admin_Page {
/**
* Add page action
*
- * @param string $hook Hook of current page, unused.
+ * @param string $hook Hook of current page.
*/
- public function add_page_actions( $hook ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- $this->a8c_data = $this->fetch_a8c_data();
+ public function add_page_actions( $hook ) {
+ if ( 'admin_page_jetpack_about' === $hook ) {
+ $this->a8c_data = $this->fetch_a8c_data();
+ }
}
/**
@@ -537,7 +539,7 @@ class Jetpack_About_Page extends Jetpack_Admin_Page {
true
);
if ( ! empty( $data ) && is_array( $data ) ) {
- set_transient( 'jetpack_a8c_data', $data, DAY_IN_SECONDS );
+ set_transient( 'jetpack_a8c_data', $data, WEEK_IN_SECONDS );
} else {
// Fallback if everything fails.
$data = array(
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-redux-state-helper.php b/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-redux-state-helper.php
index ebad61af..dff497ea 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-redux-state-helper.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-redux-state-helper.php
@@ -13,6 +13,8 @@ use Automattic\Jetpack\Constants;
use Automattic\Jetpack\Device_Detection\User_Agent_Info;
use Automattic\Jetpack\Identity_Crisis;
use Automattic\Jetpack\Licensing;
+use Automattic\Jetpack\Licensing\Endpoints as Licensing_Endpoints;
+use Automattic\Jetpack\My_Jetpack\Initializer as My_Jetpack_Initializer;
use Automattic\Jetpack\Partner;
use Automattic\Jetpack\Partner_Coupon as Jetpack_Partner_Coupon;
use Automattic\Jetpack\Status;
@@ -23,6 +25,18 @@ use Automattic\Jetpack\Status\Host;
*/
class Jetpack_Redux_State_Helper {
/**
+ * Generate minimal state for React to fetch its own data asynchronously after load
+ * This can improve user experience, reducing time spent on server requests before serving the page
+ * e.g. used by React Disconnect Dialog on plugins page where the full initial state is not needed
+ */
+ public static function get_minimal_state() {
+ return array(
+ 'WP_API_root' => esc_url_raw( rest_url() ),
+ 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ),
+ );
+ }
+
+ /**
* Generate the initial state array to be used by the Redux store.
*/
public static function get_initial_state() {
@@ -45,6 +59,10 @@ class Jetpack_Redux_State_Helper {
$modules[ $slug ]['long_description'] = html_entity_decode( $data['long_description'] );
}
+ // "mock" a block module in order to get it searchable in the settings.
+ $modules['blocks']['module'] = 'blocks';
+ $modules['blocks']['additional_search_queries'] = esc_html_x( 'blocks, block, gutenberg', 'Search terms', 'jetpack' );
+
// Collecting roles that can view site stats.
$stats_roles = array();
$enabled_roles = function_exists( 'stats_get_option' ) ? stats_get_option( 'roles' ) : array( 'administrator' );
@@ -100,10 +118,6 @@ class Jetpack_Redux_State_Helper {
$host = new Host();
- // Get Jetpack benefits for this site.
- $jetpack_benefits_response = Jetpack_Core_API_Site_Endpoint::get_benefits();
- $jetpack_benefits = 200 === $jetpack_benefits_response->status ? json_decode( $jetpack_benefits_response->data['data'] ) : array();
-
return array(
'WP_API_root' => esc_url_raw( rest_url() ),
'WP_API_nonce' => wp_create_nonce( 'wp_rest' ),
@@ -113,7 +127,7 @@ class Jetpack_Redux_State_Helper {
'pluginBaseUrl' => plugins_url( '', JETPACK__PLUGIN_FILE ),
'connectionStatus' => $connection_status,
'connectedPlugins' => Connection_Plugin_Storage::get_all(),
- 'connectUrl' => false == $current_user_data['isConnected'] // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
+ 'connectUrl' => false == $current_user_data['isConnected'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
? Jetpack::init()->build_connect_url( true, false, false )
: '',
'dismissedNotices' => self::get_dismissed_jetpack_notices(),
@@ -145,7 +159,7 @@ class Jetpack_Redux_State_Helper {
'icon' => has_site_icon()
? apply_filters( 'jetpack_photon_url', get_site_icon_url(), array( 'w' => 64 ) )
: '',
- 'siteVisibleToSearchEngines' => '1' == get_option( 'blog_public' ), // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
+ 'siteVisibleToSearchEngines' => '1' == get_option( 'blog_public' ), // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
/**
* Whether promotions are visible or not.
*
@@ -160,6 +174,8 @@ class Jetpack_Redux_State_Helper {
'plan' => Jetpack_Plan::get(),
'showBackups' => Jetpack::show_backups_ui(),
'showRecommendations' => Jetpack_Recommendations::is_enabled(),
+ /** This filter is documented in my-jetpack/src/class-initializer.php */
+ 'showMyJetpack' => My_Jetpack_Initializer::should_initialize(),
'isMultisite' => is_multisite(),
'dateFormat' => get_option( 'date_format' ),
),
@@ -168,9 +184,10 @@ class Jetpack_Redux_State_Helper {
'hasUpdate' => (bool) get_theme_update_available( $current_theme ),
'support' => array(
'infinite-scroll' => current_theme_supports( 'infinite-scroll' ) || in_array( $current_theme->get_stylesheet(), $inf_scr_support_themes, true ),
+ 'widgets' => current_theme_supports( 'widgets' ),
+ 'webfonts' => WP_Theme_JSON_Resolver::theme_has_support() && function_exists( 'wp_register_webfont_provider' ) && function_exists( 'wp_register_webfonts' ),
),
),
- 'jetpackBenefits' => $jetpack_benefits,
'jetpackStateNotices' => array(
'messageCode' => Jetpack::state( 'message' ),
'errorCode' => Jetpack::state( 'error' ),
@@ -189,12 +206,14 @@ class Jetpack_Redux_State_Helper {
'licensing' => array(
'error' => Licensing::instance()->last_error(),
'showLicensingUi' => Licensing::instance()->is_licensing_input_enabled(),
- 'userCounts' => Jetpack_Core_Json_Api_Endpoints::get_user_license_counts(),
+ 'userCounts' => Licensing_Endpoints::get_user_license_counts(),
'activationNoticeDismiss' => Licensing::instance()->get_license_activation_notice_dismiss(),
),
'hasSeenWCConnectionModal' => Jetpack_Options::get_option( 'has_seen_wc_connection_modal', false ),
+ 'newRecommendations' => Jetpack_Recommendations::get_new_conditional_recommendations(),
// Check if WooCommerce plugin is active (based on https://docs.woocommerce.com/document/create-a-plugin/).
'isWooCommerceActive' => in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', Jetpack::get_active_plugins() ), true ),
+ 'useMyJetpackLicensingUI' => My_Jetpack_Initializer::is_licensing_ui_enabled(),
);
}
@@ -342,7 +361,7 @@ class Jetpack_Redux_State_Helper {
$connect_urls = array();
jetpack_require_lib( 'class.jetpack-keyring-service-helper' );
// phpcs:disable
- foreach ( Jetpack_Keyring_Service_Helper::$SERVICES as $service_name => $service_info ) {
+ foreach ( Jetpack_Keyring_Service_Helper::SERVICES as $service_name => $service_info ) {
// phpcs:enable
$connect_urls[ $service_name ] = Jetpack_Keyring_Service_Helper::connect_url( $service_name, $service_info['for'] );
}
@@ -380,7 +399,6 @@ class Jetpack_Redux_State_Helper {
public static function generate_purchase_token() {
return wp_generate_password( 12, false );
}
-
}
/**
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-search-dashboard-page.php b/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-search-dashboard-page.php
deleted file mode 100644
index 5eef2dfe..00000000
--- a/plugins/jetpack/_inc/lib/admin-pages/class-jetpack-search-dashboard-page.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-/**
- * A class that adds a search dashboard to wp-admin.
- *
- * @package automattic/jetpack
- */
-
-use Automattic\Jetpack\Assets;
-use Automattic\Jetpack\Status;
-
-/**
- * Requires files needed.
- */
-require_once JETPACK__PLUGIN_DIR . '_inc/lib/admin-pages/class.jetpack-admin-page.php';
-require_once JETPACK__PLUGIN_DIR . '_inc/lib/admin-pages/class-jetpack-redux-state-helper.php';
-
-/**
- * Responsible for adding a search dashboard to wp-admin.
- *
- * @package Automattic\Jetpack\Search
- */
-class Jetpack_Search_Dashboard_Page extends Jetpack_Admin_Page {
- /**
- * Show the settings page only when Jetpack is connected or in dev mode.
- *
- * @var bool If the page should be shown.
- */
- protected $dont_show_if_not_active = true;
-
- /**
- * Add page specific actions given the page hook.
- *
- * @param {object} $hook The page hook.
- */
- public function add_page_actions( $hook ) {}// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
-
- /**
- * Create a menu item for the page and returns the hook.
- */
- public function get_page_hook() {
-
- if ( ! $this->should_add_sub_menu() ) {
- return;
- }
- return add_submenu_page(
- 'jetpack',
- __( 'Search Settings', 'jetpack' ),
- _x( 'Search', 'product name shown in menu', 'jetpack' ),
- 'manage_options',
- 'jetpack-search',
- array( $this, 'render' ),
- $this->get_link_offset()
- );
- }
-
- /**
- * Enqueue and localize page specific scripts
- */
- public function page_admin_scripts() {
- $this->load_admin_scripts();
- }
-
- /**
- * Override render funtion
- */
- public function render() {
- $this->page_render();
- }
-
- /**
- * Render Search setting elements
- */
- public function page_render() {
- ?>
- <div id="jp-search-dashboard" class="jp-search-dashboard">
- <div class="hide-if-js"><?php esc_html_e( 'Your Search dashboard requires JavaScript to function properly.', 'jetpack' ); ?></div>
- </div>
- <?php
- }
-
- /**
- * Test whether we should show Search menu.
- *
- * @return {boolean} Show search sub menu or not.
- */
- protected function should_add_sub_menu() {
- return method_exists( 'Jetpack_Plan', 'supports' ) && Jetpack_Plan::supports( 'search' );
- }
-
- /**
- * Place the Jetpack Search menu item at the bottom of the Jetpack submenu.
- *
- * @return int Menu offset.
- */
- private function get_link_offset() {
- global $submenu;
- return count( $submenu['jetpack'] );
- }
-
- /**
- * Enqueue admin styles.
- */
- public function load_admin_styles() {
- $this->load_admin_scripts();
- }
-
- /**
- * Enqueue admin scripts.
- */
- public function load_admin_scripts() {
- \Jetpack_Admin_Page::load_wrapper_styles();
-
- if ( ! ( new Status() )->is_offline_mode() && Jetpack::is_connection_ready() ) {
- // Required for Analytics.
- Automattic\Jetpack\Tracking::register_tracks_functions_scripts( true );
- }
-
- Assets::register_script(
- 'jp-search-dashboard',
- '_inc/build/search-dashboard.js',
- JETPACK__PLUGIN_FILE,
- array(
- 'in_footer' => true,
- 'textdomain' => 'jetpack',
- )
- );
- Assets::enqueue_script( 'jp-search-dashboard' );
-
- // Add objects to be passed to the initial state of the app.
- // Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280.
- wp_add_inline_script(
- 'jp-search-dashboard',
- 'var Initial_State=JSON.parse(decodeURIComponent("' . rawurlencode( wp_json_encode( \Jetpack_Redux_State_Helper::get_initial_state() ) ) . '"));',
- 'before'
- );
- }
-}
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php
index 86887667..d7b5675c 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php
@@ -1,36 +1,55 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Main class file for Jetpack Admin pages.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Identity_Crisis;
use Automattic\Jetpack\Redirect;
use Automattic\Jetpack\Status;
-// Shared logic between Jetpack admin pages
+/**
+ * Shared logic between Jetpack admin pages.
+ */
abstract class Jetpack_Admin_Page {
- // Add page specific actions given the page hook
- abstract function add_page_actions( $hook );
+ /**
+ * Add page specific actions given the page hook.
+ *
+ * @param string $hook Hook of current page.
+ */
+ abstract public function add_page_actions( $hook );
- // Create a menu item for the page and returns the hook
- abstract function get_page_hook();
+ /**
+ * Create a menu item for the page and returns the hook.
+ *
+ * @return string|false Return value from WordPress's `add_menu_page()` or `add_submenu_page()`.
+ */
+ abstract public function get_page_hook();
- // Enqueue and localize page specific scripts
- abstract function page_admin_scripts();
+ /**
+ * Enqueue and localize page specific scripts.
+ */
+ abstract public function page_admin_scripts();
- // Render page specific HTML
- abstract function page_render();
+ /**
+ * Render page specific HTML
+ */
+ abstract public function page_render();
/**
* Should we block the page rendering because the site is in IDC?
*
* @var bool
*/
- static $block_page_rendering_for_idc;
+ public static $block_page_rendering_for_idc;
/**
* Function called after admin_styles to load any additional needed styles.
*
* @since 4.3.0
*/
- function additional_styles() {}
+ public function additional_styles() {}
/**
* The constructor.
@@ -52,7 +71,10 @@ abstract class Jetpack_Admin_Page {
);
}
- function add_actions() {
+ /**
+ * Add common page actions and attach page-specific actions.
+ */
+ public function add_actions() {
$is_offline_mode = ( new Status() )->is_offline_mode();
// If user is not an admin and site is in Offline Mode or not connected yet then don't do anything.
@@ -70,7 +92,7 @@ abstract class Jetpack_Admin_Page {
return;
}
- // Initialize menu item for the page in the admin
+ // Initialize menu item for the page in the admin.
$hook = $this->get_page_hook();
// Attach hooks common to all Jetpack admin pages based on the created hook.
@@ -116,38 +138,51 @@ abstract class Jetpack_Admin_Page {
}
- // Render the page with a common top and bottom part, and page specific content
- function render() {
+ /**
+ * Render the page with a common top and bottom part, and page specific content.
+ */
+ public function render() {
// We're in an IDC: we need a decision made before we show the UI again.
if ( self::$block_page_rendering_for_idc ) {
return;
}
- // Check if we are looking at the main dashboard
- if ( isset( $_GET['page'] ) && 'jetpack' === $_GET['page'] ) {
+ // Check if we are looking at the main dashboard.
+ if ( isset( $_GET['page'] ) && 'jetpack' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- View logic.
$this->page_render();
return;
}
self::wrap_ui( array( $this, 'page_render' ) );
}
- function admin_help() {
+ /**
+ * Load Help tab.
+ *
+ * @todo This may no longer be used.
+ */
+ public function admin_help() {
$this->jetpack->admin_help();
}
- function admin_page_load() {
- // This is big. For the moment, just call the existing one.
+ /**
+ * Call the existing admin page events.
+ */
+ public function admin_page_load() {
$this->jetpack->admin_page_load();
}
- // Add page specific scripts and jetpack stats for all menu pages
- function admin_scripts() {
- $this->page_admin_scripts(); // Delegate to inheriting class
+ /**
+ * Add page specific scripts and jetpack stats for all menu pages.
+ */
+ public function admin_scripts() {
+ $this->page_admin_scripts(); // Delegate to inheriting class.
add_action( 'admin_footer', array( $this->jetpack, 'do_stats' ) );
}
- // Enqueue the Jetpack admin stylesheet
- function admin_styles() {
+ /**
+ * Enqueue the Jetpack admin stylesheet.
+ */
+ public function admin_styles() {
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
wp_enqueue_style( 'jetpack-admin', plugins_url( "css/jetpack-admin{$min}.css", JETPACK__PLUGIN_FILE ), array( 'genericons' ), JETPACK__VERSION . '-20121016' );
@@ -162,7 +197,7 @@ abstract class Jetpack_Admin_Page {
*
* @return bool
*/
- function is_rest_api_enabled() {
+ public function is_rest_api_enabled() {
return /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */
apply_filters( 'rest_enabled', true ) &&
/** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */
@@ -174,11 +209,11 @@ abstract class Jetpack_Admin_Page {
*
* @since 4.4.0
*
- * @param $page
+ * @param WP_Screen $page Current WP_Screen object.
*
* @return array
*/
- function check_plan_deactivate_modules( $page ) {
+ public function check_plan_deactivate_modules( $page ) {
if (
( new Status() )->is_offline_mode()
|| ! in_array(
@@ -189,7 +224,8 @@ abstract class Jetpack_Admin_Page {
'jetpack_page_vaultpress',
'jetpack_page_stats',
'jetpack_page_akismet-key-config',
- )
+ ),
+ true
)
) {
return false;
@@ -231,7 +267,10 @@ abstract class Jetpack_Admin_Page {
);
}
- static function load_wrapper_styles() {
+ /**
+ * Enqueue inline wrapper styles for the main container.
+ */
+ public static function load_wrapper_styles() {
$rtl = is_rtl() ? '.rtl' : '';
wp_enqueue_style( 'dops-css', plugins_url( "_inc/build/admin{$rtl}.css", JETPACK__PLUGIN_FILE ), array(), JETPACK__VERSION );
wp_enqueue_style( 'components-css', plugins_url( "_inc/build/style.min{$rtl}.css", JETPACK__PLUGIN_FILE ), array( 'wp-components' ), JETPACK__VERSION );
@@ -278,6 +317,14 @@ abstract class Jetpack_Admin_Page {
wp_add_inline_style( 'dops-css', $custom_css );
}
+ /**
+ * Build header, content, and footer for admin page.
+ *
+ * @param string $callback Callback to produce the content of the page. The callback is responsible for any needed escaping.
+ * @param array $args Options for the wrapping. Also passed to the `jetpack_admin_pages_wrap_ui_after_callback` action.
+ * - is-wide: (bool) Set the "is-wide" class on the wrapper div, which increases the max width. Default false.
+ * - show-nav: (bool) Whether to show the navigation bar at the top of the page. Default true.
+ */
public static function wrap_ui( $callback, $args = array() ) {
$defaults = array(
'is-wide' => false,
@@ -356,7 +403,7 @@ abstract class Jetpack_Admin_Page {
call_user_func( $callback );
$callback_ui = ob_get_contents();
ob_end_clean();
- echo $callback_ui;
+ echo $callback_ui;// phpcs:ignore WordPress.Security.EscapeOutput -- Callback is responsible for any needed escaping.
?>
<!-- END OF CALLBACK -->
@@ -417,6 +464,5 @@ abstract class Jetpack_Admin_Page {
</div>
</div>
<?php
- return;
}
}
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-landing-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-landing-page.php
index 5c06c284..2c61bd5e 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-landing-page.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-landing-page.php
@@ -1,3 +1,6 @@
<?php
-// This is intentionally left empty as a stub because some sites were caching the require()
-// @see https://github.com/Automattic/jetpack/issues/5091
+/** This is intentionally left empty as a stub because some sites were caching the require()
+ *
+ * @see https://github.com/Automattic/jetpack/issues/5091
+ * @package automattic/jetpack
+ */
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php
index 1c76ea28..d550b508 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php
@@ -1,43 +1,64 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Status;
-include_once( 'class.jetpack-admin-page.php' );
+require_once __DIR__ . '/class.jetpack-admin-page.php';
require_once __DIR__ . '/class-jetpack-redux-state-helper.php';
-// Builds the landing page and its menu
+/**
+ * Builds the landing page and its menu.
+ */
class Jetpack_React_Page extends Jetpack_Admin_Page {
-
+ /**
+ * Show the landing page only when Jetpack is connected.
+ *
+ * @var bool
+ */
protected $dont_show_if_not_active = false;
+ /**
+ * Used for fallback when REST API is disabled.
+ *
+ * @var bool
+ */
protected $is_redirecting = false;
- function get_page_hook() {
- // Add the main admin Jetpack menu
+ /**
+ * Add the main admin Jetpack menu.
+ *
+ * @return string|false Return value from WordPress's `add_menu_page()`.
+ */
+ public function get_page_hook() {
return add_menu_page( 'Jetpack', 'Jetpack', 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), 'div', 3 );
}
- function add_page_actions( $hook ) {
- /** This action is documented in class.jetpack.php */
+ /**
+ * Add page action.
+ *
+ * @param string $hook Hook of current page.
+ * @return void
+ */
+ public function add_page_actions( $hook ) {
+ /** This action is documented in class.jetpack-admin.php */
do_action( 'jetpack_admin_menu', $hook );
- if ( ! isset( $_GET['page'] ) || 'jetpack' !== $_GET['page'] ) {
- return; // No need to handle the fallback redirection if we are not on the Jetpack page
+ if ( ! isset( $_GET['page'] ) || 'jetpack' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ return; // No need to handle the fallback redirection if we are not on the Jetpack page.
}
- // Adding a redirect meta tag if the REST API is disabled
+ // Adding a redirect meta tag if the REST API is disabled.
if ( ! $this->is_rest_api_enabled() ) {
$this->is_redirecting = true;
add_action( 'admin_head', array( $this, 'add_fallback_head_meta' ) );
}
- // Adding a redirect meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled
+ // Adding a redirect meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
add_action( 'admin_head', array( $this, 'add_noscript_head_meta' ) );
// If this is the first time the user is viewing the admin, don't show JITMs.
// This filter is added just in time because this function is called on admin_menu
- // and JITMs are initialized on admin_init
+ // and JITMs are initialized on admin_init.
if ( Jetpack::is_connection_ready() && ! Jetpack_Options::get_option( 'first_admin_view', false ) ) {
Jetpack_Options::update_option( 'first_admin_view', true );
add_filter( 'jetpack_just_in_time_msgs', '__return_false' );
@@ -51,7 +72,7 @@ class Jetpack_React_Page extends Jetpack_Admin_Page {
*
* @since 4.3.0
*/
- function jetpack_add_dashboard_sub_nav_item() {
+ public function jetpack_add_dashboard_sub_nav_item() {
if ( ( new Status() )->is_offline_mode() || Jetpack::is_connection_ready() ) {
add_submenu_page( 'jetpack', __( 'Dashboard', 'jetpack' ), __( 'Dashboard', 'jetpack' ), 'jetpack_admin_page', 'jetpack#/dashboard', '__return_null' );
remove_submenu_page( 'jetpack', 'jetpack' );
@@ -130,17 +151,27 @@ class Jetpack_React_Page extends Jetpack_Admin_Page {
* @since 4.3.0
* @since 9.7.0 If Connection does not have an owner, restrict it to admins
*/
- function jetpack_add_settings_sub_nav_item() {
+ public function jetpack_add_settings_sub_nav_item() {
if ( $this->can_access_settings() ) {
add_submenu_page( 'jetpack', __( 'Settings', 'jetpack' ), __( 'Settings', 'jetpack' ), 'jetpack_admin_page', 'jetpack#/settings', '__return_null' );
}
}
- function add_fallback_head_meta() {
+ /**
+ * Fallback redirect meta tag if the REST API is disabled.
+ *
+ * @return void
+ */
+ public function add_fallback_head_meta() {
echo '<meta http-equiv="refresh" content="0; url=?page=jetpack_modules">';
}
- function add_noscript_head_meta() {
+ /**
+ * Fallback meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
+ *
+ * @return void
+ */
+ public function add_noscript_head_meta() {
echo '<noscript>';
$this->add_fallback_head_meta();
echo '</noscript>';
@@ -153,33 +184,36 @@ class Jetpack_React_Page extends Jetpack_Admin_Page {
* @param array $menu_order Menu order.
* @return array
*/
- function jetpack_menu_order( $menu_order ) {
+ public function jetpack_menu_order( $menu_order ) {
_deprecated_function( __METHOD__, 'jetpack-9.2' );
return $menu_order;
}
- function page_render() {
- /** This action is already documented in views/admin/admin-page.php */
+ /**
+ * Add action to render page specific HTML.
+ *
+ * @return void
+ */
+ public function page_render() {
+ /** This action is already documented in class.jetpack-admin-page.php */
do_action( 'jetpack_notices' );
- // Try fetching by patch
- $static_html = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static.html' );
+ // Fetch static.html.
+ $static_html = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static.html' ); //phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, Not fetching a remote file.
if ( false === $static_html ) {
- // If we still have nothing, display an error
+ // If we still have nothing, display an error.
echo '<p>';
esc_html_e( 'Error fetching static.html. Try running: ', 'jetpack' );
- echo '<code>pnpm run distclean && pnpx jetpack build plugins/jetpack</code>';
+ echo '<code>pnpm run distclean && pnpm jetpack build plugins/jetpack</code>';
echo '</p>';
} else {
-
- // We got the static.html so let's display it
- echo $static_html;
+ // We got the static.html so let's display it.
+ echo $static_html; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
-
/**
* Allow robust deep links to React.
*
@@ -202,20 +236,26 @@ class Jetpack_React_Page extends Jetpack_Admin_Page {
);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
- $target = sanitize_text_field( (string) $_GET['jp-react-redirect'] );
+ $target = sanitize_text_field( wp_unslash( $_GET['jp-react-redirect'] ) );
if ( isset( $allowed_paths[ $target ] ) ) {
wp_safe_redirect( $allowed_paths[ $target ] );
exit;
}
}
- function additional_styles() {
+ /**
+ * Load styles for static page.
+ */
+ public function additional_styles() {
Jetpack_Admin_Page::load_wrapper_styles();
}
- function page_admin_scripts() {
+ /**
+ * Load admin page scripts.
+ */
+ public function page_admin_scripts() {
if ( $this->is_redirecting ) {
- return; // No need for scripts on a fallback page
+ return; // No need for scripts on a fallback page.
}
$status = new Status();
@@ -223,16 +263,18 @@ class Jetpack_React_Page extends Jetpack_Admin_Page {
$site_suffix = $status->get_site_suffix();
$script_deps_path = JETPACK__PLUGIN_DIR . '_inc/build/admin.asset.php';
$script_dependencies = array( 'wp-polyfill' );
+ $version = JETPACK__VERSION;
if ( file_exists( $script_deps_path ) ) {
$asset_manifest = include $script_deps_path;
$script_dependencies = $asset_manifest['dependencies'];
+ $version = $asset_manifest['version'];
}
wp_enqueue_script(
'react-plugin',
plugins_url( '_inc/build/admin.js', JETPACK__PLUGIN_FILE ),
$script_dependencies,
- JETPACK__VERSION,
+ $version,
true
);
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-settings-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-settings-page.php
index 551b9f71..b1f0dab6 100644
--- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-settings-page.php
+++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-settings-page.php
@@ -1,21 +1,35 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
-use Automattic\Jetpack\Tracking;
use Automattic\Jetpack\Assets;
+use Automattic\Jetpack\Tracking;
-include_once( 'class.jetpack-admin-page.php' );
-include_once( JETPACK__PLUGIN_DIR . 'class.jetpack-modules-list-table.php' );
+require_once __DIR__ . '/class.jetpack-admin-page.php';
+require_once JETPACK__PLUGIN_DIR . 'class.jetpack-modules-list-table.php';
-// Builds the settings page and its menu
+/**
+ * Builds the settings page and its menu
+ */
class Jetpack_Settings_Page extends Jetpack_Admin_Page {
- // Show the settings page only when Jetpack is connected or in dev mode
+ /**
+ * Show the settings page only when Jetpack is connected or in dev mode.
+ *
+ * @var boolean
+ */
protected $dont_show_if_not_active = true;
- function add_page_actions( $hook ) {}
+ /**
+ * Add page action.
+ *
+ * @param string $hook Hook of current page.
+ * @return void
+ */
+ public function add_page_actions( $hook ) {} //phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- // Adds the Settings sub menu
- function get_page_hook() {
+ /**
+ * Adds the Settings sub menu.
+ */
+ public function get_page_hook() {
return add_submenu_page(
null,
__( 'Jetpack Settings', 'jetpack' ),
@@ -26,14 +40,16 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
);
}
- // Renders the module list table where you can use bulk action or row
- // actions to activate/deactivate and configure modules
- function page_render() {
- $list_table = new Jetpack_Modules_List_Table;
+ /**
+ * Renders the module list table where you can use bulk action or row
+ * actions to activate/deactivate and configure modules
+ */
+ public function page_render() {
+ $list_table = new Jetpack_Modules_List_Table();
- // We have static.html so let's continue trying to fetch the others
- $noscript_notice = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static-noscript-notice.html' );
- $rest_api_notice = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static-version-notice.html' );
+ // We have static.html so let's continue trying to fetch the others.
+ $noscript_notice = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static-noscript-notice.html' ); //phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, Not fetching a remote file.
+ $rest_api_notice = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static-version-notice.html' ); //phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, Not fetching a remote file.
$noscript_notice = str_replace(
'#HEADER_TEXT#',
@@ -58,9 +74,9 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
);
if ( ! $this->is_rest_api_enabled() ) {
- echo $rest_api_notice;
+ echo $rest_api_notice; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
- echo $noscript_notice;
+ echo $noscript_notice; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<div class="page-content configure">
@@ -92,15 +108,52 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
<?php $list_table->search_box( __( 'Search', 'jetpack' ), 'srch-term' ); ?>
<p><?php esc_html_e( 'View:', 'jetpack' ); ?></p>
<div class="button-group filter-active">
- <button type="button" class="button <?php if ( empty( $_GET['activated'] ) ) echo 'active'; ?>"><?php esc_html_e( 'All', 'jetpack' ); ?></button>
- <button type="button" class="button <?php if ( ! empty( $_GET['activated'] ) && 'true' == $_GET['activated'] ) echo 'active'; ?>" data-filter-by="activated" data-filter-value="true"><?php esc_html_e( 'Active', 'jetpack' ); ?></button>
- <button type="button" class="button <?php if ( ! empty( $_GET['activated'] ) && 'false' == $_GET['activated'] ) echo 'active'; ?>" data-filter-by="activated" data-filter-value="false"><?php esc_html_e( 'Inactive', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( empty( $_GET['activated'] ) ) {
+ echo 'active';
+ }
+ ?>
+ ">
+ <?php esc_html_e( 'All', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( ! empty( $_GET['activated'] ) && 'true' === $_GET['activated'] ) {
+ echo 'active';
+ }
+ ?>
+ " data-filter-by="activated" data-filter-value="true"><?php esc_html_e( 'Active', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( ! empty( $_GET['activated'] ) && 'false' === $_GET['activated'] ) {
+ echo 'active';
+ }
+ ?>
+ " data-filter-by="activated" data-filter-value="false"><?php esc_html_e( 'Inactive', 'jetpack' ); ?></button>
</div>
<p><?php esc_html_e( 'Sort by:', 'jetpack' ); ?></p>
<div class="button-group sort">
- <button type="button" class="button <?php if ( empty( $_GET['sort_by'] ) ) echo 'active'; ?>" data-sort-by="name"><?php esc_html_e( 'Alphabetical', 'jetpack' ); ?></button>
- <button type="button" class="button <?php if ( ! empty( $_GET['sort_by'] ) && 'introduced' == $_GET['sort_by'] ) echo 'active'; ?>" data-sort-by="introduced" data-sort-order="reverse"><?php esc_html_e( 'Newest', 'jetpack' ); ?></button>
- <button type="button" class="button <?php if ( ! empty( $_GET['sort_by'] ) && 'sort' == $_GET['sort_by'] ) echo 'active'; ?>" data-sort-by="sort"><?php esc_html_e( 'Popular', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( empty( $_GET['sort_by'] ) ) {
+ echo 'active';
+ }
+ ?>
+ " data-sort-by="name"><?php esc_html_e( 'Alphabetical', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( ! empty( $_GET['sort_by'] ) && 'introduced' === $_GET['sort_by'] ) {
+ echo 'active';
+ }
+ ?>
+ " data-sort-by="introduced" data-sort-order="reverse"><?php esc_html_e( 'Newest', 'jetpack' ); ?></button>
+ <button type="button" class="button
+ <?php // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is view logic.
+ if ( ! empty( $_GET['sort_by'] ) && 'sort' === $_GET['sort_by'] ) {
+ echo 'active';
+ }
+ ?>
+ " data-sort-by="sort"><?php esc_html_e( 'Popular', 'jetpack' ); ?></button>
</div>
<p><?php esc_html_e( 'Show:', 'jetpack' ); ?></p>
<?php $list_table->views(); ?>
@@ -109,7 +162,7 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
</div>
<div class="manage-left" style="width: 100%;">
<form class="jetpack-modules-list-table-form" onsubmit="return false;">
- <table class="<?php echo implode( ' ', $list_table->get_table_classes() ); ?>">
+ <table class="<?php echo esc_attr( implode( ' ', $list_table->get_table_classes() ) ); ?>">
<tbody id="the-list">
<?php $list_table->display_rows_or_placeholder(); ?>
</tbody>
@@ -130,17 +183,20 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
*
* @since 4.3.0
*/
- function additional_styles() {
+ public function additional_styles() {
Jetpack_Admin_Page::load_wrapper_styles();
}
- // Javascript logic specific to the list table
- function page_admin_scripts() {
+ /**
+ * Javascript logic specific to the list table
+ */
+ public function page_admin_scripts() {
wp_enqueue_script(
'jetpack-admin-js',
Assets::get_file_url_for_environment( '_inc/build/jetpack-admin.min.js', '_inc/jetpack-admin.js' ),
array( 'jquery' ),
- JETPACK__VERSION
+ JETPACK__VERSION,
+ true
);
}
}
diff --git a/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php b/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php
index ffbbddf3..77dd3a32 100644
--- a/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php
+++ b/plugins/jetpack/_inc/lib/class-jetpack-recommendations.php
@@ -7,8 +7,10 @@
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
+use Automattic\Jetpack\Plugins_Installer;
use Automattic\Jetpack\Status;
use Automattic\Jetpack\Status\Host;
+use Automattic\Jetpack\Tracking;
/**
* Contains utilities related to the Jetpack Recommendations.
@@ -20,6 +22,22 @@ use Automattic\Jetpack\Status\Host;
* Jetpack_Recommendations class
*/
class Jetpack_Recommendations {
+
+ const PUBLICIZE_RECOMMENDATION = 'publicize';
+ const SECURITY_PLAN_RECOMMENDATION = 'security-plan';
+ const ANTI_SPAM_RECOMMENDATION = 'anti-spam';
+ const VIDEOPRESS_RECOMMENDATION = 'videopress';
+
+ const CONDITIONAL_RECOMMENDATIONS_OPTION = 'recommendations_conditional';
+ const CONDITIONAL_RECOMMENDATIONS = array(
+ self::PUBLICIZE_RECOMMENDATION,
+ self::SECURITY_PLAN_RECOMMENDATION,
+ self::ANTI_SPAM_RECOMMENDATION,
+ self::VIDEOPRESS_RECOMMENDATION,
+ );
+
+ const VIDEOPRESS_TIMED_ACTION = 'jetpack_recommend_videopress';
+
/**
* Returns a boolean indicating if the Jetpack Recommendations are enabled.
*
@@ -98,6 +116,278 @@ class Jetpack_Recommendations {
}
/**
+ * Set up actions to monitor for things that trigger a recommendation.
+ *
+ * @return false|void
+ */
+ public static function init_conditional_recommendation_actions() {
+ // Check to make sure that recommendations are enabled.
+ if ( ! self::is_enabled() ) {
+ return false;
+ }
+
+ // Monitor for the publishing of a new post.
+ add_action( 'transition_post_status', array( get_called_class(), 'post_transition' ), 10, 3 );
+ add_action( 'jetpack_activate_module', array( get_called_class(), 'jetpack_module_activated' ), 10, 2 );
+
+ // Monitor for activating a new plugin.
+ add_action( 'activated_plugin', array( get_called_class(), 'plugin_activated' ), 10 );
+
+ // Monitor for the addition of a new comment.
+ add_action( 'comment_post', array( get_called_class(), 'comment_added' ), 10, 3 );
+
+ // Monitor for Jetpack connection success.
+ add_action( 'jetpack_authorize_ending_authorized', array( get_called_class(), 'jetpack_connected' ) );
+ add_action( self::VIDEOPRESS_TIMED_ACTION, array( get_called_class(), 'recommend_videopress' ) );
+ }
+
+ /**
+ * Check when Jetpack modules are activated if some recommendations should be skipped.
+ *
+ * @param string $module Name of the module activated.
+ * @param bool $success Whether the module activation was successful.
+ */
+ public static function jetpack_module_activated( $module, $success ) {
+ if ( 'publicize' === $module && $success ) {
+ self::disable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
+ } elseif ( 'videopress' === $module && $success ) {
+ // If VideoPress is enabled and a recommendation for it is scheduled, cancel that recommendation.
+ $recommendation_timestamp = wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION );
+ if ( false !== $recommendation_timestamp ) {
+ wp_unschedule_event( $recommendation_timestamp, self::VIDEOPRESS_TIMED_ACTION );
+ }
+ }
+ }
+
+ /**
+ * Hook for transition_post_status that checks for the publishing of a new post.
+ * Used to enable the publicize recommendation.
+ *
+ * @param string $new_status new status of post.
+ * @param string $old_status old status of post.
+ * @param WP_Post $post the post object being updated.
+ */
+ public static function post_transition( $new_status, $old_status, $post ) {
+ // Check for condition when post has been published.
+ if ( 'post' === $post->post_type && 'publish' === $new_status && 'publish' !== $old_status && ! Jetpack::is_module_active( 'publicize' ) ) {
+ // Set the publicize recommendation to have met criteria to be shown.
+ self::enable_conditional_recommendation( self::PUBLICIZE_RECOMMENDATION );
+ }
+ }
+
+ /**
+ * Runs when a plugin gets activated
+ *
+ * @param string $plugin Path to the plugins file relative to the plugins directory.
+ */
+ public static function plugin_activated( $plugin ) {
+ // If the plugin is in this list, don't enable the recommendation.
+ $plugin_whitelist = array(
+ 'jetpack.php',
+ 'akismet.php',
+ 'creative-mail.php',
+ 'jetpack-backup.php',
+ 'jetpack-boost.php',
+ 'crowdsignal.php',
+ 'vaultpress.php',
+ 'woocommerce.php',
+ );
+
+ $path_parts = explode( '/', $plugin );
+ $plugin_file = $path_parts ? array_pop( $path_parts ) : $plugin;
+
+ if ( ! in_array( $plugin_file, $plugin_whitelist, true ) ) {
+ $products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
+ $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $products ) ) > 0;
+ $has_anti_spam = is_plugin_active( 'akismet/akismet.php' ) || Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product;
+
+ // Check the backup state.
+ $rewind_state = get_transient( 'jetpack_rewind_state' );
+ $has_backup = $rewind_state && in_array( $rewind_state->state, array( 'awaiting_credentials', 'provisioning', 'active' ), true );
+
+ // Check for a plan or product that enables scan.
+ $plan_supports_scan = Jetpack_Plan::supports( 'scan' );
+ $has_scan_product = count( array_intersect( array( 'jetpack_scan', 'jetpack_scan_monthly' ), $products ) ) > 0;
+ $has_scan = $plan_supports_scan || $has_scan_product;
+
+ if ( ! $has_scan || ! $has_backup || ! $has_anti_spam ) {
+ self::enable_conditional_recommendation( self::SECURITY_PLAN_RECOMMENDATION );
+ }
+ }
+ }
+
+ /**
+ * Runs when a new comment is added.
+ *
+ * @param integer $comment_id The ID of the comment that was added.
+ * @param bool $comment_approved Whether or not the comment is approved.
+ * @param array $commentdata Comment data.
+ */
+ public static function comment_added( $comment_id, $comment_approved, $commentdata ) {
+ if ( self::is_conditional_recommendation_enabled( self::ANTI_SPAM_RECOMMENDATION ) ) {
+ return;
+ }
+
+ if ( Plugins_Installer::is_plugin_active( 'akismet/akismet.php' ) ) {
+ return;
+ }
+
+ // The site has anti-spam features already.
+ $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
+ $has_anti_spam_product = count( array_intersect( array( 'jetpack_anti_spam', 'jetpack_anti_spam_monthly' ), $site_products ) ) > 0;
+
+ if ( Jetpack_Plan::supports( 'antispam' ) || $has_anti_spam_product ) {
+ return;
+ }
+
+ if ( isset( $commentdata['comment_post_ID'] ) ) {
+ $post_id = $commentdata['comment_post_ID'];
+ } else {
+ $comment = get_comment( $comment_id );
+ $post_id = $comment->comment_post_ID;
+ }
+ $comment_count = get_comments_number( $post_id );
+
+ if ( intval( $comment_count ) >= 5 ) {
+ self::enable_conditional_recommendation( self::ANTI_SPAM_RECOMMENDATION );
+ }
+ }
+
+ /**
+ * Runs after a successful connection is made.
+ */
+ public static function jetpack_connected() {
+ // Schedule a recommendation for VideoPress in 2 weeks.
+ if ( false === wp_next_scheduled( self::VIDEOPRESS_TIMED_ACTION ) ) {
+ $date = new DateTime();
+ $date->add( new DateInterval( 'P14D' ) );
+ wp_schedule_single_event( $date->getTimestamp(), self::VIDEOPRESS_TIMED_ACTION );
+ }
+ }
+
+ /**
+ * Enable a recommendation for VideoPress.
+ */
+ public static function recommend_videopress() {
+ // Check to see if the VideoPress recommendation is already enabled.
+ if ( self::is_conditional_recommendation_enabled( self::VIDEOPRESS_RECOMMENDATION ) ) {
+ return;
+ }
+
+ $site_plan = Jetpack_Plan::get();
+ $site_products = array_column( Jetpack_Plan::get_products(), 'product_slug' );
+
+ if ( self::should_recommend_videopress( $site_plan, $site_products ) ) {
+ self::enable_conditional_recommendation( self::VIDEOPRESS_RECOMMENDATION );
+ }
+ }
+
+ /**
+ * Should we provide a recommendation for videopress?
+ * This method exists to facilitate unit testing
+ *
+ * @param array $site_plan A representation of the site's plan.
+ * @param array $site_products An array of product slugs.
+ * @return boolean
+ */
+ public static function should_recommend_videopress( $site_plan, $site_products ) {
+ // Does the site have the VideoPress module enabled?
+ if ( Jetpack::is_module_active( 'videopress' ) ) {
+ return false;
+ }
+
+ // Does the site plan have upgraded videopress features?
+ // For now, this just checks to see if the site has a free plan.
+ // Jetpack_Plan::supports('videopress') returns true for all plans, since there is a free tier.
+ $is_free_plan = 'free' === $site_plan['class'];
+ if ( ! $is_free_plan ) {
+ return false;
+ }
+
+ // Does this site already have a VideoPress product?
+ $has_videopress_product = count( array_intersect( array( 'jetpack_videopress', 'jetpack_videopress_monthly' ), $site_products ) ) > 0;
+ if ( $has_videopress_product ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Enable a recommendation.
+ *
+ * @param string $recommendation_name The name of the recommendation to enable.
+ * @return false|void
+ */
+ public static function enable_conditional_recommendation( $recommendation_name ) {
+ if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
+ return false;
+ }
+
+ $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
+ if ( ! in_array( $recommendation_name, $conditional_recommendations, true ) ) {
+ array_push( $conditional_recommendations, $recommendation_name );
+ Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
+ $tracking = new Tracking();
+ $tracking->record_user_event( 'recommendations_conditional_recommendation_enabled', array( 'feature' => $recommendation_name ) );
+ }
+ }
+
+ /**
+ * Disable a recommendation.
+ *
+ * @param string $recommendation_name The name of the recommendation to disable.
+ * @return false|void
+ */
+ public static function disable_conditional_recommendation( $recommendation_name ) {
+ if ( ! in_array( $recommendation_name, self::CONDITIONAL_RECOMMENDATIONS, true ) ) {
+ return false;
+ }
+
+ $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
+ $recommendation_index = array_search( $recommendation_name, $conditional_recommendations, true );
+
+ if ( false !== $recommendation_index ) {
+ array_splice( $conditional_recommendations, $recommendation_index, 1 );
+ Jetpack_Options::update_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, $conditional_recommendations );
+ }
+ }
+
+ /**
+ * Check to see if a recommendation is enabled or not.
+ *
+ * @param string $recommendation_name The name of the recommendation to check for.
+ * @return bool
+ */
+ public static function is_conditional_recommendation_enabled( $recommendation_name ) {
+ $conditional_recommendations = Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
+ return in_array( $recommendation_name, $conditional_recommendations, true );
+ }
+
+ /**
+ * Gets data for all conditional recommendations.
+ *
+ * @return mixed
+ */
+ public static function get_conditional_recommendations() {
+ return Jetpack_Options::get_option( self::CONDITIONAL_RECOMMENDATIONS_OPTION, array() );
+ }
+
+ /**
+ * Get an array of new conditional recommendations that have not been viewed.
+ *
+ * @return array
+ */
+ public static function get_new_conditional_recommendations() {
+ $conditional_recommendations = self::get_conditional_recommendations();
+ $recommendations_data = Jetpack_Options::get_option( 'recommendations_data', array() );
+ $viewed_recommendations = isset( $recommendations_data['viewedRecommendations'] ) ? $recommendations_data['viewedRecommendations'] : array();
+
+ // array_diff returns a keyed array - reduce to unique values.
+ return array_unique( array_values( array_diff( $conditional_recommendations, $viewed_recommendations ) ) );
+ }
+
+ /**
* Initializes the Recommendations step according to the Setup Wizard state.
*/
private static function initialize_jetpack_recommendations() {
diff --git a/plugins/jetpack/_inc/lib/class.color.php b/plugins/jetpack/_inc/lib/class.color.php
index 70930659..5a919af7 100644
--- a/plugins/jetpack/_inc/lib/class.color.php
+++ b/plugins/jetpack/_inc/lib/class.color.php
@@ -1,4 +1,4 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* Color utility and conversion
*
@@ -10,20 +10,29 @@
* @author Harold Asbridge <hasbridge@gmail.com>
* @author Matt Wiebe <wiebe@automattic.com>
* @license https://www.opensource.org/licenses/MIT
+ *
+ * @package automattic/jetpack
*/
+// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
+
+/**
+ * Color utilities
+ */
class Jetpack_Color {
/**
- * @var int
+ * Color code (later array or string, depending on type)
+ *
+ * @var int|array|string
*/
protected $color = 0;
/**
* Initialize object
*
- * @param string|array $color A color of the type $type
- * @param string $type The type of color we will construct from.
- * One of hex (default), rgb, hsl, int
+ * @param string|array $color A color of the type $type.
+ * @param string $type The type of color we will construct from.
+ * One of hex (default), rgb, hsl, int.
*/
public function __construct( $color = null, $type = 'hex' ) {
if ( $color ) {
@@ -32,13 +41,13 @@ class Jetpack_Color {
$this->fromHex( $color );
break;
case 'rgb':
- if ( is_array( $color ) && count( $color ) == 3 ) {
+ if ( is_array( $color ) && count( $color ) === 3 ) {
list( $r, $g, $b ) = array_values( $color );
$this->fromRgbInt( $r, $g, $b );
}
break;
case 'hsl':
- if ( is_array( $color ) && count( $color ) == 3 ) {
+ if ( is_array( $color ) && count( $color ) === 3 ) {
list( $h, $s, $l ) = array_values( $color );
$this->fromHsl( $h, $s, $l );
}
@@ -56,55 +65,44 @@ class Jetpack_Color {
/**
* Init color from hex value
*
- * @param string $hexValue
- *
- * @return Jetpack_Color
- */
- public function fromHex($hexValue) {
- $hexValue = str_replace( '#', '', $hexValue );
- // handle short hex codes like #fff
- if ( 3 === strlen( $hexValue ) ) {
- $short = $hexValue;
- $i = 0;
- $hexValue = '';
- while ( $i < 3 ) {
- $chunk = substr($short, $i, 1 );
- $hexValue .= $chunk . $chunk;
- $i++;
- }
- }
- $intValue = hexdec( $hexValue );
-
- if ( $intValue < 0 || $intValue > 16777215 ) {
- throw new RangeException( $hexValue . " out of valid color code range" );
+ * @param string $hex_value Color hex value.
+ *
+ * @return $this
+ * @throws RangeException Invalid color code range error.
+ */
+ public function fromHex( $hex_value ) {
+ $hex_value = str_replace( '#', '', $hex_value );
+ // handle short hex codes like #fff.
+ if ( 3 === strlen( $hex_value ) ) {
+ $hex_value = $hex_value[0] . $hex_value[0] . $hex_value[1] . $hex_value[1] . $hex_value[2] . $hex_value[2];
}
-
- $this->color = $intValue;
-
- return $this;
+ return $this->fromInt( hexdec( $hex_value ) );
}
/**
* Init color from integer RGB values
*
- * @param int $red
- * @param int $green
- * @param int $blue
+ * @param int $red Red color code.
+ * @param int $green Green color code.
+ * @param int $blue Blue color code.
*
- * @return Jetpack_Color
+ * @return $this
+ * @throws RangeException Invalid color code range error.
*/
- public function fromRgbInt($red, $green, $blue)
- {
- if ( $red < 0 || $red > 255 )
- throw new RangeException( "Red value " . $red . " out of valid color code range" );
+ public function fromRgbInt( $red, $green, $blue ) {
+ if ( $red < 0 || $red > 255 ) {
+ throw new RangeException( 'Red value ' . $red . ' out of valid color code range' );
+ }
- if ( $green < 0 || $green > 255 )
- throw new RangeException( "Green value " . $green . " out of valid color code range" );
+ if ( $green < 0 || $green > 255 ) {
+ throw new RangeException( 'Green value ' . $green . ' out of valid color code range' );
+ }
- if ( $blue < 0 || $blue > 255 )
- throw new RangeException( "Blue value " . $blue . " out of valid color code range" );
+ if ( $blue < 0 || $blue > 255 ) {
+ throw new RangeException( 'Blue value ' . $blue . ' out of valid color code range' );
+ }
- $this->color = (int)(($red << 16) + ($green << 8) + $blue);
+ $this->color = (int) ( ( $red << 16 ) + ( $green << 8 ) + $blue );
return $this;
}
@@ -112,36 +110,40 @@ class Jetpack_Color {
/**
* Init color from hex RGB values
*
- * @param string $red
- * @param string $green
- * @param string $blue
+ * @param string $red Red color code.
+ * @param string $green Green color code.
+ * @param string $blue Blue color code.
*
- * @return Jetpack_Color
+ * @return $this
*/
- public function fromRgbHex($red, $green, $blue)
- {
- return $this->fromRgbInt(hexdec($red), hexdec($green), hexdec($blue));
+ public function fromRgbHex( $red, $green, $blue ) {
+ return $this->fromRgbInt( hexdec( $red ), hexdec( $green ), hexdec( $blue ) );
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from https://en.wikipedia.org/wiki/HSL_color_space.
- * @param int $h Hue. [0-360]
- * @param in $s Saturation [0, 100]
- * @param int $l Lightness [0, 100]
+ *
+ * @param int $h Hue. [0-360].
+ * @param int $s Saturation [0, 100].
+ * @param int $l Lightness [0, 100].
*/
public function fromHsl( $h, $s, $l ) {
- $h /= 360; $s /= 100; $l /= 100;
-
- if ( $s == 0 ) {
- $r = $g = $b = $l; // achromatic
- }
- else {
+ $h /= 360;
+ $s /= 100;
+ $l /= 100;
+
+ if ( 0 === $s ) {
+ // achromatic.
+ $r = $l;
+ $g = $l;
+ $b = $l;
+ } else {
$q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
$p = 2 * $l - $q;
- $r = $this->hue2rgb( $p, $q, $h + 1/3 );
+ $r = $this->hue2rgb( $p, $q, $h + 1 / 3 );
$g = $this->hue2rgb( $p, $q, $h );
- $b = $this->hue2rgb( $p, $q, $h - 1/3 );
+ $b = $this->hue2rgb( $p, $q, $h - 1 / 3 );
}
return $this->fromRgbInt( $r * 255, $g * 255, $b * 255 );
@@ -149,29 +151,44 @@ class Jetpack_Color {
/**
* Helper function for Jetpack_Color::fromHsl()
+ *
+ * @param float $p Minimum of R/G/B [0, 1].
+ * @param float $q Maximum of R/G/B [0, 1].
+ * @param float $t Adjusted hue [0, 1].
*/
private function hue2rgb( $p, $q, $t ) {
- if ( $t < 0 ) $t += 1;
- if ( $t > 1 ) $t -= 1;
- if ( $t < 1/6 ) return $p + ( $q - $p ) * 6 * $t;
- if ( $t < 1/2 ) return $q;
- if ( $t < 2/3 ) return $p + ( $q - $p ) * ( 2/3 - $t ) * 6;
+ if ( $t < 0 ) {
+ ++$t;
+ }
+ if ( $t > 1 ) {
+ --$t;
+ }
+ if ( $t < 1 / 6 ) {
+ return $p + ( $q - $p ) * 6 * $t;
+ }
+ if ( $t < 1 / 2 ) {
+ return $q;
+ }
+ if ( $t < 2 / 3 ) {
+ return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
+ }
return $p;
}
/**
* Init color from integer value
*
- * @param int $intValue
+ * @param int $int_value Color code.
*
- * @return Jetpack_Color
+ * @return $this
+ * @throws RangeException Invalid color code range error.
*/
- public function fromInt($intValue)
- {
- if ( $intValue < 0 || $intValue > 16777215 )
- throw new RangeException( $intValue . " out of valid color code range" );
+ public function fromInt( $int_value ) {
+ if ( $int_value < 0 || $int_value > 16777215 ) {
+ throw new RangeException( $int_value . ' out of valid color code range' );
+ }
- $this->color = $intValue;
+ $this->color = $int_value;
return $this;
}
@@ -181,9 +198,8 @@ class Jetpack_Color {
*
* @return string
*/
- public function toHex()
- {
- return str_pad(dechex($this->color), 6, '0', STR_PAD_LEFT);
+ public function toHex() {
+ return sprintf( '%06x', $this->color );
}
/**
@@ -191,12 +207,11 @@ class Jetpack_Color {
*
* @return array
*/
- public function toRgbInt()
- {
+ public function toRgbInt() {
return array(
- 'red' => (int)(255 & ($this->color >> 16)),
- 'green' => (int)(255 & ($this->color >> 8)),
- 'blue' => (int)(255 & ($this->color))
+ 'red' => (int) ( 255 & ( $this->color >> 16 ) ),
+ 'green' => (int) ( 255 & ( $this->color >> 8 ) ),
+ 'blue' => (int) ( 255 & ( $this->color ) ),
);
}
@@ -205,11 +220,10 @@ class Jetpack_Color {
*
* @return array
*/
- public function toRgbHex()
- {
+ public function toRgbHex() {
$r = array();
- foreach ($this->toRgbInt() as $item) {
- $r[] = dechex($item);
+ foreach ( $this->toRgbInt() as $item ) {
+ $r[] = dechex( $item );
}
return $r;
}
@@ -220,55 +234,54 @@ class Jetpack_Color {
*
* @return array
*/
- public function toHsvFloat()
- {
+ public function toHsvFloat() {
$rgb = $this->toRgbInt();
- $rgbMin = min($rgb);
- $rgbMax = max($rgb);
+ $rgb_min = min( $rgb );
+ $rgb_max = max( $rgb );
$hsv = array(
- 'hue' => 0,
- 'sat' => 0,
- 'val' => $rgbMax
+ 'hue' => 0,
+ 'sat' => 0,
+ 'val' => $rgb_max,
);
- // If v is 0, color is black
- if ($hsv['val'] == 0) {
+ // If v is 0, color is black.
+ if ( 0 === $hsv['val'] ) {
return $hsv;
}
- // Normalize RGB values to 1
- $rgb['red'] /= $hsv['val'];
+ // Normalize RGB values to 1.
+ $rgb['red'] /= $hsv['val'];
$rgb['green'] /= $hsv['val'];
- $rgb['blue'] /= $hsv['val'];
- $rgbMin = min($rgb);
- $rgbMax = max($rgb);
+ $rgb['blue'] /= $hsv['val'];
+ $rgb_min = min( $rgb );
+ $rgb_max = max( $rgb );
- // Calculate saturation
- $hsv['sat'] = $rgbMax - $rgbMin;
- if ($hsv['sat'] == 0) {
+ // Calculate saturation.
+ $hsv['sat'] = $rgb_max - $rgb_min;
+ if ( 0 === $hsv['sat'] ) {
$hsv['hue'] = 0;
return $hsv;
}
- // Normalize saturation to 1
- $rgb['red'] = ($rgb['red'] - $rgbMin) / ($rgbMax - $rgbMin);
- $rgb['green'] = ($rgb['green'] - $rgbMin) / ($rgbMax - $rgbMin);
- $rgb['blue'] = ($rgb['blue'] - $rgbMin) / ($rgbMax - $rgbMin);
- $rgbMin = min($rgb);
- $rgbMax = max($rgb);
-
- // Calculate hue
- if ($rgbMax == $rgb['red']) {
- $hsv['hue'] = 0.0 + 60 * ($rgb['green'] - $rgb['blue']);
- if ($hsv['hue'] < 0) {
+ // Normalize saturation to 1.
+ $rgb['red'] = ( $rgb['red'] - $rgb_min ) / ( $rgb_max - $rgb_min );
+ $rgb['green'] = ( $rgb['green'] - $rgb_min ) / ( $rgb_max - $rgb_min );
+ $rgb['blue'] = ( $rgb['blue'] - $rgb_min ) / ( $rgb_max - $rgb_min );
+ $rgb_min = min( $rgb );
+ $rgb_max = max( $rgb );
+
+ // Calculate hue.
+ if ( $rgb_max === $rgb['red'] ) {
+ $hsv['hue'] = 0.0 + 60 * ( $rgb['green'] - $rgb['blue'] );
+ if ( $hsv['hue'] < 0 ) {
$hsv['hue'] += 360;
}
- } else if ($rgbMax == $rgb['green']) {
- $hsv['hue'] = 120 + (60 * ($rgb['blue'] - $rgb['red']));
+ } elseif ( $rgb_max === $rgb['green'] ) {
+ $hsv['hue'] = 120 + ( 60 * ( $rgb['blue'] - $rgb['red'] ) );
} else {
- $hsv['hue'] = 240 + (60 * ($rgb['red'] - $rgb['green']));
+ $hsv['hue'] = 240 + ( 60 * ( $rgb['red'] - $rgb['green'] ) );
}
return $hsv;
@@ -278,42 +291,41 @@ class Jetpack_Color {
* Get HSV values for color
* (integer values from 0-255, fast but less accurate)
*
- * @return int
+ * @return array
*/
- public function toHsvInt()
- {
+ public function toHsvInt() {
$rgb = $this->toRgbInt();
- $rgbMin = min($rgb);
- $rgbMax = max($rgb);
+ $rgb_min = min( $rgb );
+ $rgb_max = max( $rgb );
$hsv = array(
- 'hue' => 0,
- 'sat' => 0,
- 'val' => $rgbMax
+ 'hue' => 0,
+ 'sat' => 0,
+ 'val' => $rgb_max,
);
- // If value is 0, color is black
- if ($hsv['val'] == 0) {
+ // If value is 0, color is black.
+ if ( 0 === $hsv['val'] ) {
return $hsv;
}
- // Calculate saturation
- $hsv['sat'] = round(255 * ($rgbMax - $rgbMin) / $hsv['val']);
- if ($hsv['sat'] == 0) {
+ // Calculate saturation.
+ $hsv['sat'] = round( 255 * ( $rgb_max - $rgb_min ) / $hsv['val'] );
+ if ( 0 === $hsv['sat'] ) {
$hsv['hue'] = 0;
return $hsv;
}
- // Calculate hue
- if ($rgbMax == $rgb['red']) {
- $hsv['hue'] = round(0 + 43 * ($rgb['green'] - $rgb['blue']) / ($rgbMax - $rgbMin));
- } else if ($rgbMax == $rgb['green']) {
- $hsv['hue'] = round(85 + 43 * ($rgb['blue'] - $rgb['red']) / ($rgbMax - $rgbMin));
+ // Calculate hue.
+ if ( $rgb_max === $rgb['red'] ) {
+ $hsv['hue'] = round( 0 + 43 * ( $rgb['green'] - $rgb['blue'] ) / ( $rgb_max - $rgb_min ) );
+ } elseif ( $rgb_max === $rgb['green'] ) {
+ $hsv['hue'] = round( 85 + 43 * ( $rgb['blue'] - $rgb['red'] ) / ( $rgb_max - $rgb_min ) );
} else {
- $hsv['hue'] = round(171 + 43 * ($rgb['red'] - $rgb['green']) / ($rgbMax - $rgbMin));
+ $hsv['hue'] = round( 171 + 43 * ( $rgb['red'] - $rgb['green'] ) / ( $rgb_max - $rgb_min ) );
}
- if ($hsv['hue'] < 0) {
+ if ( $hsv['hue'] < 0 ) {
$hsv['hue'] += 255;
}
@@ -326,19 +338,22 @@ class Jetpack_Color {
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h in [0, 360], s in [0, 100], l in [0, 100]
*
- * @return Array The HSL representation
+ * @return Array The HSL representation
*/
public function toHsl() {
list( $r, $g, $b ) = array_values( $this->toRgbInt() );
- $r /= 255; $g /= 255; $b /= 255;
- $max = max( $r, $g, $b );
- $min = min( $r, $g, $b );
- $h = $s = $l = ( $max + $min ) / 2;
- #var_dump( array( compact('max', 'min', 'r', 'g', 'b')) );
- if ( $max == $min ) {
- $h = $s = 0; // achromatic
- }
- else {
+ $r /= 255;
+ $g /= 255;
+ $b /= 255;
+ $max = max( $r, $g, $b );
+ $min = min( $r, $g, $b );
+ $l = ( $max + $min ) / 2;
+
+ if ( $max === $min ) {
+ // achromatic.
+ $s = 0;
+ $h = 0;
+ } else {
$d = $max - $min;
$s = $l > 0.5 ? $d / ( 2 - $max - $min ) : $d / ( $max + $min );
switch ( $max ) {
@@ -360,34 +375,36 @@ class Jetpack_Color {
return compact( 'h', 's', 'l' );
}
+ /**
+ * From a color code to a string to be used in CSS declaration.
+ *
+ * @param string $type Color code type.
+ * @param int $alpha Transparency.
+ *
+ * @return string
+ */
public function toCSS( $type = 'hex', $alpha = 1 ) {
switch ( $type ) {
case 'hex':
return $this->toString();
- break;
case 'rgb':
case 'rgba':
list( $r, $g, $b ) = array_values( $this->toRgbInt() );
if ( is_numeric( $alpha ) && $alpha < 1 ) {
return "rgba( {$r}, {$g}, {$b}, $alpha )";
- }
- else {
+ } else {
return "rgb( {$r}, {$g}, {$b} )";
}
- break;
case 'hsl':
case 'hsla':
list( $h, $s, $l ) = array_values( $this->toHsl() );
if ( is_numeric( $alpha ) && $alpha < 1 ) {
return "hsla( {$h}, {$s}, {$l}, $alpha )";
- }
- else {
+ } else {
return "hsl( {$h}, {$s}, {$l} )";
}
- break;
default:
return $this->toString();
- break;
}
}
@@ -396,22 +413,20 @@ class Jetpack_Color {
*
* @return array
*/
- public function toXyz()
- {
+ public function toXyz() {
$rgb = $this->toRgbInt();
- // Normalize RGB values to 1
-
+ // Normalize RGB values to 1.
$rgb_new = array();
- foreach ($rgb as $item) {
+ foreach ( $rgb as $item ) {
$rgb_new[] = $item / 255;
}
$rgb = $rgb_new;
$rgb_new = array();
- foreach ($rgb as $item) {
- if ($item > 0.04045) {
- $item = pow((($item + 0.055) / 1.055), 2.4);
+ foreach ( $rgb as $item ) {
+ if ( $item > 0.04045 ) {
+ $item = pow( ( ( $item + 0.055 ) / 1.055 ), 2.4 );
} else {
$item = $item / 12.92;
}
@@ -419,11 +434,11 @@ class Jetpack_Color {
}
$rgb = $rgb_new;
- // Observer. = 2°, Illuminant = D65
+ // Observer. = 2°, Illuminant = D65.
$xyz = array(
- 'x' => ($rgb['red'] * 0.4124) + ($rgb['green'] * 0.3576) + ($rgb['blue'] * 0.1805),
- 'y' => ($rgb['red'] * 0.2126) + ($rgb['green'] * 0.7152) + ($rgb['blue'] * 0.0722),
- 'z' => ($rgb['red'] * 0.0193) + ($rgb['green'] * 0.1192) + ($rgb['blue'] * 0.9505)
+ 'x' => ( $rgb['red'] * 0.4124 ) + ( $rgb['green'] * 0.3576 ) + ( $rgb['blue'] * 0.1805 ),
+ 'y' => ( $rgb['red'] * 0.2126 ) + ( $rgb['green'] * 0.7152 ) + ( $rgb['blue'] * 0.0722 ),
+ 'z' => ( $rgb['red'] * 0.0193 ) + ( $rgb['green'] * 0.1192 ) + ( $rgb['blue'] * 0.9505 ),
);
return $xyz;
@@ -434,29 +449,28 @@ class Jetpack_Color {
*
* @return array
*/
- public function toLabCie()
- {
+ public function toLabCie() {
$xyz = $this->toXyz();
- //Ovserver = 2*, Iluminant=D65
+ // Ovserver = 2*, Iluminant=D65.
$xyz['x'] /= 95.047;
$xyz['y'] /= 100;
$xyz['z'] /= 108.883;
$xyz_new = array();
- foreach ($xyz as $item) {
- if ($item > 0.008856) {
- $xyz_new[] = pow($item, 1/3);
+ foreach ( $xyz as $item ) {
+ if ( $item > 0.008856 ) {
+ $xyz_new[] = pow( $item, 1 / 3 );
} else {
- $xyz_new[] = (7.787 * $item) + (16 / 116);
+ $xyz_new[] = ( 7.787 * $item ) + ( 16 / 116 );
}
}
$xyz = $xyz_new;
$lab = array(
- 'l' => (116 * $xyz['y']) - 16,
- 'a' => 500 * ($xyz['x'] - $xyz['y']),
- 'b' => 200 * ($xyz['y'] - $xyz['z'])
+ 'l' => ( 116 * $xyz['y'] ) - 16,
+ 'a' => 500 * ( $xyz['x'] - $xyz['y'] ),
+ 'b' => 200 * ( $xyz['y'] - $xyz['z'] ),
);
return $lab;
@@ -467,8 +481,7 @@ class Jetpack_Color {
*
* @return int
*/
- public function toInt()
- {
+ public function toInt() {
return $this->color;
}
@@ -477,8 +490,7 @@ class Jetpack_Color {
*
* @return string
*/
- public function __toString()
- {
+ public function __toString() {
return $this->toString();
}
@@ -487,58 +499,60 @@ class Jetpack_Color {
*
* @return string
*/
- public function toString()
- {
+ public function toString() {
$str = $this->toHex();
- return strtoupper("#{$str}");
+ return strtoupper( "#{$str}" );
}
/**
* Get the distance between this color and the given color
*
- * @param Jetpack_Color $color
+ * @param Jetpack_Color $color Color code.
*
* @return int
*/
- public function getDistanceRgbFrom(Jetpack_Color $color)
- {
+ public function getDistanceRgbFrom( Jetpack_Color $color ) {
$rgb1 = $this->toRgbInt();
$rgb2 = $color->toRgbInt();
- $rDiff = abs($rgb1['red'] - $rgb2['red']);
- $gDiff = abs($rgb1['green'] - $rgb2['green']);
- $bDiff = abs($rgb1['blue'] - $rgb2['blue']);
+ $r_diff = abs( $rgb1['red'] - $rgb2['red'] );
+ $g_diff = abs( $rgb1['green'] - $rgb2['green'] );
+ $b_diff = abs( $rgb1['blue'] - $rgb2['blue'] );
- // Sum of RGB differences
- $diff = $rDiff + $gDiff + $bDiff;
+ // Sum of RGB differences.
+ $diff = $r_diff + $g_diff + $b_diff;
return $diff;
}
/**
* Get distance from the given color using the Delta E method
*
- * @param Jetpack_Color $color
+ * @param Jetpack_Color $color Color code.
*
* @return float
*/
- public function getDistanceLabFrom(Jetpack_Color $color)
- {
+ public function getDistanceLabFrom( Jetpack_Color $color ) {
$lab1 = $this->toLabCie();
$lab2 = $color->toLabCie();
- $lDiff = abs($lab2['l'] - $lab1['l']);
- $aDiff = abs($lab2['a'] - $lab1['a']);
- $bDiff = abs($lab2['b'] - $lab1['b']);
+ $l_diff = abs( $lab2['l'] - $lab1['l'] );
+ $a_diff = abs( $lab2['a'] - $lab1['a'] );
+ $b_diff = abs( $lab2['b'] - $lab1['b'] );
- $delta = sqrt($lDiff + $aDiff + $bDiff);
+ $delta = sqrt( $l_diff + $a_diff + $b_diff );
return $delta;
}
+ /**
+ * Calculate luminosity.
+ *
+ * @return float
+ */
public function toLuminosity() {
$lum = array();
- foreach( $this->toRgbInt() as $slot => $value ) {
- $chan = $value / 255;
+ foreach ( $this->toRgbInt() as $slot => $value ) {
+ $chan = $value / 255;
$lum[ $slot ] = ( $chan <= 0.03928 ) ? $chan / 12.92 : pow( ( ( $chan + 0.055 ) / 1.055 ), 2.4 );
}
return 0.2126 * $lum['red'] + 0.7152 * $lum['green'] + 0.0722 * $lum['blue'];
@@ -548,36 +562,47 @@ class Jetpack_Color {
* Get distance between colors using luminance.
* Should be more than 5 for readable contrast
*
- * @param Jetpack_Color $color Another color
+ * @param Jetpack_Color $color Another color.
* @return float
*/
public function getDistanceLuminosityFrom( Jetpack_Color $color ) {
- $L1 = $this->toLuminosity();
- $L2 = $color->toLuminosity();
- if ( $L1 > $L2 ) {
- return ( $L1 + 0.05 ) / ( $L2 + 0.05 );
- }
- else{
- return ( $L2 + 0.05 ) / ( $L1 + 0.05 );
+ $l1 = $this->toLuminosity();
+ $l2 = $color->toLuminosity();
+ if ( $l1 > $l2 ) {
+ return ( $l1 + 0.05 ) / ( $l2 + 0.05 );
+ } else {
+ return ( $l2 + 0.05 ) / ( $l1 + 0.05 );
}
}
+ /**
+ * Get maximum contrast color.
+ *
+ * @return $this
+ */
public function getMaxContrastColor() {
- $withBlack = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#000') );
- $withWhite = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#fff') );
- $color = new Jetpack_Color;
- $hex = ( $withBlack >= $withWhite ) ? '#000000' : '#ffffff';
+ $with_black = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#000' ) );
+ $with_white = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#fff' ) );
+ $color = new Jetpack_Color();
+ $hex = ( $with_black >= $with_white ) ? '#000000' : '#ffffff';
return $color->fromHex( $hex );
}
+ /**
+ * Get grayscale contrasting color.
+ *
+ * @param bool|int $contrast Contrast.
+ *
+ * @return $this
+ */
public function getGrayscaleContrastingColor( $contrast = false ) {
if ( ! $contrast ) {
return $this->getMaxContrastColor();
}
- // don't allow less than 5
+ // don't allow less than 5.
$target_contrast = ( $contrast < 5 ) ? 5 : $contrast;
- $color = $this->getMaxContrastColor();
- $contrast = $color->getDistanceLuminosityFrom( $this );
+ $color = $this->getMaxContrastColor();
+ $contrast = $color->getDistanceLuminosityFrom( $this );
// if current max contrast is less than the target contrast, we had wishful thinking.
if ( $contrast <= $target_contrast ) {
@@ -586,7 +611,7 @@ class Jetpack_Color {
$incr = ( '#000000' === $color->toString() ) ? 1 : -1;
while ( $contrast > $target_contrast ) {
- $color = $color->incrementLightness( $incr );
+ $color = $color->incrementLightness( $incr );
$contrast = $color->getDistanceLuminosityFrom( $this );
}
@@ -595,7 +620,8 @@ class Jetpack_Color {
/**
* Gets a readable contrasting color. $this is assumed to be the text and $color the background color.
- * @param object $bg_color A Color object that will be compared against $this
+ *
+ * @param object $bg_color A Color object that will be compared against $this.
* @param integer $min_contrast The minimum contrast to achieve, if possible.
* @return object A Color object, an increased contrast $this compared against $bg_color
*/
@@ -605,17 +631,17 @@ class Jetpack_Color {
}
// you shouldn't use less than 5, but you might want to.
$target_contrast = $min_contrast;
- // working things
- $contrast = $bg_color->getDistanceLuminosityFrom( $this );
+ // working things.
+ $contrast = $bg_color->getDistanceLuminosityFrom( $this );
$max_contrast_color = $bg_color->getMaxContrastColor();
- $max_contrast = $max_contrast_color->getDistanceLuminosityFrom( $bg_color );
+ $max_contrast = $max_contrast_color->getDistanceLuminosityFrom( $bg_color );
// if current max contrast is less than the target contrast, we had wishful thinking.
- // still, go max
+ // still, go max.
if ( $max_contrast <= $target_contrast ) {
return $max_contrast_color;
}
- // or, we might already have sufficient contrast
+ // or, we might already have sufficient contrast.
if ( $contrast >= $target_contrast ) {
return $this;
}
@@ -625,7 +651,7 @@ class Jetpack_Color {
$this->incrementLightness( $incr );
$contrast = $bg_color->getDistanceLuminosityFrom( $this );
// infininite loop prevention: you never know.
- if ( $this->color === 0 || $this->color === 16777215 ) {
+ if ( 0 === $this->color || 16777215 === $this->color ) {
break;
}
}
@@ -636,18 +662,17 @@ class Jetpack_Color {
/**
* Detect if color is grayscale
*
- * @param int @threshold
+ * @param int $threshold Max difference between colors.
*
* @return bool
*/
- public function isGrayscale($threshold = 16)
- {
+ public function isGrayscale( $threshold = 16 ) {
$rgb = $this->toRgbInt();
- // Get min and max rgb values, then difference between them
- $rgbMin = min($rgb);
- $rgbMax = max($rgb);
- $diff = $rgbMax - $rgbMin;
+ // Get min and max rgb values, then difference between them.
+ $rgb_min = min( $rgb );
+ $rgb_max = max( $rgb );
+ $diff = $rgb_max - $rgb_min;
return $diff < $threshold;
}
@@ -655,38 +680,58 @@ class Jetpack_Color {
/**
* Get the closest matching color from the given array of colors
*
- * @param array $colors array of integers or Jetpack_Color objects
+ * @param array $colors array of integers or Jetpack_Color objects.
*
* @return mixed the array key of the matched color
*/
- public function getClosestMatch(array $colors)
- {
- $matchDist = 10000;
- $matchKey = null;
- foreach($colors as $key => $color) {
- if (false === ($color instanceof Jetpack_Color)) {
- $c = new Jetpack_Color($color);
+ public function getClosestMatch( array $colors ) {
+ $match_dist = 10000;
+ $match_key = null;
+ foreach ( $colors as $key => $color ) {
+ if ( false === ( $color instanceof Jetpack_Color ) ) {
+ $c = new Jetpack_Color( $color );
}
- $dist = $this->getDistanceLabFrom($c);
- if ($dist < $matchDist) {
- $matchDist = $dist;
- $matchKey = $key;
+ $dist = $this->getDistanceLabFrom( $c );
+ if ( $dist < $match_dist ) {
+ $match_dist = $dist;
+ $match_key = $key;
}
}
- return $matchKey;
+ return $match_key;
}
/* TRANSFORMS */
+ /**
+ * Transform -- Darken color.
+ *
+ * @param int $amount Amount. Default to 5.
+ *
+ * @return $this
+ */
public function darken( $amount = 5 ) {
return $this->incrementLightness( - $amount );
}
+ /**
+ * Transform -- Lighten color.
+ *
+ * @param int $amount Amount. Default to 5.
+ *
+ * @return $this
+ */
public function lighten( $amount = 5 ) {
return $this->incrementLightness( $amount );
}
+ /**
+ * Transform -- Increment lightness.
+ *
+ * @param int $amount Amount.
+ *
+ * @return $this
+ */
public function incrementLightness( $amount ) {
$hsl = $this->toHsl();
@@ -695,19 +740,44 @@ class Jetpack_Color {
$l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
$l += $amount;
- if ( $l < 0 ) $l = 0;
- if ( $l > 100 ) $l = 100;
+ if ( $l < 0 ) {
+ $l = 0;
+ }
+ if ( $l > 100 ) {
+ $l = 100;
+ }
return $this->fromHsl( $h, $s, $l );
}
+ /**
+ * Transform -- Saturate color.
+ *
+ * @param int $amount Amount. Default to 15.
+ *
+ * @return $this
+ */
public function saturate( $amount = 15 ) {
return $this->incrementSaturation( $amount );
}
+ /**
+ * Transform -- Desaturate color.
+ *
+ * @param int $amount Amount. Default to 15.
+ *
+ * @return $this
+ */
public function desaturate( $amount = 15 ) {
return $this->incrementSaturation( - $amount );
}
+ /**
+ * Transform -- Increment saturation.
+ *
+ * @param int $amount Amount.
+ *
+ * @return $this
+ */
public function incrementSaturation( $amount ) {
$hsl = $this->toHsl();
@@ -716,11 +786,20 @@ class Jetpack_Color {
$l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
$s += $amount;
- if ( $s < 0 ) $s = 0;
- if ( $s > 100 ) $s = 100;
+ if ( $s < 0 ) {
+ $s = 0;
+ }
+ if ( $s > 100 ) {
+ $s = 100;
+ }
return $this->fromHsl( $h, $s, $l );
}
+ /**
+ * Transform -- To grayscale.
+ *
+ * @return $this
+ */
public function toGrayscale() {
$hsl = $this->toHsl();
@@ -731,30 +810,80 @@ class Jetpack_Color {
return $this->fromHsl( $h, $s, $l );
}
+ /**
+ * Transform -- To the complementary color.
+ *
+ * The complement is the color on the opposite side of the color wheel, 180° away.
+ *
+ * @return $this
+ */
public function getComplement() {
return $this->incrementHue( 180 );
}
+ /**
+ * Transform -- To an analogous color of the complement.
+ *
+ * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
+ *
+ * @return $this
+ */
public function getSplitComplement( $step = 1 ) {
$incr = 180 + ( $step * 30 );
return $this->incrementHue( $incr );
}
+ /**
+ * Transform -- To an analogous color.
+ *
+ * Analogous colors are those adjacent on the color wheel, separated by 30°.
+ *
+ * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
+ *
+ * @return $this
+ */
public function getAnalog( $step = 1 ) {
$incr = $step * 30;
return $this->incrementHue( $incr );
}
+ /**
+ * Transform -- To a tetradic (rectangular) color.
+ *
+ * A rectangular color scheme uses a color, its complement, and the colors 60° from each.
+ * This transforms the color to its 60° "tetrad".
+ *
+ * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
+ *
+ * @return $this
+ */
public function getTetrad( $step = 1 ) {
$incr = $step * 60;
return $this->incrementHue( $incr );
}
+ /**
+ * Transform -- To a triadic color.
+ *
+ * A triadic color scheme uses three colors evenly spaced (120°) around the color wheel.
+ * This transforms the color to one of its triadic colors.
+ *
+ * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
+ *
+ * @return $this
+ */
public function getTriad( $step = 1 ) {
$incr = $step * 120;
return $this->incrementHue( $incr );
}
+ /**
+ * Transform -- Increment hue.
+ *
+ * @param int $amount Amount.
+ *
+ * @return $this
+ */
public function incrementHue( $amount ) {
$hsl = $this->toHsl();
@@ -763,8 +892,10 @@ class Jetpack_Color {
$l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
$h = ( $h + $amount ) % 360;
- if ( $h < 0 ) $h = 360 - $h;
+ if ( $h < 0 ) {
+ $h += 360;
+ }
return $this->fromHsl( $h, $s, $l );
}
-} // class Jetpack_Color
+}
diff --git a/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php b/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php
index 342c85b2..35d91c3b 100644
--- a/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php
+++ b/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php
@@ -1,19 +1,18 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Register WP REST API endpoints for Jetpack.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Connection\Rest_Authentication;
use Automattic\Jetpack\Connection\REST_Connector;
use Automattic\Jetpack\Jetpack_CRM_Data;
-use Automattic\Jetpack\Licensing;
-use Automattic\Jetpack\Search\REST_Controller as Search_REST_Controller;
+use Automattic\Jetpack\Plugins_Installer;
use Automattic\Jetpack\Status\Host;
-
-/**
- * Register WP REST API endpoints for Jetpack.
- *
- * @author Automattic
- */
+use Automattic\Jetpack\Status\Visitor;
/**
* Disable direct access.
@@ -31,25 +30,16 @@ add_action( 'rest_api_init', array( 'Jetpack_Core_Json_Api_Endpoints', 'register
// Each of these is a class that will register its own routes on 'rest_api_init'.
require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/load-wpcom-endpoints.php';
-// Load Search endpoints when WP REST API is initialized.
-add_action( 'rest_api_init', array( new Search_REST_Controller(), 'register_rest_routes' ) );
-
/**
* Class Jetpack_Core_Json_Api_Endpoints
*
* @since 4.3.0
*/
class Jetpack_Core_Json_Api_Endpoints {
-
/**
- * @var string Generic error message when user is not allowed to perform an action.
+ * Roles that can access Stats once they're granted access.
*
- * @deprecated 8.8.0 Use `REST_Connector::get_user_permissions_error_msg()` instead.
- */
- public static $user_permissions_error_msg;
-
- /**
- * @var array Roles that can access Stats once they're granted access.
+ * @var array
*/
public static $stats_roles;
@@ -60,16 +50,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function register_endpoints() {
- // Load API endpoint base classes
+ // Load API endpoint base classes.
require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php';
- // Load API endpoints
+ // Load API endpoints.
require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php';
require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php';
require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php';
- self::$user_permissions_error_msg = REST_Connector::get_user_permissions_error_msg();
-
self::$stats_roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
$ixr_client = new Jetpack_IXR_Client( array( 'user_id' => get_current_user_id() ) );
@@ -110,7 +98,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Test current connection status of Jetpack
+ // Test current connection status of Jetpack.
register_rest_route(
'jetpack/v4',
'/connection/test',
@@ -152,7 +140,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Fetches a fresh connect URL
+ // Fetches a fresh connect URL.
register_rest_route(
'jetpack/v4',
'/connection/url',
@@ -188,7 +176,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Disconnect/unlink user from WordPress.com servers
+ // Disconnect/unlink user from WordPress.com servers.
register_rest_route(
'jetpack/v4',
'/connection/user',
@@ -199,7 +187,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Get current site data
+ // Get current site data.
register_rest_route(
'jetpack/v4',
'/site',
@@ -210,7 +198,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Get current site data
+ // Get current site data.
register_rest_route(
'jetpack/v4',
'/site/features',
@@ -242,7 +230,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Get current site benefits
+ // Get current site benefits.
register_rest_route(
'jetpack/v4',
'/site/benefits',
@@ -264,7 +252,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Return all modules
+ // Return all modules.
register_rest_route(
'jetpack/v4',
'/module/all',
@@ -275,7 +263,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Activate many modules
+ // Activate many modules.
register_rest_route(
'jetpack/v4',
'/module/all/active',
@@ -303,7 +291,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Return a single module and update it when needed
+ // Return a single module and update it when needed.
register_rest_route(
'jetpack/v4',
'/module/(?P<slug>[a-z\-]+)',
@@ -314,7 +302,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Activate and deactivate a module
+ // Activate and deactivate a module.
register_rest_route(
'jetpack/v4',
'/module/(?P<slug>[a-z\-]+)/active',
@@ -333,7 +321,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Update a module
+ // Update a module.
register_rest_route(
'jetpack/v4',
'/module/(?P<slug>[a-z\-]+)',
@@ -365,7 +353,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Check if the API key for a specific service is valid or not
+ // Check if the API key for a specific service is valid or not.
register_rest_route(
'jetpack/v4',
'/module/(?P<service>[a-z\-]+)/key/check',
@@ -395,7 +383,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Update any Jetpack module option or setting
+ // Update any Jetpack module option or setting.
register_rest_route(
'jetpack/v4',
'/settings',
@@ -407,7 +395,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Update a module
+ // Update a module.
register_rest_route(
'jetpack/v4',
'/settings/(?P<slug>[a-z\-]+)',
@@ -419,7 +407,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Return all module settings
+ // Return all module settings.
register_rest_route(
'jetpack/v4',
'/settings/',
@@ -430,7 +418,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Reset all Jetpack options
+ // Reset all Jetpack options.
register_rest_route(
'jetpack/v4',
'/options/(?P<options>[a-z\-]+)',
@@ -441,7 +429,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Updates: get number of plugin updates available
+ // Updates: get number of plugin updates available.
register_rest_route(
'jetpack/v4',
'/updates/plugins',
@@ -452,7 +440,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Dismiss Jetpack Notices
+ // Dismiss Jetpack Notices.
register_rest_route(
'jetpack/v4',
'/notice/(?P<notice>[a-z\-_]+)',
@@ -559,7 +547,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Site Verify: check if the site is verified, and a get verification token if not
+ // Site Verify: check if the site is verified, and a get verification token if not.
register_rest_route(
'jetpack/v4',
'/verify-site/(?P<service>[a-z\-_]+)',
@@ -580,7 +568,7 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- // Site Verify: tell a service to verify the site
+ // Site Verify: tell a service to verify the site.
register_rest_route(
'jetpack/v4',
'/verify-site/(?P<service>[a-z\-_]+)',
@@ -680,105 +668,26 @@ class Jetpack_Core_Json_Api_Endpoints {
)
);
- /*
- * Get and update the last licensing error message.
- */
register_rest_route(
'jetpack/v4',
- '/licensing/error',
+ '/recommendations/conditional',
array(
array(
'methods' => WP_REST_Server::READABLE,
- 'callback' => __CLASS__ . '::get_licensing_error',
- 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check',
- ),
- array(
- 'methods' => WP_REST_Server::EDITABLE,
- 'callback' => __CLASS__ . '::update_licensing_error',
+ 'callback' => __CLASS__ . '::get_conditional_recommendations',
'permission_callback' => __CLASS__ . '::view_admin_page_permission_check',
- 'args' => array(
- 'error' => array(
- 'required' => true,
- 'type' => 'string',
- 'validate_callback' => __CLASS__ . '::validate_string',
- 'sanitize_callback' => 'sanitize_text_field',
- ),
- ),
),
)
);
- // Return all module settings.
+ // Get site discount.
register_rest_route(
'jetpack/v4',
- '/licensing/set-license',
- array(
- 'methods' => WP_REST_Server::EDITABLE,
- 'callback' => __CLASS__ . '::set_jetpack_license',
- 'permission_callback' => __CLASS__ . '::set_jetpack_license_key_permission_check',
- 'args' => array(
- 'license' => array(
- 'required' => true,
- 'type' => 'string',
- 'validate_callback' => __CLASS__ . '::validate_string',
- 'sanitize_callback' => 'sanitize_text_field',
- ),
- ),
- )
- );
-
- /**
- * Get Jetpack user license counts.
- */
- register_rest_route(
- 'jetpack/v4',
- 'licensing/user/counts',
+ '/site/discount',
array(
'methods' => WP_REST_Server::READABLE,
- 'callback' => __CLASS__ . '::get_user_license_counts',
- 'permission_callback' => __CLASS__ . '::user_licensing_permission_check',
- )
- );
-
- /**
- * Update user-licensing activation notice dismiss info.
- */
- register_rest_route(
- 'jetpack/v4',
- 'licensing/user/activation-notice-dismiss',
- array(
- 'methods' => WP_REST_Server::EDITABLE,
- 'callback' => __CLASS__ . '::update_licensing_activation_notice_dismiss',
- 'permission_callback' => __CLASS__ . '::user_licensing_permission_check',
- 'args' => array(
- 'last_detached_count' => array(
- 'required' => true,
- 'type' => 'integer',
- 'validate_callback' => __CLASS__ . '::validate_non_neg_int',
- ),
- ),
- )
- );
-
- /**
- * Attach licenses to user account
- */
- register_rest_route(
- 'jetpack/v4',
- '/licensing/attach-licenses',
- array(
- 'methods' => WP_REST_Server::EDITABLE,
- 'callback' => __CLASS__ . '::attach_jetpack_licenses',
- 'permission_callback' => __CLASS__ . '::user_licensing_permission_check',
- 'args' => array(
- 'licenses' => array(
- 'required' => true,
- 'type' => 'array',
- 'items' => array(
- 'type' => 'string',
- ),
- ),
- ),
+ 'callback' => __CLASS__ . '::get_site_discount',
+ 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check',
)
);
@@ -837,6 +746,17 @@ class Jetpack_Core_Json_Api_Endpoints {
'permission_callback' => __CLASS__ . '::manage_modules_permission_check',
)
);
+
+ // Get Jetpack introduction offers
+ register_rest_route(
+ 'jetpack/v4',
+ '/intro-offers',
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => __CLASS__ . '::get_intro_offers',
+ 'permission_callback' => __CLASS__ . '::view_admin_page_permission_check',
+ )
+ );
}
/**
@@ -908,7 +828,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
)
);
@@ -952,7 +872,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
)
);
@@ -970,6 +890,15 @@ class Jetpack_Core_Json_Api_Endpoints {
}
/**
+ * Get conditional recommendations data.
+ *
+ * @return array Conditional recommendations data.
+ */
+ public static function get_conditional_recommendations() {
+ return Jetpack_Recommendations::get_conditional_recommendations();
+ }
+
+ /**
* Validate the recommendations data
*
* @param array $value Value to check received by request.
@@ -1029,6 +958,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return Jetpack_Options::delete_option( 'purchase_token' );
}
+ /**
+ * Get list of Jetpack Plans.
+ *
+ * @param WP_REST_Request $request The request.
+ */
public static function get_plans( $request ) {
$request = Client::wpcom_json_api_request_as_user(
'/plans?_locale=' . get_user_locale(),
@@ -1036,7 +970,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
)
);
@@ -1045,7 +979,7 @@ class Jetpack_Core_Json_Api_Endpoints {
if ( 200 === wp_remote_retrieve_response_code( $request ) ) {
$data = $body;
} else {
- // something went wrong so we'll just return the response without caching
+ // something went wrong so we'll just return the response without caching.
return $body;
}
@@ -1060,14 +994,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*
* @return string|WP_Error A JSON object of wpcom products if the request was successful, or a WP_Error otherwise.
*/
- public static function get_products( $request ) {
+ public static function get_products( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$wpcom_request = Client::wpcom_json_api_request_as_user(
'/products?_locale=' . get_user_locale() . '&type=jetpack',
'2',
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
)
);
@@ -1086,76 +1020,11 @@ class Jetpack_Core_Json_Api_Endpoints {
}
/**
- * Gets the users licenses counts.
- *
- * @since 10.4.0
- *
- * @return string|WP_Error A JSON object of user license counts if the request was successful, or a WP_Error otherwise.
- */
- public static function get_user_license_counts() {
- $wpcom_request = Client::wpcom_json_api_request_as_user(
- '/jetpack-licensing/user/licenses/counts',
- '2',
- array(
- 'method' => 'GET',
- 'headers' => array(
- 'Content-Type' => 'application/json',
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
- ),
- )
- );
-
- $response_code = wp_remote_retrieve_response_code( $wpcom_request );
- if ( 200 === $response_code ) {
- $license_counts = json_decode( wp_remote_retrieve_body( $wpcom_request ) );
- return $license_counts;
- } else {
- return new WP_Error(
- 'failed_to_fetch_data',
- esc_html__( 'Unable to fetch the requested data.', 'jetpack' ),
- array( 'status' => $response_code )
- );
- }
- }
-
- /**
- * Update the user-licenses activation notice dismissal data.
- *
- * @since 10.4.0
- *
- * @param WP_REST_Request $request The request sent to the WP REST API.
+ * Send Survey details to WordPress.com.
*
- * @return array|WP_Error
+ * @param WP_REST_Request $request The request.
*/
- public static function update_licensing_activation_notice_dismiss( $request ) {
-
- if ( ! isset( $request['last_detached_count'] ) ) {
- return new WP_Error( 'invalid_param', esc_html__( 'Missing parameter "last_detached_count".', 'jetpack' ), array( 'status' => 404 ) );
- }
-
- $default = array(
- 'last_detached_count' => null,
- 'last_dismissed_time' => null,
- );
- $last_detached_count = ( '' === $request['last_detached_count'] )
- ? $default['last_detached_count']
- : $request['last_detached_count'];
- $last_dismissed_time = ( '' === $request['last_detached_count'] )
- ? $default['last_dismissed_time']
- // Use UTC timezone and convert to ISO8601 format(DateTime::W3C) for best compatibility with JavaScript Date in all browsers.
- : ( new DateTime( 'NOW', new DateTimeZone( 'UTC' ) ) )->format( DateTime::W3C );
-
- $notice_data = array(
- 'last_detached_count' => $last_detached_count,
- 'last_dismissed_time' => $last_dismissed_time,
- );
-
- Jetpack_Options::update_option( 'licensing_activation_notice_dismiss', $notice_data, true );
- return rest_ensure_response( $notice_data );
- }
-
public static function submit_survey( $request ) {
-
$wpcom_request = Client::wpcom_json_api_request_as_user(
'/marketing/survey',
'v2',
@@ -1163,7 +1032,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/json',
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
),
$request->get_json_params()
@@ -1173,7 +1042,7 @@ class Jetpack_Core_Json_Api_Endpoints {
if ( 200 === wp_remote_retrieve_response_code( $wpcom_request ) ) {
$data = $wpcom_request_body;
} else {
- // something went wrong so we'll just return the response without caching
+ // something went wrong so we'll just return the response without caching.
return $wpcom_request_body;
}
@@ -1214,10 +1083,10 @@ class Jetpack_Core_Json_Api_Endpoints {
$csp4 = get_option( 'seed_csp4_settings_content', array() );
if (
( Jetpack::is_plugin_active( 'mojo-marketplace-wp-plugin/mojo-marketplace.php' ) && 'true' === $mm_coming_soon )
- || Jetpack::is_plugin_active( 'mojo-under-construction/mojo-contruction.php' ) && 1 == $under_construction_activation_status // WPCS: loose comparison ok.
- || ( Jetpack::is_plugin_active( 'under-construction-page/under-construction.php' ) && isset( $ucp_options['status'] ) && 1 == $ucp_options['status'] ) // WPCS: loose comparison ok.
- || ( Jetpack::is_plugin_active( 'ultimate-under-construction/ultimate-under-construction.php' ) && isset( $uuc_settings['enable'] ) && 1 == $uuc_settings['enable'] ) // WPCS: loose comparison ok.
- || ( Jetpack::is_plugin_active( 'coming-soon/coming-soon.php' ) && isset( $csp4['status'] ) && ( 1 == $csp4['status'] || 2 == $csp4['status'] ) ) // WPCS: loose comparison ok.
+ || Jetpack::is_plugin_active( 'mojo-under-construction/mojo-contruction.php' ) && 1 == $under_construction_activation_status // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
+ || ( Jetpack::is_plugin_active( 'under-construction-page/under-construction.php' ) && isset( $ucp_options['status'] ) && 1 == $ucp_options['status'] ) // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
+ || ( Jetpack::is_plugin_active( 'ultimate-under-construction/ultimate-under-construction.php' ) && isset( $uuc_settings['enable'] ) && 1 == $uuc_settings['enable'] ) // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
+ || ( Jetpack::is_plugin_active( 'coming-soon/coming-soon.php' ) && isset( $csp4['status'] ) && ( 1 == $csp4['status'] || 2 == $csp4['status'] ) ) // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
/**
* Allow plugins to mark a site as "under construction".
*
@@ -1254,6 +1123,11 @@ class Jetpack_Core_Json_Api_Endpoints {
}
}
+ /**
+ * Verify site with external service.
+ *
+ * @param WP_REST_Request $request The request.
+ */
public static function verify_site( $request ) {
$xml = new Jetpack_IXR_Client(
array(
@@ -1299,7 +1173,7 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function dismiss_notice( $request ) {
$notice = $request['notice'];
- if ( ! isset( $request['dismissed'] ) || $request['dismissed'] !== true ) {
+ if ( ! isset( $request['dismissed'] ) || true !== $request['dismissed'] ) {
return new WP_Error( 'invalid_param', esc_html__( 'Invalid parameter "dismissed".', 'jetpack' ), array( 'status' => 404 ) );
}
@@ -1332,7 +1206,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_jetpack_disconnect', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_jetpack_disconnect',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
@@ -1348,7 +1226,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_jetpack_connect', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_jetpack_connect',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
@@ -1366,7 +1248,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_unlink_user', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_unlink_user',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1381,7 +1267,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_manage_modules', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_manage_modules',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1396,7 +1286,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_configure_modules', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_configure_modules',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1411,7 +1305,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_view_admin', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_view_admin',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1426,7 +1324,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_manage_settings', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_manage_settings',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1441,7 +1343,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_activate_plugins', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_activate_plugins',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1454,7 +1360,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_user_permission_edit_others_posts', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_user_permission_edit_others_posts',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1471,22 +1381,11 @@ class Jetpack_Core_Json_Api_Endpoints {
return true;
}
- return new WP_Error( 'invalid_permission_manage_purchase_token', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
- }
-
- /**
- * Verify that user can view and update user-licensing data.
- *
- * @return bool Whether the user is currently connected and they are the connection owner.
- */
- public static function user_licensing_permission_check() {
- $connection_manager = new Connection_Manager( 'jetpack' );
-
- if ( $connection_manager->is_user_connected() && $connection_manager->is_connection_owner() ) {
- return true;
- }
-
- return new WP_Error( 'invalid_permission_manage_user_licenses', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
+ return new WP_Error(
+ 'invalid_permission_manage_purchase_token',
+ REST_Connector::get_user_permissions_error_msg(),
+ array( 'status' => rest_authorization_required_code() )
+ );
}
/**
@@ -1520,16 +1419,17 @@ class Jetpack_Core_Json_Api_Endpoints {
* @return bool
*/
public static function view_jetpack_connection_test_check() {
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended -- This is verifying the trusted caller via a shared private key and timestamp.
if ( ! isset( $_GET['signature'], $_GET['timestamp'], $_GET['url'] ) ) {
return false;
}
- $signature = base64_decode( $_GET['signature'] );
+ $signature = base64_decode( wp_unslash( $_GET['signature'] ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$signature_data = wp_json_encode(
array(
- 'rest_route' => $_GET['rest_route'],
- 'timestamp' => (int) $_GET['timestamp'],
- 'url' => wp_unslash( $_GET['url'] ),
+ 'rest_route' => isset( $_GET['rest_route'] ) ? filter_var( wp_unslash( $_GET['rest_route'] ) ) : null,
+ 'timestamp' => (int) $_GET['timestamp'],
+ 'url' => esc_url_raw( wp_unslash( $_GET['url'] ) ),
)
);
@@ -1544,11 +1444,13 @@ class Jetpack_Core_Json_Api_Endpoints {
return false;
}
- // signature timestamp must be within 5min of current time
+ // signature timestamp must be within 5min of current time.
if ( abs( time() - (int) $_GET['timestamp'] ) > 300 ) {
return false;
}
+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
+
return true;
}
@@ -1617,6 +1519,9 @@ class Jetpack_Core_Json_Api_Endpoints {
);
}
+ /**
+ * Fetch information about the Rewind status of the site.
+ */
public static function rewind_data() {
$site_id = Jetpack_Options::get_option( 'id' );
@@ -1778,7 +1683,7 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function disconnect_site( $request ) {
_deprecated_function( __METHOD__, 'jetpack-10.0.0', '\Automattic\Jetpack\Connection\REST_Connector::disconnect_site' );
- if ( ! isset( $request['isActive'] ) || $request['isActive'] !== false ) {
+ if ( ! isset( $request['isActive'] ) || false !== $request['isActive'] ) {
return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) );
}
@@ -1818,7 +1723,7 @@ class Jetpack_Core_Json_Api_Endpoints {
return rest_ensure_response(
array(
- 'authorizeUrl' => Jetpack::build_authorize_url( false, true ),
+ 'authorizeUrl' => Jetpack::build_authorize_url( false ),
)
);
}
@@ -1884,7 +1789,7 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function unlink_user( $request ) {
- if ( ! isset( $request['linked'] ) || $request['linked'] !== false ) {
+ if ( ! isset( $request['linked'] ) || false !== $request['linked'] ) {
return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) );
}
@@ -1908,7 +1813,7 @@ class Jetpack_Core_Json_Api_Endpoints {
*
* @return WP_REST_Response|WP_Error Response, else error.
*/
- public static function get_user_tracking_settings( $request ) {
+ public static function get_user_tracking_settings( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( ! ( new Connection_Manager( 'jetpack' ) )->is_user_connected() ) {
$response = array(
'tracks_opt_out' => true, // Default to opt-out if not connected to wp.com.
@@ -1920,7 +1825,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
)
);
@@ -1954,7 +1859,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'method' => 'PUT',
'headers' => array(
'Content-Type' => 'application/json',
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
),
wp_json_encode( $request->get_params() )
@@ -1985,7 +1890,7 @@ class Jetpack_Core_Json_Api_Endpoints {
// Allow use a store sandbox. Internal ref: PCYsg-IA-p2.
if ( isset( $_COOKIE ) && isset( $_COOKIE['store_sandbox'] ) ) {
- $secret = $_COOKIE['store_sandbox'];
+ $secret = filter_var( wp_unslash( $_COOKIE['store_sandbox'] ) );
$args['headers']['Cookie'] = "store_sandbox=$secret;";
}
@@ -2032,7 +1937,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'code' => 'success',
'message' => esc_html__( 'Site data correctly received.', 'jetpack' ),
- 'data' => json_encode( $site_data ),
+ 'data' => wp_json_encode( $site_data ),
)
);
}
@@ -2081,7 +1986,7 @@ class Jetpack_Core_Json_Api_Endpoints {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
),
),
null,
@@ -2103,7 +2008,7 @@ class Jetpack_Core_Json_Api_Endpoints {
return new WP_Error(
'activity_not_found',
esc_html__( 'No activity found', 'jetpack' ),
- array( 'status' => 204 ) // no content
+ array( 'status' => 204 ) // no content.
);
}
@@ -2116,6 +2021,62 @@ class Jetpack_Core_Json_Api_Endpoints {
}
/**
+ * Fetch the discount for this site and return it.
+ *
+ * @since 10.8
+ *
+ * @return array|WP_Error
+ */
+ public static function get_site_discount() {
+ $site_id = Jetpack_Options::get_option( 'id' );
+
+ if ( ! $site_id ) {
+ return new WP_Error(
+ 'site_id_missing',
+ esc_html__( 'Site ID is missing.', 'jetpack' ),
+ array( 'status' => 400 )
+ );
+ }
+
+ $response = Client::wpcom_json_api_request_as_user(
+ "/sites/$site_id/discount",
+ '2',
+ array(
+ 'method' => 'GET',
+ 'headers' => array(
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
+ ),
+ )
+ );
+
+ $response_code = wp_remote_retrieve_response_code( $response );
+ $data = json_decode( wp_remote_retrieve_body( $response ) );
+
+ if ( 200 !== $response_code ) {
+ return new WP_Error(
+ 'discount_fetch_failed',
+ is_object( $data ) && property_exists( $data, 'error' ) ? $data->error : esc_html__( 'Could not retrieve site discount.', 'jetpack' ),
+ array( 'status' => $response_code )
+ );
+ }
+
+ if ( ! isset( $data ) ) {
+ return new WP_Error(
+ 'discount_parse_error',
+ esc_html__( 'Could not parse discount', 'jetpack' ),
+ array( 'status' => 204 ) // no content.
+ );
+ }
+
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'data' => $data,
+ )
+ );
+ }
+
+ /**
* Reset Jetpack options
*
* @since 4.3.0
@@ -2130,18 +2091,19 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function reset_jetpack_options( $request ) {
- if ( ! isset( $request['reset'] ) || $request['reset'] !== true ) {
+ if ( ! isset( $request['reset'] ) || true !== $request['reset'] ) {
return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) );
}
if ( isset( $request['options'] ) ) {
- $data = $request['options'];
+ $data = $request['options'];
+ $message = '';
switch ( $data ) {
case ( 'options' ):
$options_to_reset = Jetpack::get_jetpack_options_for_reset();
- // Reset the Jetpack options
+ // Reset the Jetpack options.
foreach ( $options_to_reset['jp_options'] as $option_to_reset ) {
Jetpack_Options::delete_option( $option_to_reset );
}
@@ -2150,32 +2112,28 @@ class Jetpack_Core_Json_Api_Endpoints {
delete_option( $option_to_reset );
}
- // Reset to default modules
+ // Reset to default modules.
$default_modules = Jetpack::get_default_modules();
Jetpack::update_active_modules( $default_modules );
+ $message = esc_html__( 'Jetpack options reset.', 'jetpack' );
- return rest_ensure_response(
- array(
- 'code' => 'success',
- 'message' => esc_html__( 'Jetpack options reset.', 'jetpack' ),
- )
- );
break;
-
case 'modules':
$default_modules = Jetpack::get_default_modules();
Jetpack::update_active_modules( $default_modules );
- return rest_ensure_response(
- array(
- 'code' => 'success',
- 'message' => esc_html__( 'Modules reset to default.', 'jetpack' ),
- )
- );
- break;
+ $message = esc_html__( 'Modules reset to default.', 'jetpack' );
+ break;
default:
return new WP_Error( 'invalid_param', esc_html__( 'Invalid Parameter', 'jetpack' ), array( 'status' => 404 ) );
}
+
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => $message,
+ )
+ );
}
return new WP_Error( 'required_param', esc_html__( 'Missing parameter "type".', 'jetpack' ), array( 'status' => 404 ) );
@@ -2217,6 +2175,14 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function get_updateable_data_list( $selector = '' ) {
$options = array(
+ // Blocks.
+ 'jetpack_blocks_disabled' => array(
+ 'description' => esc_html__( 'Jetpack Blocks disabled.', 'jetpack' ),
+ 'type' => 'boolean',
+ 'default' => false,
+ 'validate_callback' => __CLASS__ . '::validate_boolean',
+ 'jp_group' => 'settings',
+ ),
// Carousel
'carousel_background_color' => array(
@@ -2257,7 +2223,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'carousel',
),
- // Comments
+ // Comments.
'highlander_comment_form_prompt' => array(
'description' => esc_html__( 'Greeting Text', 'jetpack' ),
'type' => 'string',
@@ -2283,7 +2249,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'comments',
),
- // Custom Content Types
+ // Custom Content Types.
'jetpack_portfolio' => array(
'description' => esc_html__( 'Enable or disable Jetpack portfolio post type.', 'jetpack' ),
'type' => 'boolean',
@@ -2313,7 +2279,38 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'custom-content-types',
),
- // Galleries
+ // WAF.
+ 'jetpack_waf_ip_list' => array(
+ 'description' => esc_html__( 'Allow / Block list - Block or allow a specific request IP.', 'jetpack' ),
+ 'type' => 'boolean',
+ 'default' => 0,
+ 'validate_callback' => __CLASS__ . '::validate_boolean',
+ 'jp_group' => 'waf',
+ ),
+ 'jetpack_waf_ip_block_list' => array(
+ 'description' => esc_html__( 'Blocked IP addresses', 'jetpack' ),
+ 'type' => 'string',
+ 'default' => '',
+ 'validate_callback' => __CLASS__ . '::validate_string',
+ 'sanitize_callback' => 'esc_textarea',
+ 'jp_group' => 'waf',
+ ),
+ 'jetpack_waf_ip_allow_list' => array(
+ 'description' => esc_html__( 'Always allowed IP addresses', 'jetpack' ),
+ 'type' => 'string',
+ 'default' => '',
+ 'validate_callback' => __CLASS__ . '::validate_string',
+ 'sanitize_callback' => 'esc_textarea',
+ 'jp_group' => 'waf',
+ ),
+ 'jetpack_waf_share_data' => array(
+ 'description' => esc_html__( 'Share data with Jetpack.', 'jetpack' ),
+ 'type' => 'boolean',
+ 'default' => 0,
+ 'validate_callback' => __CLASS__ . '::validate_boolean',
+ 'jp_group' => 'waf',
+ ),
+ // Galleries.
'tiled_galleries' => array(
'description' => esc_html__( 'Display all your gallery pictures in a cool mosaic.', 'jetpack' ),
'type' => 'boolean',
@@ -2339,7 +2336,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'gravatar-hovercards',
),
- // Infinite Scroll
+ // Infinite Scroll.
'infinite_scroll' => array(
'description' => esc_html__( 'To infinity and beyond', 'jetpack' ),
'type' => 'boolean',
@@ -2355,7 +2352,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'infinite-scroll',
),
- // Likes
+ // Likes.
'wpl_default' => array(
'description' => esc_html__( 'WordPress.com Likes are', 'jetpack' ),
'type' => 'string',
@@ -2379,7 +2376,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'likes',
),
- // Markdown
+ // Markdown.
'wpcom_publish_comments_with_markdown' => array(
'description' => esc_html__( 'Use Markdown for comments.', 'jetpack' ),
'type' => 'boolean',
@@ -2395,7 +2392,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'markdown',
),
- // Monitor
+ // Monitor.
'monitor_receive_notifications' => array(
'description' => esc_html__( 'Receive Monitor Email Notifications.', 'jetpack' ),
'type' => 'boolean',
@@ -2404,7 +2401,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'monitor',
),
- // Post by Email
+ // Post by Email.
'post_by_email_address' => array(
'description' => esc_html__( 'Email Address', 'jetpack' ),
'type' => 'string',
@@ -2425,7 +2422,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'post-by-email',
),
- // Protect
+ // Protect.
'jetpack_protect_key' => array(
'description' => esc_html__( 'Protect API key', 'jetpack' ),
'type' => 'string',
@@ -2442,7 +2439,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'protect',
),
- // Sharing
+ // Sharing.
'sharing_services' => array(
'description' => esc_html__( 'Enabled Services and those hidden behind a button', 'jetpack' ),
'type' => 'object',
@@ -2525,7 +2522,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'sharedaddy',
),
- // SSO
+ // SSO.
'jetpack_sso_require_two_step' => array(
'description' => esc_html__( 'Require Two-Step Authentication', 'jetpack' ),
'type' => 'boolean',
@@ -2541,7 +2538,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'sso',
),
- // Subscriptions
+ // Subscriptions.
'stb_enabled' => array(
'description' => esc_html__( "Show a <em>'follow blog'</em> option in the comment form", 'jetpack' ),
'type' => 'boolean',
@@ -2564,7 +2561,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'subscriptions',
),
- // Related Posts
+ // Related Posts.
'show_headline' => array(
'description' => esc_html__( 'Highlight related content with a heading', 'jetpack' ),
'type' => 'boolean',
@@ -2605,7 +2602,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'search',
),
- // Verification Tools
+ // Verification Tools.
'google' => array(
'description' => esc_html__( 'Google Search Console', 'jetpack' ),
'type' => 'string',
@@ -2723,7 +2720,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'wordads',
),
- // Google Analytics
+ // Google Analytics.
'google_analytics_tracking_id' => array(
'description' => esc_html__( 'Google Analytics', 'jetpack' ),
'type' => 'string',
@@ -2732,7 +2729,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'google-analytics',
),
- // Stats
+ // Stats.
'admin_bar' => array(
'description' => esc_html__( 'Include a small chart in your admin bar with a 48-hour traffic snapshot.', 'jetpack' ),
'type' => 'boolean',
@@ -2807,7 +2804,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'settings',
),
- // Apps card on dashboard
+ // Apps card on dashboard.
'dismiss_dash_app_card' => array(
'description' => '',
'type' => 'boolean',
@@ -2816,7 +2813,7 @@ class Jetpack_Core_Json_Api_Endpoints {
'jp_group' => 'settings',
),
- // Empty stats card dismiss
+ // Empty stats card dismiss.
'dismiss_empty_stats_card' => array(
'description' => '',
'type' => 'boolean',
@@ -2878,9 +2875,18 @@ class Jetpack_Core_Json_Api_Endpoints {
'sanitize_callback' => 'Jetpack_SEO_Titles::sanitize_title_formats',
),
+ // VideoPress.
+ 'videopress_private_enabled_for_site' => array(
+ 'description' => esc_html__( 'Video Privacy: Restrict views to members of this site', 'jetpack' ),
+ 'type' => 'boolean',
+ 'default' => 0,
+ 'validate_callback' => __CLASS__ . '::validate_boolean',
+ 'jp_group' => 'videopress',
+ ),
+
);
- // Add modules to list so they can be toggled
+ // Add modules to list so they can be toggled.
$modules = Jetpack::get_available_modules();
if ( is_array( $modules ) && ! empty( $modules ) ) {
$module_args = array(
@@ -2897,13 +2903,13 @@ class Jetpack_Core_Json_Api_Endpoints {
if ( is_array( $selector ) ) {
- // Return only those options whose keys match $selector keys
+ // Return only those options whose keys match $selector keys.
return array_intersect_key( $options, $selector );
}
if ( 'any' === $selector ) {
- // Toggle module or update any module option or any general setting
+ // Toggle module or update any module option or any general setting.
return $options;
}
@@ -2966,7 +2972,14 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function validate_boolean( $value, $request, $param ) {
// phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- Other code depends on loose comparison here.
if ( ! is_bool( $value ) && ! ( ctype_digit( (string) $value ) && in_array( $value, array( 0, 1 ) ) ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be true, false, 0 or 1.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be true, false, 0 or 1.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -2984,7 +2997,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_posint( $value, $request, $param ) {
if ( ! is_numeric( $value ) || $value <= 0 ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a positive integer.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be a positive integer.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3025,14 +3045,23 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function validate_list_item( $value, $request, $param ) {
$attributes = $request->get_attributes();
if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s not recognized', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s not recognized', 'jetpack' ),
+ $param
+ )
+ );
}
$args = $attributes['args'][ $param ];
if ( ! empty( $args['enum'] ) ) {
-
// If it's an associative array, use the keys to check that the value is among those admitted.
- $enum = ( count( array_filter( array_keys( $args['enum'] ), 'is_string' ) ) > 0 ) ? array_keys( $args['enum'] ) : $args['enum'];
- if ( ! in_array( $value, $enum ) ) {
+ $enum = ( count( array_filter( array_keys( $args['enum'] ), 'is_string' ) ) > 0 )
+ ? array_keys( $args['enum'] )
+ : $args['enum'];
+ $enum = array_map( 'strval', $enum );
+ if ( ! in_array( $value, $enum, true ) ) {
return new WP_Error(
'invalid_param_value',
sprintf(
@@ -3060,13 +3089,27 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_module_list( $value, $request, $param ) {
if ( ! is_array( $value ) ) {
- return new WP_Error( 'invalid_param_value', sprintf( esc_html__( '%s must be an array', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param_value',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be an array', 'jetpack' ),
+ $param
+ )
+ );
}
$modules = Jetpack::get_available_modules();
- if ( count( array_intersect( $value, $modules ) ) != count( $value ) ) {
- return new WP_Error( 'invalid_param_value', sprintf( esc_html__( '%s must be a list of valid modules', 'jetpack' ), $param ) );
+ if ( count( array_intersect( $value, $modules ) ) !== count( $value ) ) {
+ return new WP_Error(
+ 'invalid_param_value',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be a list of valid modules', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
@@ -3085,7 +3128,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_alphanum( $value, $request, $param ) {
if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/^[a-z0-9]+$/i', $value ) ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an alphanumeric string.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be an alphanumeric string.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3095,15 +3145,22 @@ class Jetpack_Core_Json_Api_Endpoints {
*
* @since 4.6.0
*
- * @param string $value Value to check.
- * @param WP_REST_Request $request
- * @param string $param Name of the parameter passed to endpoint holding $value.
+ * @param string $value Value to check.
+ * @param WP_REST_Request $request The request sent to the WP REST API.
+ * @param string $param Name of the parameter passed to endpoint holding $value.
*
* @return bool|WP_Error
*/
public static function validate_verification_service( $value, $request, $param ) {
if ( ! empty( $value ) && ! ( is_string( $value ) && ( preg_match( '/^[a-z0-9_-]+$/i', $value ) || jetpack_verification_get_code( $value ) !== false ) ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an alphanumeric string or a verification tag.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a verification string used to verify a service like Google Webmaster Console. */
+ esc_html__( '%s must be an alphanumeric string or a verification tag.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3124,7 +3181,7 @@ class Jetpack_Core_Json_Api_Endpoints {
return new WP_Error(
'invalid_param',
sprintf(
- /* 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. */
+ /* 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. */
esc_html__( '%1$s must be %2$s.', 'jetpack' ),
$param,
join( ', ', self::$stats_roles )
@@ -3148,13 +3205,20 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function validate_sharing_show( $value, $request, $param ) {
$views = array( 'index', 'post', 'page', 'attachment', 'jetpack-portfolio' );
if ( ! is_array( $value ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array of post types.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be an array of post types.', 'jetpack' ),
+ $param
+ )
+ );
}
if ( ! array_intersect( $views, $value ) ) {
return new WP_Error(
'invalid_param',
sprintf(
- /* 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 */
+ /* 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 */
esc_html__( '%1$s must be %2$s.', 'jetpack' ),
$param,
join( ', ', $views )
@@ -3182,7 +3246,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_services( $value, $request, $param ) {
if ( ! is_array( $value ) || ! isset( $value['visible'] ) || ! isset( $value['hidden'] ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array with visible and hidden items.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be an array with visible and hidden items.', 'jetpack' ),
+ $param
+ )
+ );
}
// Allow to clear everything.
@@ -3203,7 +3274,7 @@ class Jetpack_Core_Json_Api_Endpoints {
return new WP_Error(
'invalid_param',
sprintf(
- /* Translators: placeholder 1 is a parameter holding the services passed to endpoint, placeholder 2 is a list of all Jetpack Sharing services */
+ /* Translators: placeholder 1 is a parameter holding the services passed to endpoint, placeholder 2 is a list of all Jetpack Sharing services */
esc_html__( '%1$s visible and hidden items must be a list of %2$s.', 'jetpack' ),
$param,
join( ', ', $services )
@@ -3226,7 +3297,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_custom_service( $value, $request, $param ) {
if ( ! is_array( $value ) || ! isset( $value['sharing_name'] ) || ! isset( $value['sharing_url'] ) || ! isset( $value['sharing_icon'] ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an array with sharing name, url and icon.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be an array with sharing name, url and icon.', 'jetpack' ),
+ $param
+ )
+ );
}
// Allow to clear everything.
@@ -3241,7 +3319,14 @@ class Jetpack_Core_Json_Api_Endpoints {
if ( ( ! empty( $value['sharing_name'] ) && ! is_string( $value['sharing_name'] ) )
|| ( ! empty( $value['sharing_url'] ) && ! is_string( $value['sharing_url'] ) )
|| ( ! empty( $value['sharing_icon'] ) && ! is_string( $value['sharing_icon'] ) ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s needs sharing name, url and icon.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s needs sharing name, url and icon.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3259,17 +3344,31 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_custom_service_id( $value, $request, $param ) {
if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/custom\-[0-1]+/i', $value ) ) ) {
- 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 ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( "%s must be a string prefixed with 'custom-' and followed by a numeric ID.", 'jetpack' ),
+ $param
+ )
+ );
}
if ( ! class_exists( 'Sharing_Service' ) && ! include_once JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) {
return new WP_Error( 'invalid_param', esc_html__( 'Failed loading required dependency Sharing_Service.', 'jetpack' ) );
}
$sharer = new Sharing_Service();
- $services = array_keys( $sharer->get_all_services() );
+ $services = $sharer->get_all_services();
- if ( ! empty( $value ) && ! in_array( $value, $services ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s is not a registered custom sharing service.', 'jetpack' ), $param ) );
+ if ( ! empty( $value ) && ! isset( $services[ $value ] ) ) {
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s is not a registered custom sharing service.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
@@ -3280,15 +3379,22 @@ class Jetpack_Core_Json_Api_Endpoints {
*
* @since 4.3.0
*
- * @param string $value Value to check.
- * @param WP_REST_Request $request
- * @param string $param Name of the parameter passed to endpoint holding $value.
+ * @param string $value Value to check.
+ * @param WP_REST_Request $request The request sent to the WP REST API.
+ * @param string $param Name of the parameter passed to endpoint holding $value.
*
* @return bool|WP_Error
*/
public static function validate_twitter_username( $value, $request, $param ) {
if ( ! empty( $value ) && ( ! is_string( $value ) || ! preg_match( '/^@?\w{1,15}$/i', $value ) ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a Twitter username.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a twitter name. */
+ esc_html__( '%s must be a Twitter username.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3306,7 +3412,14 @@ class Jetpack_Core_Json_Api_Endpoints {
*/
public static function validate_string( $value, $request, $param ) {
if ( ! is_string( $value ) ) {
- return new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be a string.', 'jetpack' ), $param ) );
+ return new WP_Error(
+ 'invalid_param',
+ sprintf(
+ /* Translators: Placeholder is a parameter name. */
+ esc_html__( '%s must be a string.', 'jetpack' ),
+ $param
+ )
+ );
}
return true;
}
@@ -3399,12 +3512,12 @@ class Jetpack_Core_Json_Api_Endpoints {
$news_sitemap_url = home_url( $location . '/?jetpack-sitemap=news-sitemap.xml' );
}
- if ( is_null( $slug ) && isset( $modules['sitemaps'] ) ) {
- // Is a list of modules
+ if ( $slug === null && isset( $modules['sitemaps'] ) ) {
+ // Is a list of modules.
$modules['sitemaps']['extra']['sitemap_url'] = $sitemap_url;
$modules['sitemaps']['extra']['news_sitemap_url'] = $news_sitemap_url;
- } elseif ( 'sitemaps' == $slug ) {
- // It's a single module
+ } elseif ( 'sitemaps' === $slug ) {
+ // It's a single module.
$modules['extra']['sitemap_url'] = $sitemap_url;
$modules['extra']['news_sitemap_url'] = $news_sitemap_url;
}
@@ -3432,17 +3545,17 @@ class Jetpack_Core_Json_Api_Endpoints {
switch ( $module ) {
case 'monitor':
- // Status of user notifications
+ // 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
+ // 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
+ // Protect.
$options['jetpack_protect_key']['current_value'] = get_site_option( 'jetpack_protect_key', false );
if ( ! function_exists( 'jetpack_protect_format_whitelist' ) ) {
include_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php';
@@ -3464,7 +3577,7 @@ class Jetpack_Core_Json_Api_Endpoints {
$wga = get_option( 'jetpack_wga' );
$code = '';
if ( is_array( $wga ) && array_key_exists( 'code', $wga ) ) {
- $code = $wga[ 'code' ];
+ $code = $wga['code'];
}
$options['google_analytics_tracking_id']['current_value'] = $code;
break;
@@ -3503,7 +3616,7 @@ class Jetpack_Core_Json_Api_Endpoints {
// At this point some options have current_value not set because they're options
// that only get written on update, so we set current_value to the default one.
foreach ( $options as $key => $value ) {
- // We don't need validate_callback in the response
+ // We don't need validate_callback in the response.
if ( isset( $options[ $key ]['validate_callback'] ) ) {
unset( $options[ $key ]['validate_callback'] );
}
@@ -3549,7 +3662,7 @@ class Jetpack_Core_Json_Api_Endpoints {
* @return bool|float|int|string
*/
public static function cast_value( $value, $definition ) {
- if ( $value === 'NULL' ) {
+ if ( 'NULL' === $value ) {
return null;
}
@@ -3561,19 +3674,19 @@ class Jetpack_Core_Json_Api_Endpoints {
} elseif ( 'false' === $value || 'off' === $value ) {
return false;
}
- return (bool) $value;
+ $value = (bool) $value;
break;
case 'integer':
- return (int) $value;
+ $value = (int) $value;
break;
case 'float':
- return (float) $value;
+ $value = (float) $value;
break;
case 'string':
- return (string) $value;
+ $value = (string) $value;
break;
}
}
@@ -3625,14 +3738,14 @@ class Jetpack_Core_Json_Api_Endpoints {
return false;
}
$value = Jetpack_Post_By_Email::init()->get_post_by_email_address();
- if ( $value === null ) {
- $value = 'NULL'; // sentinel value so it actually gets set
+ if ( null === $value ) {
+ $value = 'NULL'; // sentinel value so it actually gets set.
}
break;
}
// Normalize value to boolean.
- if ( is_wp_error( $value ) || is_null( $value ) ) {
+ if ( is_wp_error( $value ) || $value === null ) {
$value = false;
}
@@ -3653,7 +3766,7 @@ class Jetpack_Core_Json_Api_Endpoints {
$updates = wp_get_update_data();
if ( isset( $updates['counts'] ) && isset( $updates['counts']['plugins'] ) ) {
$count = $updates['counts']['plugins'];
- if ( 0 == $count ) {
+ if ( 0 === $count ) {
$response = array(
'code' => 'success',
'message' => esc_html__( 'All plugins are up-to-date. Keep up the good work!', 'jetpack' ),
@@ -3662,7 +3775,13 @@ class Jetpack_Core_Json_Api_Endpoints {
} else {
$response = array(
'code' => 'updates-available',
- 'message' => esc_html( sprintf( _n( '%s plugin need updating.', '%s plugins need updating.', $count, 'jetpack' ), $count ) ),
+ 'message' => esc_html(
+ sprintf(
+ /* Translators: placeholders are numbers. */
+ _n( '%s plugin needs updating.', '%s plugins need updating.', $count, 'jetpack' ),
+ $count
+ )
+ ),
'count' => $count,
);
}
@@ -3680,8 +3799,7 @@ class Jetpack_Core_Json_Api_Endpoints {
* @return WP_REST_Response|WP_Error List of plugins in the site. Otherwise, a WP_Error instance with the corresponding error.
*/
public static function get_plugins() {
- jetpack_require_lib( 'plugins' );
- $plugins = Jetpack_Plugins::get_plugins();
+ $plugins = Plugins_Installer::get_plugins();
if ( ! empty( $plugins ) ) {
return rest_ensure_response( $plugins );
@@ -3708,14 +3826,12 @@ class Jetpack_Core_Json_Api_Endpoints {
public static function install_plugin( $request ) {
$plugin = stripslashes( $request['slug'] );
- jetpack_require_lib( 'plugins' );
-
// Let's make sure the plugin isn't already installed.
- $plugin_id = Jetpack_Plugins::get_plugin_id_by_slug( $plugin );
+ $plugin_id = Plugins_Installer::get_plugin_id_by_slug( $plugin );
// If not installed, let's install now.
if ( ! $plugin_id ) {
- $result = Jetpack_Plugins::install_plugin( $plugin );
+ $result = Plugins_Installer::install_plugin( $plugin );
if ( is_wp_error( $result ) ) {
return new WP_Error(
@@ -3756,7 +3872,7 @@ class Jetpack_Core_Json_Api_Endpoints {
* Let's check again for the plugin's ID if we don't already have it.
*/
if ( ! $plugin_id ) {
- $plugin_id = Jetpack_Plugins::get_plugin_id_by_slug( $plugin );
+ $plugin_id = Plugins_Installer::get_plugin_id_by_slug( $plugin );
if ( ! $plugin_id ) {
return new WP_Error(
'unable_to_determine_installed_plugin',
@@ -3803,8 +3919,7 @@ class Jetpack_Core_Json_Api_Endpoints {
);
}
- jetpack_require_lib( 'plugins' );
- $plugins = Jetpack_Plugins::get_plugins();
+ $plugins = Plugins_Installer::get_plugins();
if ( empty( $plugins ) ) {
return new WP_Error( 'no_plugins_found', esc_html__( 'This site has no plugins.', 'jetpack' ), array( 'status' => 404 ) );
@@ -3817,7 +3932,7 @@ class Jetpack_Core_Json_Api_Endpoints {
$plugin = $request['plugin'] . '.php';
// Is the plugin installed?
- if ( ! in_array( $plugin, array_keys( $plugins ), true ) ) {
+ if ( ! array_key_exists( $plugin, $plugins ) ) {
return new WP_Error(
'plugin_not_found',
esc_html(
@@ -3832,7 +3947,7 @@ class Jetpack_Core_Json_Api_Endpoints {
}
// Is the plugin active already?
- $status = Jetpack_Plugins::get_plugin_status( $plugin );
+ $status = Plugins_Installer::get_plugin_status( $plugin );
if ( in_array( $status, array( 'active', 'network-active' ), true ) ) {
return new WP_Error(
'plugin_already_active',
@@ -3903,8 +4018,7 @@ class Jetpack_Core_Json_Api_Endpoints {
* @return bool|WP_Error True if module was activated. Otherwise, a WP_Error instance with the corresponding error.
*/
public static function get_plugin( $request ) {
- jetpack_require_lib( 'plugins' );
- $plugins = Jetpack_Plugins::get_plugins();
+ $plugins = Plugins_Installer::get_plugins();
if ( empty( $plugins ) ) {
return new WP_Error( 'no_plugins_found', esc_html__( 'This site has no plugins.', 'jetpack' ), array( 'status' => 404 ) );
@@ -3912,13 +4026,23 @@ class Jetpack_Core_Json_Api_Endpoints {
$plugin = stripslashes( $request['plugin'] );
- if ( ! in_array( $plugin, array_keys( $plugins ) ) ) {
- return new WP_Error( 'plugin_not_found', esc_html( sprintf( __( 'Plugin %s is not installed.', 'jetpack' ), $plugin ) ), array( 'status' => 404 ) );
+ if ( ! array_key_exists( $plugin, $plugins ) ) {
+ return new WP_Error(
+ 'plugin_not_found',
+ esc_html(
+ sprintf(
+ /* Translators: placeholder is a plugin name. */
+ __( 'Plugin %s is not installed.', 'jetpack' ),
+ $plugin
+ )
+ ),
+ array( 'status' => 404 )
+ );
}
$plugin_data = $plugins[ $plugin ];
- $plugin_data['active'] = in_array( Jetpack_Plugins::get_plugin_status( $plugin ), array( 'active', 'network-active' ), true );
+ $plugin_data['active'] = in_array( Plugins_Installer::get_plugin_status( $plugin ), array( 'active', 'network-active' ), true );
return rest_ensure_response(
array(
@@ -3936,7 +4060,7 @@ class Jetpack_Core_Json_Api_Endpoints {
* @param WP_REST_REQUEST $request The request parameters.
* @return bool|WP_Error
*/
- public static function send_mobile_magic_link( $request ) {
+ public static function send_mobile_magic_link( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$xml = new Jetpack_IXR_Client(
array(
'user_id' => get_current_user_id(),
@@ -3955,8 +4079,6 @@ class Jetpack_Core_Json_Api_Endpoints {
);
}
- $response = $xml->getResponse();
-
return rest_ensure_response(
array(
'code' => 'success',
@@ -3965,74 +4087,6 @@ class Jetpack_Core_Json_Api_Endpoints {
}
/**
- * Get the last licensing error message, if any.
- *
- * @since 9.0.0
- *
- * @return string Licensing error message or empty string.
- */
- public static function get_licensing_error() {
- return Licensing::instance()->last_error();
- }
-
- /**
- * Update the last licensing error message.
- *
- * @since 9.0.0
- *
- * @param WP_REST_Request $request The request.
- *
- * @return bool true.
- */
- public static function update_licensing_error( $request ) {
- Licensing::instance()->log_error( $request['error'] );
-
- return true;
- }
-
- /**
- * Set a Jetpack license
- *
- * @since 9.6.0
- *
- * @param WP_REST_Request $request The request.
- *
- * @return WP_REST_Response|WP_Error A response object if the option was successfully updated, or a WP_Error if it failed.
- */
- public static function set_jetpack_license( $request ) {
- $license = trim( sanitize_text_field( $request['license'] ) );
-
- if ( Licensing::instance()->append_license( $license ) ) {
- return rest_ensure_response( array( 'code' => 'success' ) );
- }
-
- return new WP_Error(
- 'setting_license_key_failed',
- esc_html__( 'Could not set this license key. Please try again.', 'jetpack' ),
- array( 'status' => 500 )
- );
- }
-
- /**
- * Attach Jetpack licenses
- *
- * @since 10.4.0
- *
- * @param WP_REST_Request $request The request.
- *
- * @return WP_REST_Response|WP_Error A response object
- */
- public static function attach_jetpack_licenses( $request ) {
- $licenses = array_map(
- function ( $license ) {
- return trim( sanitize_text_field( $license ) );
- },
- $request['licenses']
- );
- return rest_ensure_response( Licensing::instance()->attach_licenses( $licenses ) );
- }
-
- /**
* Returns the Jetpack CRM data.
*
* @return WP_REST_Response A response object containing the Jetpack CRM data.
@@ -4074,7 +4128,7 @@ class Jetpack_Core_Json_Api_Endpoints {
return new WP_Error(
'invalid_user_permission_jetpack_crm_data',
- self::$user_permissions_error_msg,
+ REST_Connector::get_user_permissions_error_msg(),
array( 'status' => rest_authorization_required_code() )
);
}
@@ -4091,38 +4145,79 @@ class Jetpack_Core_Json_Api_Endpoints {
return new WP_Error(
'invalid_user_permission_activate_jetpack_crm_ext',
- self::$user_permissions_error_msg,
+ REST_Connector::get_user_permissions_error_msg(),
array( 'status' => rest_authorization_required_code() )
);
}
/**
- * Verify that the user can set a Jetpack license key
+ * Set hasSeenWCConnectionModal to true when the site has displayed it
*
- * @since 9.5.0
+ * @since 10.4.0
*
- * @return bool|WP_Error True if user is able to set a Jetpack license key
+ * @return bool
*/
- public static function set_jetpack_license_key_permission_check() {
- if ( Licensing::instance()->is_licensing_input_enabled() ) {
- return true;
- }
-
- return new WP_Error( 'invalid_user_permission_set_jetpack_license_key', self::$user_permissions_error_msg, array( 'status' => rest_authorization_required_code() ) );
+ public static function set_has_seen_wc_connection_modal() {
+ $updated_option = Jetpack_Options::update_option( 'has_seen_wc_connection_modal', true );
+ return rest_ensure_response( array( 'success' => $updated_option ) );
}
/**
- * Set hasSeenWCConnectionModal to true when the site has displayed it
+ * Fetch introdution offers.
*
- * @since 10.4.0
+ * @since 10.9
*
- * @return bool
+ * @return array|WP_Error
*/
- public static function set_has_seen_wc_connection_modal() {
- $updated_option = Jetpack_Options::update_option( 'has_seen_wc_connection_modal', true );
+ public static function get_intro_offers() {
+ $site_id = Jetpack_Options::get_option( 'id' );
- return rest_ensure_response( array( 'success' => $updated_option ) );
+ if ( ! $site_id ) {
+ return new WP_Error(
+ 'site_id_missing',
+ esc_html__( 'Site ID is missing.', 'jetpack' ),
+ array( 'status' => 400 )
+ );
+ }
+
+ $response = Client::wpcom_json_api_request_as_user(
+ '/introductory-offers',
+ '2',
+ array(
+ 'method' => 'GET',
+ 'headers' => array(
+ 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ),
+ ),
+ )
+ );
+
+ $response_code = wp_remote_retrieve_response_code( $response );
+
+ if ( 200 !== $response_code ) {
+ return new WP_Error(
+ 'intro_offers_fetch_failed',
+ esc_html__( 'Could not retrieve intro offers.', 'jetpack' ),
+ array( 'status' => $response_code )
+ );
+ }
+
+ $data = json_decode( wp_remote_retrieve_body( $response ) );
+
+ if ( ! isset( $data ) ) {
+ return new WP_Error(
+ 'intro_offers_error',
+ esc_html__( 'Could not parse intro offers.', 'jetpack' ),
+ array( 'status' => 204 ) // no content.
+ );
+ }
+
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'data' => $data,
+ )
+ );
}
} // class end
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-automatic-install-skin.php b/plugins/jetpack/_inc/lib/class.jetpack-automatic-install-skin.php
index 00afeb01..de46b144 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-automatic-install-skin.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-automatic-install-skin.php
@@ -1,112 +1,10 @@
<?php
-
-include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
-include_once ABSPATH . 'wp-admin/includes/file.php';
-
/**
- * Allows us to capture that the site doesn't have proper file system access.
- * In order to update the plugin.
+ * This file has been moved to the jetpack-plugins-installer package
+ *
+ * @deprecated 10.7
+ *
+ * @package jetpack
*/
-class Jetpack_Automatic_Install_Skin extends Automatic_Upgrader_Skin {
- /**
- * Stores the last error key;
- **/
- protected $main_error_code = 'install_error';
-
- /**
- * Stores the last error message.
- **/
- protected $main_error_message = 'An unknown error occurred during installation';
-
- /**
- * Overwrites the set_upgrader to be able to tell if we e ven have the ability to write to the files.
- *
- * @param WP_Upgrader $upgrader
- *
- */
- public function set_upgrader( &$upgrader ) {
- parent::set_upgrader( $upgrader );
-
- // Check if we even have permission to.
- $result = $upgrader->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
- if ( ! $result ) {
- // set the string here since they are not available just yet
- $upgrader->generic_strings();
- $this->feedback( 'fs_unavailable' );
- }
- }
-
- /**
- * Overwrites the error function
- */
- public function error( $error ) {
- if ( is_wp_error( $error ) ) {
- $this->feedback( $error );
- }
- }
-
- private function set_main_error_code( $code ) {
- // Don't set the process_failed as code since it is not that helpful unless we don't have one already set.
- $this->main_error_code = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $code );
- }
-
- private function set_main_error_message( $message, $code ) {
- // Don't set the process_failed as message since it is not that helpful unless we don't have one already set.
- $this->main_error_message = ( $code === 'process_failed' && $this->main_error_code ? $this->main_error_code : $message );
- }
-
- public function get_main_error_code() {
- return $this->main_error_code;
- }
-
- public function get_main_error_message() {
- return $this->main_error_message;
- }
-
- /**
- * Overwrites the feedback function
- *
- * @param string|array|WP_Error $data Data.
- * @param mixed ...$args Optional text replacements.
- */
- public function feedback( $data, ...$args ) {
-
- $current_error = null;
- if ( is_wp_error( $data ) ) {
- $this->set_main_error_code( $data->get_error_code() );
- $string = $data->get_error_message();
- } elseif ( is_array( $data ) ) {
- return;
- } else {
- $string = $data;
- }
-
- if ( ! empty( $this->upgrader->strings[$string] ) ) {
- $this->set_main_error_code( $string );
-
- $current_error = $string;
- $string = $this->upgrader->strings[$string];
- }
-
- if ( strpos( $string, '%' ) !== false ) {
- if ( ! empty( $args ) ) {
- $string = vsprintf( $string, $args );
- }
- }
-
- $string = trim( $string );
- $string = wp_kses(
- $string, array(
- 'a' => array(
- 'href' => true
- ),
- 'br' => true,
- 'em' => true,
- 'strong' => true,
- )
- );
- $this->set_main_error_message( $string, $current_error );
- $this->messages[] = $string;
- }
-}
+class_alias( Automattic\Jetpack\Automatic_Install_Skin::class, 'Jetpack_Automatic_Install_Skin' );
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-iframe-embed.php b/plugins/jetpack/_inc/lib/class.jetpack-iframe-embed.php
index 4445cb65..a4a5ed3c 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-iframe-embed.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-iframe-embed.php
@@ -1,20 +1,32 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
- * Tweak the preview when rendered in an iframe
+ * Tweak a preview when rendered in an iframe.
+ * This is used when rendering iFrames in the Calypso app.
+ *
+ * This file is shared between WordPress.com and Jetpack.
+ * The canonical source is Jetpack and no WordPress.com-specific code should exist in this file.
+ *
+ * @package automattic/jetpack
*/
+/**
+ * Tweak a preview when rendered in an iframe.
+ */
class Jetpack_Iframe_Embed {
- static function init() {
+ /**
+ * Initialize class.
+ */
+ public static function init() {
if ( ! self::is_embedding_in_iframe() ) {
return;
}
- // Disable the admin bar
+ // Disable the admin bar.
if ( ! defined( 'IFRAME_REQUEST' ) ) {
define( 'IFRAME_REQUEST', true );
}
- // Prevent canonical redirects
+ // Prevent canonical redirects.
remove_filter( 'template_redirect', 'redirect_canonical' );
add_action( 'wp_head', array( 'Jetpack_Iframe_Embed', 'noindex' ), 1 );
@@ -23,36 +35,44 @@ class Jetpack_Iframe_Embed {
add_filter( 'shortcode_atts_video', array( 'Jetpack_Iframe_Embed', 'disable_autoplay' ) );
add_filter( 'shortcode_atts_audio', array( 'Jetpack_Iframe_Embed', 'disable_autoplay' ) );
+ $ver = sprintf( '%s-%s', gmdate( 'oW' ), defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : '' );
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
- wp_enqueue_script( 'jetpack-iframe-embed', WPMU_PLUGIN_URL . '/jetpack-iframe-embed/jetpack-iframe-embed.js', array( 'jquery' ) );
+ wp_enqueue_script(
+ 'jetpack-iframe-embed',
+ WPMU_PLUGIN_URL . '/jetpack-iframe-embed/jetpack-iframe-embed.js',
+ array( 'jquery' ),
+ $ver,
+ false
+ );
} else {
- $ver = sprintf( '%s-%s', gmdate( 'oW' ), defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : '' );
- wp_enqueue_script( 'jetpack-iframe-embed', '//s0.wp.com/wp-content/mu-plugins/jetpack-iframe-embed/jetpack-iframe-embed.js', array( 'jquery' ), $ver );
+ wp_enqueue_script(
+ 'jetpack-iframe-embed',
+ '//s0.wp.com/wp-content/mu-plugins/jetpack-iframe-embed/jetpack-iframe-embed.js',
+ array( 'jquery' ),
+ $ver,
+ false
+ );
}
wp_localize_script( 'jetpack-iframe-embed', '_previewSite', array( 'siteURL' => get_site_url() ) );
}
- static function is_embedding_in_iframe() {
+ /**
+ * Check that we are in an iFrame.
+ *
+ * @return bool
+ */
+ private static function is_embedding_in_iframe() {
return (
- self::has_iframe_get_param() && (
- self::has_preview_get_param() ||
- self::has_preview_theme_preview_param()
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended -- No nonce needed, we're only checking for a specific screen view.
+ isset( $_GET['iframe'] ) && 'true' === $_GET['iframe']
+ && (
+ isset( $_GET['preview'] ) && 'true' === $_GET['preview']
+ || isset( $_GET['theme_preview'] ) && 'true' === $_GET['theme_preview']
)
+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
);
}
- private static function has_iframe_get_param() {
- return isset( $_GET['iframe'] ) && $_GET['iframe'] === 'true';
- }
-
- private static function has_preview_get_param() {
- return isset( $_GET['preview'] ) && $_GET['preview'] === 'true';
- }
-
- private static function has_preview_theme_preview_param() {
- return isset( $_GET['theme_preview'] ) && $_GET['theme_preview'] === 'true';
- }
-
/**
* Disable `autoplay` shortcode attribute in context of an iframe
* Added via `shortcode_atts_video` & `shortcode_atts_audio` in `init`
@@ -61,7 +81,7 @@ class Jetpack_Iframe_Embed {
*
* @return array The output array of shortcode attributes.
*/
- static function disable_autoplay( $atts ) {
+ public static function disable_autoplay( $atts ) {
return array_merge( $atts, array( 'autoplay' => false ) );
}
@@ -69,7 +89,7 @@ class Jetpack_Iframe_Embed {
* We don't want search engines to index iframe previews
* Added via `wp_head` action in `init`
*/
- static function noindex() {
+ public static function noindex() {
echo '<meta name="robots" content="noindex,nofollow" />';
}
@@ -78,7 +98,7 @@ class Jetpack_Iframe_Embed {
* (unless overridden on client-side by JS)
* Added via `wp_head` action in `init`
*/
- static function base_target_blank() {
+ public static function base_target_blank() {
echo '<base target="_blank" />';
}
}
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-keyring-service-helper.php b/plugins/jetpack/_inc/lib/class.jetpack-keyring-service-helper.php
index d623a3eb..4c2a0112 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-keyring-service-helper.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-keyring-service-helper.php
@@ -1,11 +1,22 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Utilities to interact with a Keyring instance.
+ * Used for Publicize as well as the Site Verification tools.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Connection\Secrets;
+/**
+ * A series of utilities to interact with a Keyring instance.
+ */
class Jetpack_Keyring_Service_Helper {
/**
+ * Class instance
+ *
* @var Jetpack_Keyring_Service_Helper
- **/
+ */
private static $instance = null;
/**
@@ -15,36 +26,39 @@ class Jetpack_Keyring_Service_Helper {
*/
private static $is_sharing_page_registered = false;
- static function init() {
- if ( is_null( self::$instance ) ) {
- self::$instance = new Jetpack_Keyring_Service_Helper;
+ /**
+ * Initialize instance.
+ */
+ public static function init() {
+ if ( self::$instance === null ) {
+ self::$instance = new Jetpack_Keyring_Service_Helper();
}
return self::$instance;
}
- public static $SERVICES = array(
- 'facebook' => array(
- 'for' => 'publicize'
+ const SERVICES = array(
+ 'facebook' => array(
+ 'for' => 'publicize',
),
- 'twitter' => array(
- 'for' => 'publicize'
+ 'twitter' => array(
+ 'for' => 'publicize',
),
- 'linkedin' => array(
- 'for' => 'publicize'
+ 'linkedin' => array(
+ 'for' => 'publicize',
),
- 'tumblr' => array(
- 'for' => 'publicize'
+ 'tumblr' => array(
+ 'for' => 'publicize',
),
- 'path' => array(
- 'for' => 'publicize'
+ 'path' => array(
+ 'for' => 'publicize',
),
- 'google_plus' => array(
- 'for' => 'publicize'
+ 'google_plus' => array(
+ 'for' => 'publicize',
),
'google_site_verification' => array(
- 'for' => 'other'
- )
+ 'for' => 'other',
+ ),
);
/**
@@ -79,7 +93,12 @@ class Jetpack_Keyring_Service_Helper {
$_registered_pages[ $hookname ] = true; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
- function get_services( $filter = 'all' ) {
+ /**
+ * Return a list of services.
+ *
+ * @param string $filter Choose 'all' to get all connected services, vs. just the connected ones.
+ */
+ public function get_services( $filter = 'all' ) {
$services = array();
if ( 'all' === $filter ) {
@@ -97,14 +116,15 @@ class Jetpack_Keyring_Service_Helper {
}
/**
- * Gets a URL to the public-api actions. Works like WP's admin_url
+ * Gets a URL to the public-api actions. Works like WP's admin_url.
+ * On WordPress.com this is/calls Keyring::admin_url.
*
* @param string $service Shortname of a specific service.
+ * @param array $params Parameters to append to an API connection URL.
*
* @return URL to specific public-api process
*/
- // on WordPress.com this is/calls Keyring::admin_url
- static function api_url( $service = false, $params = array() ) {
+ private static function api_url( $service = false, $params = array() ) {
/**
* Filters the API URL used to interact with WordPress.com.
*
@@ -125,7 +145,13 @@ class Jetpack_Keyring_Service_Helper {
return $url;
}
- static function connect_url( $service_name, $for ) {
+ /**
+ * Build a connection URL (sharing settings page with unique query args to create a connection).
+ *
+ * @param string $service_name Service name.
+ * @param string $for Feature name.
+ */
+ public static function connect_url( $service_name, $for ) {
return add_query_arg(
array(
'action' => 'request',
@@ -138,7 +164,14 @@ class Jetpack_Keyring_Service_Helper {
);
}
- static function refresh_url( $service_name, $for ) {
+ /**
+ * Build a URL to refresh a connection (sharing settings page with unique query args to refresh a connection).
+ * Similar to connect_url, but with a refresh parameter.
+ *
+ * @param string $service_name Service name.
+ * @param string $for Feature name.
+ */
+ public static function refresh_url( $service_name, $for ) {
return add_query_arg(
array(
'action' => 'request',
@@ -152,7 +185,13 @@ class Jetpack_Keyring_Service_Helper {
);
}
- static function disconnect_url( $service_name, $id ) {
+ /**
+ * Build a URL to delete a connection (sharing settings page with unique query args to delete a connection).
+ *
+ * @param string $service_name Service name.
+ * @param string $id Connection ID.
+ */
+ public static function disconnect_url( $service_name, $id ) {
return add_query_arg(
array(
'action' => 'delete',
@@ -165,10 +204,13 @@ class Jetpack_Keyring_Service_Helper {
);
}
- static function admin_page_load() {
+ /**
+ * Build contents handling Keyring connection management into Sharing settings screen.
+ */
+ public static function admin_page_load() {
if ( isset( $_GET['action'] ) ) {
if ( isset( $_GET['service'] ) ) {
- $service_name = $_GET['service'];
+ $service_name = sanitize_text_field( wp_unslash( $_GET['service'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We verify below.
}
switch ( $_GET['action'] ) {
@@ -180,7 +222,20 @@ class Jetpack_Keyring_Service_Helper {
$verification = ( new Secrets() )->generate( 'publicize' );
if ( ! $verification ) {
$url = Jetpack::admin_url( 'jetpack#/settings' );
- wp_die( sprintf( __( "Jetpack is not connected. Please connect Jetpack by visiting <a href='%s'>Settings</a>.", 'jetpack' ), $url ) );
+ wp_die(
+ sprintf(
+ wp_kses(
+ /* Translators: placeholder is a URL to a Settings page. */
+ __( "Jetpack is not connected. Please connect Jetpack by visiting <a href='%s'>Settings</a>.", 'jetpack' ),
+ array(
+ 'a' => array(
+ 'href' => array(),
+ ),
+ )
+ ),
+ esc_url( $url )
+ )
+ );
}
$stats_options = get_option( 'stats_options' );
@@ -188,23 +243,32 @@ class Jetpack_Keyring_Service_Helper {
$wpcom_blog_id = ! empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
$user = wp_get_current_user();
- $redirect = Jetpack_Keyring_Service_Helper::api_url( $service_name, urlencode_deep( array(
- 'action' => 'request',
- 'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
- 'for' => 'publicize',
- // required flag that says this connection is intended for publicize
- 'siteurl' => site_url(),
- 'state' => $user->ID,
- 'blog_id' => $wpcom_blog_id,
- 'secret_1' => $verification['secret_1'],
- 'secret_2' => $verification['secret_2'],
- 'eol' => $verification['exp'],
- ) ) );
- wp_redirect( $redirect );
+ $redirect = self::api_url(
+ $service_name,
+ urlencode_deep(
+ array(
+ 'action' => 'request',
+ 'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
+ 'for' => 'publicize',
+ // required flag that says this connection is intended for publicize.
+ 'siteurl' => site_url(),
+ 'state' => $user->ID,
+ 'blog_id' => $wpcom_blog_id,
+ 'secret_1' => $verification['secret_1'],
+ 'secret_2' => $verification['secret_2'],
+ 'eol' => $verification['exp'],
+ )
+ )
+ );
+ wp_redirect( $redirect ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- The API URL is an external URL and is filterable.
exit;
- break;
case 'completed':
+ /*
+ * We do not use a nonce here,
+ * since we're populating a local cache of
+ * the Publicize connections that were created and stored on WordPress.com.
+ */
$xml = new Jetpack_IXR_Client();
$xml->query( 'jetpack.fetchPublicizeConnections' );
@@ -216,12 +280,12 @@ class Jetpack_Keyring_Service_Helper {
break;
case 'delete':
- $id = $_GET['id'];
+ $id = isset( $_GET['id'] ) ? sanitize_text_field( wp_unslash( $_GET['id'] ) ) : null;
check_admin_referer( 'keyring-request', 'kr_nonce' );
check_admin_referer( "keyring-request-$service_name", 'nonce' );
- Jetpack_Keyring_Service_Helper::disconnect( $service_name, $id );
+ self::disconnect( $service_name, $id );
do_action( 'connection_disconnected', $service_name );
break;
@@ -231,8 +295,14 @@ class Jetpack_Keyring_Service_Helper {
/**
* Remove a Publicize connection
+ *
+ * @param string $service_name Service name.
+ * @param string $connection_id Connection ID.
+ * @param int|bool $_blog_id Blog ID.
+ * @param int|bool $_user_id User ID.
+ * @param bool $force_delete Force delete the connection.
*/
- static function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
+ public static function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$xml = new Jetpack_IXR_Client();
$xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
@@ -242,5 +312,4 @@ class Jetpack_Keyring_Service_Helper {
return false;
}
}
-
}
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-password-checker.php b/plugins/jetpack/_inc/lib/class.jetpack-password-checker.php
index 75b6bbfd..4887e588 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-password-checker.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-password-checker.php
@@ -101,7 +101,7 @@ class Jetpack_Password_Checker {
*/
$this->common_passwords = apply_filters( 'jetpack_password_checker_restricted_strings', array() );
- if ( is_null( $user ) ) {
+ if ( $user === null ) {
$this->user_id = get_current_user_id();
} elseif ( is_object( $user ) && isset( $user->ID ) ) {
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-photon-image-sizes.php b/plugins/jetpack/_inc/lib/class.jetpack-photon-image-sizes.php
index 1bf5bf6c..f533e4c3 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-photon-image-sizes.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-photon-image-sizes.php
@@ -1,4 +1,4 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* The Image Sizes library.
*
@@ -15,17 +15,23 @@ jetpack_require_lib( 'class.jetpack-photon-image' );
class Jetpack_Photon_ImageSizes {
/**
- * @var array $data Attachment metadata.
+ * Attachment metadata.
+ *
+ * @var array
*/
public $data;
/**
- * @var Image Image to be resized.
+ * Image to be resized.
+ *
+ * @var Image
*/
public $image;
/**
- * @var null|array $sizes Intermediate sizes.
+ * Intermediate sizes.
+ *
+ * @var null|array
*/
public static $sizes = null;
@@ -99,6 +105,8 @@ class Jetpack_Photon_ImageSizes {
}
/**
+ * Add filtered sizes.
+ *
* @return array
*/
public function filtered_sizes() {
@@ -170,7 +178,9 @@ class Jetpack_Photon_ImageSizes {
}
/**
- * @param array $size_data
+ * Resize image.
+ *
+ * @param array $size_data Resize parameters.
*
* @return array|\WP_Error Array for usage in $metadata['sizes']; WP_Error on failure.
*/
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-photon-image.php b/plugins/jetpack/_inc/lib/class.jetpack-photon-image.php
index 81ef74b4..4e15f08d 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-photon-image.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-photon-image.php
@@ -1,4 +1,4 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* The Image Class.
*
@@ -11,37 +11,51 @@
class Jetpack_Photon_Image {
/**
- * @var string $filename Attachment's Filename.
+ * Attachment's Filename.
+ *
+ * @var string
*/
public $filename;
/**
- * @var string/WP_Erorr $mime_type Attachment's mime-type, WP_Error on failure when recalculating the dimensions.
+ * Attachment's mime-type, WP_Error on failure when recalculating the dimensions.
+ *
+ * @var string|WP_Error
*/
private $mime_type;
/**
- * @var int $original_width Image original width.
+ * Image original width.
+ *
+ * @var int
*/
private $original_width;
/**
- * @var int $original_width Image original height.
+ * Image original height.
+ *
+ * @var int
*/
private $original_height;
/**
- * @var int $width Current attachment's width.
+ * Current attachment's width.
+ *
+ * @var int
*/
private $width;
/**
- * @var int $height Current attachment's height.
+ * Current attachment's height.
+ *
+ * @var int
*/
private $height;
/**
- * @var bool $is_resized Whether the attachment has been resized yet, or not.
+ * Whether the attachment has been resized yet, or not.
+ *
+ * @var bool
*/
private $is_resized = false;
@@ -53,14 +67,16 @@ class Jetpack_Photon_Image {
* width : int Image width
* height : int Image height
*
- * @param array $data Array of attachment metadata, typically value of _wp_attachment_metadata postmeta
+ * @param array $data Array of attachment metadata, typically value of _wp_attachment_metadata postmeta.
* @param string|\WP_Error $mime_type Typically value returned from get_post_mime_type function.
*/
public function __construct( $data, $mime_type ) {
- $this->filename = $data['file'];
- $this->width = $this->original_width = $data['width'];
- $this->height = $this->original_height = $data['height'];
- $this->mime_type = $mime_type;
+ $this->filename = $data['file'];
+ $this->original_width = $data['width'];
+ $this->original_height = $data['height'];
+ $this->width = $this->original_width;
+ $this->height = $this->original_height;
+ $this->mime_type = $mime_type;
}
/**
@@ -84,7 +100,9 @@ class Jetpack_Photon_Image {
$this->set_width_height( $dimensions );
- return $this->is_resized = true;
+ $this->is_resized = true;
+
+ return true;
}
/**
@@ -205,16 +223,16 @@ class Jetpack_Photon_Image {
* associative array for the sake of more readable code no relying on index
* nor `list`.
*
- * @param int $max_width
- * @param int $max_height
- * @param bool|array $crop
+ * @param int $max_width Maximum width.
+ * @param int $max_height Maximum height.
+ * @param bool|array $crop Cropping parameters.
*
* @return array|\WP_Error Array of dimensions matching the parameters to imagecopyresampled. WP_Error on failure.
*/
protected function image_resize_dimensions( $max_width, $max_height, $crop ) {
$dimensions = image_resize_dimensions( $this->original_width, $this->original_height, $max_width, $max_height, $crop );
if ( ! $dimensions ) {
- return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ), $this->filename );
+ return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions', 'jetpack' ), $this->filename );
}
return array_combine(
diff --git a/plugins/jetpack/_inc/lib/class.jetpack-search-performance-logger.php b/plugins/jetpack/_inc/lib/class.jetpack-search-performance-logger.php
index c3df0778..fb9dbf85 100644
--- a/plugins/jetpack/_inc/lib/class.jetpack-search-performance-logger.php
+++ b/plugins/jetpack/_inc/lib/class.jetpack-search-performance-logger.php
@@ -1,23 +1,51 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Measure the performance of Jetpack Search queries.
+ */
class Jetpack_Search_Performance_Logger {
/**
- * @var Jetpack_Search_Performance_Logger
- **/
+ * Jetpack_Search_Performance_Logger instance.
+ *
+ * @var null|Jetpack_Search_Performance_Logger
+ */
private static $instance = null;
+ /**
+ * WP_Query instance.
+ *
+ * @var null|WP_Query
+ */
private $current_query = null;
+
+ /**
+ * Time when the query was started.
+ *
+ * @var null|float
+ */
private $query_started = null;
+
+ /**
+ * Performance results.
+ *
+ * @var null|array
+ */
private $stats = null;
- static function init() {
- if ( is_null( self::$instance ) ) {
- self::$instance = new Jetpack_Search_Performance_Logger;
+ /**
+ * Initialize the class.
+ */
+ public static function init() {
+ if ( self::$instance === null ) {
+ self::$instance = new Jetpack_Search_Performance_Logger();
}
return self::$instance;
}
+ /**
+ * The constructor.
+ */
private function __construct() {
$this->stats = array();
add_action( 'pre_get_posts', array( $this, 'begin_log_query' ), 10, 1 );
@@ -26,17 +54,28 @@ class Jetpack_Search_Performance_Logger {
add_action( 'wp_footer', array( $this, 'print_stats' ) );
}
- public function begin_log_query( $query ) {
+ /**
+ * Log the time when the query was started.
+ *
+ * @param WP_Query $query The query.
+ */
+ public function begin_log_query( $query ) {
if ( $this->should_log_query( $query ) ) {
$this->query_started = microtime( true );
$this->current_query = $query;
}
}
+ /**
+ * Record the time when an SQL query was completed.
+ *
+ * @param int $found_posts The number of posts found.
+ * @param WP_Query $query The WP_Query instance (passed by reference).
+ */
public function log_mysql_query( $found_posts, $query ) {
if ( $this->current_query === $query ) {
$duration = microtime( true ) - $this->query_started;
- if ( $duration < 60 ) { // eliminate outliers, likely tracking errors
+ if ( $duration < 60 ) { // eliminate outliers, likely tracking errors.
$this->record_query_time( $duration, false );
}
$this->reset_query_state();
@@ -45,38 +84,58 @@ class Jetpack_Search_Performance_Logger {
return $found_posts;
}
+ /**
+ * Log Jetpack Search query.
+ */
public function log_jetpack_search_query() {
$duration = microtime( true ) - $this->query_started;
- if ( $duration < 60 ) { // eliminate outliers, likely tracking errors
+ if ( $duration < 60 ) { // eliminate outliers, likely tracking errors.
$this->record_query_time( $duration, true );
}
$this->reset_query_state();
}
+ /**
+ * Reset data after each log.
+ */
private function reset_query_state() {
$this->query_started = null;
$this->current_query = null;
}
+ /**
+ * Check if a query should be logged (a main query, or a jetpack search query).
+ *
+ * @param WP_Query $query The WP_Query instance.
+ */
private function should_log_query( $query ) {
return $query->is_main_query() && $query->is_search();
}
+ /**
+ * Record the time of a query.
+ *
+ * @param float $duration The duration of the query.
+ * @param bool $was_jetpack_search Was this a Jetpack Search query.
+ */
private function record_query_time( $duration, $was_jetpack_search ) {
$this->stats[] = array( $was_jetpack_search, (int) ( $duration * 1000 ) );
}
+ /**
+ * Print performance stats in the footer.
+ */
public function print_stats() {
$beacons = array();
if ( ! empty( $this->stats ) ) {
- foreach( $this->stats as $stat ) {
+ foreach ( $this->stats as $stat ) {
$search_type = $stat[0] ? 'es' : 'mysql';
- $beacons[] = "%22jetpack.search.{$search_type}.duration:{$stat[1]}|ms%22";
+ $beacons[] = "%22jetpack.search.{$search_type}.duration:{$stat[1]}|ms%22";
}
- $encoded_json = '{%22beacons%22:[' . implode(',', $beacons ) . ']}';
- $encoded_site_url = urlencode( site_url() );
- $url = "https://pixel.wp.com/boom.gif?v=0.9&u={$encoded_site_url}&json={$encoded_json}";
+ $encoded_json = '{%22beacons%22:[' . implode( ',', $beacons ) . ']}';
+ $encoded_site_url = rawurlencode( site_url() );
+ $url = "https://pixel.wp.com/boom.gif?v=0.9&u={$encoded_site_url}&json={$encoded_json}";
echo '<img src="' . esc_url( $url ) . '" width="1" height="1" style="display:none;" alt=""/>';
}
}
diff --git a/plugins/jetpack/_inc/lib/class.media.php b/plugins/jetpack/_inc/lib/class.media.php
index a9ae488c..826c1535 100644
--- a/plugins/jetpack/_inc/lib/class.media.php
+++ b/plugins/jetpack/_inc/lib/class.media.php
@@ -1,15 +1,35 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
-require_once( JETPACK__PLUGIN_DIR . 'sal/class.json-api-date.php' );
+require_once JETPACK__PLUGIN_DIR . 'sal/class.json-api-date.php';
/**
* Class to handle different actions related to media.
*/
class Jetpack_Media {
- public static $WP_ORIGINAL_MEDIA = '_wp_original_post_media';
- public static $WP_REVISION_HISTORY = '_wp_revision_history';
- public static $REVISION_HISTORY_MAXIMUM_AMOUNT = 0;
- public static $WP_ATTACHMENT_IMAGE_ALT = '_wp_attachment_image_alt';
+ /**
+ * Original media meta data. Metadata key as stored by WP.
+ *
+ * @var string
+ */
+ const WP_ORIGINAL_MEDIA = '_wp_original_post_media';
+ /**
+ * Revision history. Metadata key as stored by WP.
+ *
+ * @var string
+ */
+ const WP_REVISION_HISTORY = '_wp_revision_history';
+ /**
+ * Maximum amount of revisions.
+ *
+ * @var int
+ */
+ const REVISION_HISTORY_MAXIMUM_AMOUNT = 0;
+ /**
+ * Image Alt. Metadata key as stored by WP.
+ *
+ * @var string
+ */
+ const WP_ATTACHMENT_IMAGE_ALT = '_wp_attachment_image_alt';
/**
* Generate a filename in function of the original filename of the media.
@@ -45,7 +65,7 @@ class Jetpack_Media {
// Add unique seed based on the filename.
$filename_base .= '-' . crc32( $filename_base ) . '-';
- $number_suffix = time() . rand( 100, 999 );
+ $number_suffix = time() . wp_rand( 100, 999 );
do {
$filename = $filename_base;
@@ -70,13 +90,14 @@ class Jetpack_Media {
* "http://test.files.wordpress.com/2016/10/test.png" the resulting string
* would be: "2016/10"
*
- * @param number $media_id
+ * @param int $media_id Attachment ID.
* @return string
*/
private static function get_time_string_from_guid( $media_id ) {
- $time = date( "Y/m", strtotime( current_time( 'mysql' ) ) );
+ $time = gmdate( 'Y/m', strtotime( current_time( 'mysql' ) ) );
- if ( $media = get_post( $media_id ) ) {
+ $media = get_post( $media_id );
+ if ( $media ) {
$pattern = '/\/(\d{4}\/\d{2})\//';
preg_match( $pattern, $media->guid, $matches );
if ( count( $matches ) > 1 ) {
@@ -89,20 +110,27 @@ class Jetpack_Media {
/**
* Return an array of allowed mime_type items used to upload a media file.
*
+ * @param array $default_mime_types Array of mime types.
+ *
* @return array mime_type array
*/
- static function get_allowed_mime_types( $default_mime_types ) {
- return array_unique( array_merge( $default_mime_types, array(
- 'application/msword', // .doc
- 'application/vnd.ms-powerpoint', // .ppt, .pps
- 'application/vnd.ms-excel', // .xls
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
- 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', // .ppsx
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
- 'application/vnd.oasis.opendocument.text', // .odt
- 'application/pdf', // .pdf
- ) ) );
+ public static function get_allowed_mime_types( $default_mime_types ) {
+ return array_unique(
+ array_merge(
+ $default_mime_types,
+ array(
+ 'application/msword', // .doc
+ 'application/vnd.ms-powerpoint', // .ppt, .pps
+ 'application/vnd.ms-excel', // .xls
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', // .ppsx
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
+ 'application/vnd.oasis.opendocument.text', // .odt
+ 'application/pdf', // .pdf
+ )
+ )
+ );
}
/**
@@ -119,14 +147,15 @@ class Jetpack_Media {
/**
* Try to remove the temporal file from the given file array.
*
- * @param array $file_array Array with data about the temporal file
+ * @param array $file_array Array with data about the temporal file.
+ *
* @return bool `true` if the file has been removed. `false` either the file doesn't exist or it couldn't be removed.
*/
private static function remove_tmp_file( $file_array ) {
- if ( ! file_exists ( $file_array['tmp_name'] ) ) {
+ if ( ! file_exists( $file_array['tmp_name'] ) ) {
return false;
}
- return @unlink( $file_array['tmp_name'] );
+ return @unlink( $file_array['tmp_name'] ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
}
/**
@@ -135,8 +164,8 @@ class Jetpack_Media {
* The file type control is done through of `jetpack_supported_media_sideload_types` filter,
* which allows define to the users their own file types list.
*
- * @param array $file_array file to save
- * @param number $media_id
+ * @param array $file_array file to save.
+ * @param int $media_id Attachment ID.
* @return array|WP_Error an array with information about the new file saved or a WP_Error is something went wrong.
*/
public static function save_temporary_file( $file_array, $media_id ) {
@@ -146,10 +175,10 @@ class Jetpack_Media {
return new WP_Error( 'invalid_input', 'No media provided in input.' );
}
- // add additional mime_types through of the `jetpack_supported_media_sideload_types` filter
+ // add additional mime_types through of the `jetpack_supported_media_sideload_types` filter.
$mime_type_static_filter = array(
'Jetpack_Media',
- 'get_allowed_mime_types'
+ 'get_allowed_mime_types',
);
add_filter( 'jetpack_supported_media_sideload_types', $mime_type_static_filter );
@@ -157,22 +186,22 @@ class Jetpack_Media {
! self::is_file_supported_for_sideloading( $tmp_filename ) &&
! file_is_displayable_image( $tmp_filename )
) {
- @unlink( $tmp_filename );
+ @unlink( $tmp_filename ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
return new WP_Error( 'invalid_input', 'Invalid file type.', 403 );
}
remove_filter( 'jetpack_supported_media_sideload_types', $mime_type_static_filter );
- // generate a new file name
- $tmp_new_filename = self::generate_new_filename( $media_id, $file_array[ 'name' ] );
+ // generate a new file name.
+ $tmp_new_filename = self::generate_new_filename( $media_id, $file_array['name'] );
- // start to create the parameters to move the temporal file
+ // start to create the parameters to move the temporal file.
$overrides = array( 'test_form' => false );
- // get time according to the original filaname
+ // get time according to the original filaname.
$time = self::get_time_string_from_guid( $media_id );
$file_array['name'] = $tmp_new_filename;
- $file = wp_handle_sideload( $file_array, $overrides, $time );
+ $file = wp_handle_sideload( $file_array, $overrides, $time );
self::remove_tmp_file( $file_array );
@@ -186,20 +215,20 @@ class Jetpack_Media {
/**
* Return an object with an snapshot of a revision item.
*
- * @param object $media_item - media post object
+ * @param object $media_item - media post object.
* @return object a revision item
*/
public static function get_snapshot( $media_item ) {
$current_file = get_attached_file( $media_item->ID );
- $file_paths = pathinfo( $current_file );
+ $file_paths = pathinfo( $current_file );
$snapshot = array(
- 'date' => (string) WPCOM_JSON_API_Date::format_date( $media_item->post_modified_gmt, $media_item->post_modified ),
- 'URL' => (string) wp_get_attachment_url( $media_item->ID ),
- 'file' => (string) $file_paths['basename'],
- 'extension' => (string) $file_paths['extension'],
- 'mime_type' => (string) $media_item->post_mime_type,
- 'size' => (int) filesize( $current_file ),
+ 'date' => (string) WPCOM_JSON_API_Date::format_date( $media_item->post_modified_gmt, $media_item->post_modified ),
+ 'URL' => (string) wp_get_attachment_url( $media_item->ID ),
+ 'file' => (string) $file_paths['basename'],
+ 'extension' => (string) $file_paths['extension'],
+ 'mime_type' => (string) $media_item->post_mime_type,
+ 'size' => (int) filesize( $current_file ),
);
return (object) $snapshot;
@@ -208,9 +237,9 @@ class Jetpack_Media {
/**
* Add a new item into revision_history array.
*
- * @param object $media_item - media post object
- * @param file $file - file recently added
- * @param bool $has_original_media - condition is the original media has been already added
+ * @param object $media_item - media post object.
+ * @param file $file - file recently added.
+ * @param bool $has_original_media - condition is the original media has been already added.
* @return bool `true` if the item has been added. Otherwise `false`.
*/
public static function register_revision( $media_item, $file, $has_original_media ) {
@@ -218,30 +247,37 @@ class Jetpack_Media {
return false;
}
- add_post_meta( $media_item->ID, self::$WP_REVISION_HISTORY, self::get_snapshot( $media_item ) );
+ add_post_meta( $media_item->ID, self::WP_REVISION_HISTORY, self::get_snapshot( $media_item ) );
}
/**
* Return the `revision_history` of the given media.
*
- * @param number $media_id - media post ID
+ * @param number $media_id - media post ID.
* @return array `revision_history` array
*/
public static function get_revision_history( $media_id ) {
- return array_reverse( get_post_meta( $media_id, self::$WP_REVISION_HISTORY ) );
+ return array_reverse( get_post_meta( $media_id, self::WP_REVISION_HISTORY ) );
}
/**
- * Return the original media data
+ * Return the original media data.
+ *
+ * @param int $media_id Attachment ID.
*/
public static function get_original_media( $media_id ) {
- $original = get_post_meta( $media_id, self::$WP_ORIGINAL_MEDIA, true );
+ $original = get_post_meta( $media_id, self::WP_ORIGINAL_MEDIA, true );
$original = $original ? $original : array();
return $original;
}
+ /**
+ * Delete a file.
+ *
+ * @param string $pathname Path name.
+ */
public static function delete_file( $pathname ) {
if ( ! file_exists( $pathname ) || ! is_file( $pathname ) ) {
- // let's touch a fake file to try to `really` remove the media file
+ // let's touch a fake file to try to `really` remove the media file.
touch( $pathname );
}
@@ -252,27 +288,28 @@ class Jetpack_Media {
* Try to delete a file according to the dirname of
* the media attached file and the filename.
*
- * @param number $media_id - media post ID
- * @param string $filename - basename of the file ( name-of-file.ext )
- * @return bool `true` is the file has been removed, `false` if not.
+ * @param int $media_id - media post ID.
+ * @param string $filename - basename of the file ( name-of-file.ext ).
+ *
+ * @return void
*/
private static function delete_media_history_file( $media_id, $filename ) {
- $attached_path = get_attached_file( $media_id );
+ $attached_path = get_attached_file( $media_id );
$attached_parts = pathinfo( $attached_path );
- $dirname = $attached_parts['dirname'];
+ $dirname = $attached_parts['dirname'];
$pathname = $dirname . '/' . $filename;
- // remove thumbnails
+ // remove thumbnails.
$metadata = wp_generate_attachment_metadata( $media_id, $pathname );
if ( isset( $metadata ) && isset( $metadata['sizes'] ) ) {
- foreach ( $metadata['sizes'] as $size => $properties ) {
+ foreach ( $metadata['sizes'] as $properties ) {
self::delete_file( $dirname . '/' . $properties['file'] );
}
}
- // remove primary file
+ // remove primary file.
self::delete_file( $pathname );
}
@@ -285,18 +322,19 @@ class Jetpack_Media {
*
* Also, it removes the file defined in each item.
*
- * @param number $media_id - media post ID
- * @param object $criteria - criteria to remove the items
- * @param array [$revision_history] - revision history array
+ * @param int $media_id - media post ID.
+ * @param object $criteria - criteria to remove the items.
+ * @param array $revision_history - revision history array.
+ *
* @return array `revision_history` array updated.
*/
public static function remove_items_from_revision_history( $media_id, $criteria, $revision_history ) {
- if ( ! isset ( $revision_history ) ) {
+ if ( ! isset( $revision_history ) ) {
$revision_history = self::get_revision_history( $media_id );
}
$from = $criteria['from'];
- $to = $criteria['to'] ? $criteria['to'] : ( $from + 1 );
+ $to = $criteria['to'] ? $criteria['to'] : ( $from + 1 );
for ( $i = $from; $i < $to; $i++ ) {
$removed_item = array_slice( $revision_history, $from, 1 );
@@ -308,11 +346,11 @@ class Jetpack_Media {
self::delete_media_history_file( $media_id, $removed_item[0]->file );
}
- // override all history items
- delete_post_meta( $media_id, self::$WP_REVISION_HISTORY );
+ // override all history items.
+ delete_post_meta( $media_id, self::WP_REVISION_HISTORY );
$revision_history = array_reverse( $revision_history );
foreach ( $revision_history as &$item ) {
- add_post_meta( $media_id, self::$WP_REVISION_HISTORY, $item );
+ add_post_meta( $media_id, self::WP_REVISION_HISTORY, $item );
}
return $revision_history;
@@ -322,13 +360,14 @@ class Jetpack_Media {
* Limit the number of items of the `revision_history` array.
* When the stack is overflowing the oldest item is remove from there (FIFO).
*
- * @param number $media_id - media post ID
- * @param number [$limit] - maximun amount of items. 20 as default.
+ * @param int $media_id - media post ID.
+ * @param null|int $limit - maximun amount of items. 20 as default.
+ *
* @return array items removed from `revision_history`
*/
- public static function limit_revision_history( $media_id, $limit = null) {
- if ( is_null( $limit ) ) {
- $limit = self::$REVISION_HISTORY_MAXIMUM_AMOUNT;
+ public static function limit_revision_history( $media_id, $limit = null ) {
+ if ( $limit === null ) {
+ $limit = self::REVISION_HISTORY_MAXIMUM_AMOUNT;
}
$revision_history = self::get_revision_history( $media_id );
@@ -341,7 +380,10 @@ class Jetpack_Media {
self::remove_items_from_revision_history(
$media_id,
- array( 'from' => $limit, 'to' => $total ),
+ array(
+ 'from' => $limit,
+ 'to' => $total,
+ ),
$revision_history
);
@@ -351,7 +393,7 @@ class Jetpack_Media {
/**
* Remove the original file and clean the post metadata.
*
- * @param number $media_id - media post ID
+ * @param int $media_id - media post ID.
*/
public static function clean_original_media( $media_id ) {
$original_file = self::get_original_media( $media_id );
@@ -361,7 +403,7 @@ class Jetpack_Media {
}
self::delete_media_history_file( $media_id, $original_file->file );
- return delete_post_meta( $media_id, self::$WP_ORIGINAL_MEDIA );
+ return delete_post_meta( $media_id, self::WP_ORIGINAL_MEDIA );
}
/**
@@ -370,15 +412,16 @@ class Jetpack_Media {
* - clean `revision_history` meta data.
* - remove and clean the `original_media`
*
- * @param number $media_id - media post ID
+ * @param int $media_id - media post ID.
+ *
* @return array results of removing these files
*/
public static function clean_revision_history( $media_id ) {
self::clean_original_media( $media_id );
$revision_history = self::get_revision_history( $media_id );
- $total = count( $revision_history );
- $updated_history = array();
+ $total = count( $revision_history );
+ $updated_history = array();
if ( $total < 1 ) {
return $updated_history;
@@ -386,7 +429,10 @@ class Jetpack_Media {
$updated_history = self::remove_items_from_revision_history(
$media_id,
- array( 'from' => 0, 'to' => $total ),
+ array(
+ 'from' => 0,
+ 'to' => $total,
+ ),
$revision_history
);
@@ -413,8 +459,7 @@ class Jetpack_Media {
// The first time that the media is updated
// the original media is stored into the revision_history.
$snapshot = self::get_snapshot( $media_item );
- //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
- add_post_meta( $media_id, self::$WP_ORIGINAL_MEDIA, $snapshot, true );
+ add_post_meta( $media_id, self::WP_ORIGINAL_MEDIA, $snapshot, true );
}
// Save temporary file in the correct location.
@@ -433,7 +478,7 @@ class Jetpack_Media {
$was_updated = update_attached_file( $media_id, $uploaded_path );
if ( ! $was_updated ) {
- return WP_Error( 'update_error', 'Media update error' );
+ return new WP_Error( 'update_error', 'Media update error' );
}
// Check maximum amount of revision_history before updating the attachment metadata.
@@ -458,9 +503,12 @@ class Jetpack_Media {
}
}
-// hook: clean revision history when the media item is deleted
-function clean_revision_history( $media_id ) {
+/**
+ * Clean revision history when the media item is deleted.
+ *
+ * @param int $media_id Attachment ID.
+ */
+function jetpack_clean_revision_history( $media_id ) {
Jetpack_Media::clean_revision_history( $media_id );
-};
-
-add_action( 'delete_attachment', 'clean_revision_history' );
+}
+add_action( 'delete_attachment', 'jetpack_clean_revision_history' );
diff --git a/plugins/jetpack/_inc/lib/core-api/class-wpcom-rest-field-controller.php b/plugins/jetpack/_inc/lib/core-api/class-wpcom-rest-field-controller.php
index 2a2245e4..4b4839ca 100644
--- a/plugins/jetpack/_inc/lib/core-api/class-wpcom-rest-field-controller.php
+++ b/plugins/jetpack/_inc/lib/core-api/class-wpcom-rest-field-controller.php
@@ -1,38 +1,64 @@
-<?php
-
-// @todo - nicer API for array values?
-
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* `WP_REST_Controller` is basically a wrapper for `register_rest_route()`
* `WPCOM_REST_API_V2_Field_Controller` is a mostly-analogous wrapper for `register_rest_field()`
+ *
+ * @todo - nicer API for array values?
+ *
+ * @package automattic/jetpack
+ */
+
+/**
+ * Abstract WPCOM_REST_API_V2_Field_Controller class extended for different fields needed in the Jetpack plugin.
*/
abstract class WPCOM_REST_API_V2_Field_Controller {
/**
- * @var string|string[] $object_type The REST Object Type(s) to which the field should be added.
+ * The REST Object Type(s) to which the field should be added.
+ *
+ * @var string|string[]
*/
protected $object_type;
/**
- * @var string $field_name The name of the REST API field to add.
+ * The name of the REST API field to add.
+ *
+ * @var string
*/
protected $field_name;
+ /**
+ * Constructor
+ */
public function __construct() {
if ( ! $this->object_type ) {
- /* translators: %s: object_type */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::$object_type', sprintf( __( "Property '%s' must be overridden.", 'jetpack' ), 'object_type' ), 'Jetpack 6.8' );
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::$object_type',
+ sprintf(
+ /* translators: %s: object_type */
+ esc_html__( "Property '%s' must be overridden.", 'jetpack' ),
+ 'object_type'
+ ),
+ 'jetpack-6.8'
+ );
return;
}
if ( ! $this->field_name ) {
- /* translators: %s: field_name */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::$field_name', sprintf( __( "Property '%s' must be overridden.", 'jetpack' ), 'field_name' ), 'Jetpack 6.8' );
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::$field_name',
+ sprintf(
+ /* translators: %s: field_name */
+ esc_html__( "Property '%s' must be overridden.", 'jetpack' ),
+ 'field_name'
+ ),
+ 'jetpack-6.8'
+ );
return;
}
add_action( 'rest_api_init', array( $this, 'register_fields' ) );
- // do this again later to collect any CPTs that get registered later
+ // do this again later to collect any CPTs that get registered later.
add_action( 'restapi_theme_init', array( $this, 'register_fields' ), 20 );
}
@@ -41,6 +67,9 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
*/
public function register_fields() {
foreach ( (array) $this->object_type as $object_type ) {
+ if ( $this->is_registered( $object_type ) ) {
+ continue;
+ }
register_rest_field(
$object_type,
$this->field_name,
@@ -54,10 +83,23 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
}
/**
+ * Checks if the field is already registered for the object_type
+ *
+ * @param string $object_type The name of the object type.
+ * @return boolean Whether the field has been registered for the type.
+ */
+ public function is_registered( $object_type ) {
+ global $wp_rest_additional_fields;
+
+ return ! empty( $wp_rest_additional_fields[ $object_type ][ $this->field_name ] );
+ }
+
+ /**
* Ensures the response matches the schema and request context.
*
- * @param mixed $value
- * @param WP_REST_Request $request
+ * @param mixed $value Value passed in request.
+ * @param WP_REST_Request $request WP API request.
+ *
* @return mixed
*/
private function prepare_for_response( $value, $request ) {
@@ -77,7 +119,8 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
*
* If there is no default, returns the type's falsey value.
*
- * @param array $schema
+ * @param array $schema Schema to validate against.
+ *
* @return mixed
*/
final public function get_default_value( $schema ) {
@@ -85,7 +128,7 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
return $schema['default'];
}
- // If you have something more complicated, use $schema['default'];
+ // If you have something more complicated, use $schema['default'].
switch ( isset( $schema['type'] ) ? $schema['type'] : 'null' ) {
case 'string':
return '';
@@ -110,17 +153,25 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
* This cannot be extended: implement `->get()` instead.
*
* @param mixed $object_data Probably an array. Whatever the endpoint returns.
- * @param string $field_name Should always match `->field_name`
- * @param WP_REST_Request $request
- * @param string $object_type Should always match `->object_type`
+ * @param string $field_name Should always match `->field_name`.
+ * @param WP_REST_Request $request WP API request.
+ * @param string $object_type Should always match `->object_type`.
+ *
* @return mixed
*/
- final public function get_for_response( $object_data, $field_name, $request, $object_type ) {
+ final public function get_for_response( $object_data, $field_name, $request, $object_type ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$permission_check = $this->get_permission_check( $object_data, $request );
if ( ! $permission_check ) {
- /* translators: %s: get_permission_check() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::get_permission_check', sprintf( __( "Method '%s' must return either true or WP_Error.", 'jetpack' ), 'get_permission_check' ), 'Jetpack 6.8' );
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::get_permission_check',
+ sprintf(
+ /* translators: %s: get_permission_check() */
+ esc_html__( "Method '%s' must return either true or WP_Error.", 'jetpack' ),
+ 'get_permission_check'
+ ),
+ 'jetpack-6.8'
+ );
return $this->get_default_value( $this->get_schema() );
}
@@ -138,21 +189,35 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
*
* This cannot be extended: implement `->update()` instead.
*
- * @param mixed $value The new value for the field.
- * @param mixed $object_data Probably a WordPress object (e.g., WP_Post)
- * @param string $field_name Should always match `->field_name`
- * @param WP_REST_Request $request
- * @param string $object_type Should always match `->object_type`
+ * @param mixed $value The new value for the field.
+ * @param mixed $object_data Probably a WordPress object (e.g., WP_Post).
+ * @param string $field_name Should always match `->field_name`.
+ * @param WP_REST_Request $request WP API request.
+ * @param string $object_type Should always match `->object_type`.
* @return void|WP_Error
*/
- final public function update_from_request( $value, $object_data, $field_name, $request, $object_type ) {
+ final public function update_from_request( $value, $object_data, $field_name, $request, $object_type ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$permission_check = $this->update_permission_check( $value, $object_data, $request );
if ( ! $permission_check ) {
- /* translators: %s: update_permission_check() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::update_permission_check', sprintf( __( "Method '%s' must return either true or WP_Error.", 'jetpack' ), 'update_permission_check' ), 'Jetpack 6.8' );
- /* translators: %s: the name of an API response field */
- return new WP_Error( 'invalid_user_permission', sprintf( __( "You are not allowed to access the '%s' field.", 'jetpack' ), $this->field_name ) );
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::update_permission_check',
+ sprintf(
+ /* translators: %s: update_permission_check() */
+ esc_html__( "Method '%s' must return either true or WP_Error.", 'jetpack' ),
+ 'update_permission_check'
+ ),
+ 'jetpack-6.8'
+ );
+
+ return new WP_Error(
+ 'invalid_user_permission',
+ sprintf(
+ /* translators: %s: the name of an API response field */
+ __( "You are not allowed to access the '%s' field.", 'jetpack' ),
+ $this->field_name
+ )
+ );
}
if ( is_wp_error( $permission_check ) ) {
@@ -170,50 +235,83 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
* Permission Check for the field's getter. Must be implemented in the inheriting class.
*
* @param mixed $object_data Whatever the endpoint would return for its response.
- * @param WP_REST_Request $request
+ * @param WP_REST_Request $request WP API request.
+ *
* @return true|WP_Error
*/
- public function get_permission_check( $object_data, $request ) {
- /* translators: %s: get_permission_check() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::get_permission_check', sprintf( __( "Method '%s' must be overridden.", 'jetpack' ), __METHOD__ ), 'Jetpack 6.8' );
+ public function get_permission_check( $object_data, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::get_permission_check',
+ sprintf(
+ /* translators: %s: method name. */
+ esc_html__( "Method '%s' must be overridden.", 'jetpack' ),
+ __METHOD__
+ ),
+ 'jetpack-6.8'
+ );
+ return null;
}
/**
* The field's "raw" getter. Must be implemented in the inheriting class.
*
* @param mixed $object_data Whatever the endpoint would return for its response.
- * @param WP_REST_Request $request
+ * @param WP_REST_Request $request WP API request.
* @return mixed
*/
- public function get( $object_data, $request ) {
- /* translators: %s: get() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::get', sprintf( __( "Method '%s' must be overridden.", 'jetpack' ), __METHOD__ ), 'Jetpack 6.8' );
+ public function get( $object_data, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::get',
+ sprintf(
+ /* translators: %s: method name. */
+ esc_html__( "Method '%s' must be overridden.", 'jetpack' ),
+ __METHOD__
+ ),
+ 'jetpack-6.8'
+ );
}
/**
* Permission Check for the field's setter. Must be implemented in the inheriting class.
*
* @param mixed $value The new value for the field.
- * @param mixed $object_data Probably a WordPress object (e.g., WP_Post)
- * @param WP_REST_Request $request
+ * @param mixed $object_data Probably a WordPress object (e.g., WP_Post).
+ * @param WP_REST_Request $request WP API request.
+ *
* @return true|WP_Error
*/
- public function update_permission_check( $value, $object_data, $request ) {
- /* translators: %s: update_permission_check() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::update_permission_check', sprintf( __( "Method '%s' must be overridden.", 'jetpack' ), __METHOD__ ), 'Jetpack 6.8' );
+ public function update_permission_check( $value, $object_data, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::update_permission_check',
+ sprintf(
+ /* translators: %s: method name. */
+ esc_html__( "Method '%s' must be overridden.", 'jetpack' ),
+ __METHOD__
+ ),
+ 'jetpack-6.8'
+ );
+ return null;
}
/**
* The field's "raw" setter. Must be implemented in the inheriting class.
*
* @param mixed $value The new value for the field.
- * @param mixed $object_data Probably a WordPress object (e.g., WP_Post)
- * @param WP_REST_Request $request
+ * @param mixed $object_data Probably a WordPress object (e.g., WP_Post).
+ * @param WP_REST_Request $request WP API request.
+ *
* @return mixed
*/
- public function update( $value, $object_data, $request ) {
- /* translators: %s: update() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::update', sprintf( __( "Method '%s' must be overridden.", 'jetpack' ), __METHOD__ ), 'Jetpack 6.8' );
+ public function update( $value, $object_data, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::update',
+ sprintf(
+ /* translators: %s: method name. */
+ esc_html__( "Method '%s' must be overridden.", 'jetpack' ),
+ __METHOD__
+ ),
+ 'jetpack-6.8'
+ );
}
/**
@@ -242,13 +340,23 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
* @return array
*/
public function get_schema() {
- /* translators: %s: get_schema() */
- _doing_it_wrong( 'WPCOM_REST_API_V2_Field_Controller::get_schema', sprintf( __( "Method '%s' must be overridden.", 'jetpack' ), __METHOD__ ), 'Jetpack 6.8' );
+ _doing_it_wrong(
+ 'WPCOM_REST_API_V2_Field_Controller::get_schema',
+ sprintf(
+ /* translators: %s: method name. */
+ esc_html__( "Method '%s' must be overridden.", 'jetpack' ),
+ __METHOD__
+ ),
+ 'jetpack-6.8'
+ );
+ return null;
}
/**
- * @param array $schema
- * @param string $context REST API Request context
+ * Ensure that our request matches its expected context.
+ *
+ * @param array $schema Schema to validate against.
+ * @param string $context REST API Request context.
* @return bool
*/
private function is_valid_for_context( $schema, $context ) {
@@ -274,9 +382,10 @@ abstract class WPCOM_REST_API_V2_Field_Controller {
*
* This function handles that recursion.
*
- * @param mixed $value
- * @param array $schema
- * @param string $context REST API Request context
+ * @param mixed $value Value passed to API request.
+ * @param array $schema Schema to validate against.
+ * @param string $context REST API Request context.
+ *
* @return mixed Filtered $value
*/
final public function filter_response_by_context( $value, $schema, $context ) {
diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php
index 04acfb91..5578bf33 100644
--- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php
+++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php
@@ -1,10 +1,16 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Tools to interact with Jetpack modules via API requests.
+ *
+ * @package automattic/jetpack
+ */
+use Automattic\Jetpack\Connection\REST_Connector;
+use Automattic\Jetpack\Plugins_Installer;
use Automattic\Jetpack\Status;
/**
* This is the base class for every Core API endpoint Jetpack uses.
- *
*/
class Jetpack_Core_API_Module_Toggle_Endpoint
extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
@@ -79,10 +85,12 @@ class Jetpack_Core_API_Module_Toggle_Endpoint
}
if ( Jetpack::activate_module( $module_slug, false, false ) ) {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => esc_html__( 'The requested Jetpack module was activated.', 'jetpack' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html__( 'The requested Jetpack module was activated.', 'jetpack' ),
+ )
+ );
}
return new WP_Error(
@@ -139,10 +147,12 @@ class Jetpack_Core_API_Module_Toggle_Endpoint
}
if ( Jetpack::deactivate_module( $module_slug ) ) {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => esc_html__( 'The requested Jetpack module was deactivated.', 'jetpack' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html__( 'The requested Jetpack module was deactivated.', 'jetpack' ),
+ )
+ );
}
return new WP_Error(
'deactivation_failed',
@@ -163,7 +173,13 @@ class Jetpack_Core_API_Module_Toggle_Endpoint
}
}
+/**
+ * Interact with multiple modules at once (list or activate).
+ *
+ * // phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
+ */
class Jetpack_Core_API_Module_List_Endpoint {
+ // phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound
/**
* A WordPress REST API callback method that accepts a request object and decides what to do with it.
@@ -190,7 +206,7 @@ class Jetpack_Core_API_Module_List_Endpoint {
* @return array Array of Jetpack modules.
*/
public function get_modules() {
- require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php' );
+ require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php';
$modules = Jetpack_Admin::init()->get_modules();
foreach ( $modules as $slug => $properties ) {
@@ -237,7 +253,7 @@ class Jetpack_Core_API_Module_List_Endpoint {
}
$activated = array();
- $failed = array();
+ $failed = array();
foreach ( $request['modules'] as $module ) {
if ( Jetpack::activate_module( $module, false, false ) ) {
@@ -248,10 +264,12 @@ class Jetpack_Core_API_Module_List_Endpoint {
}
if ( empty( $failed ) ) {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => esc_html__( 'All modules activated.', 'jetpack' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html__( 'All modules activated.', 'jetpack' ),
+ )
+ );
}
$error = '';
@@ -262,12 +280,15 @@ class Jetpack_Core_API_Module_List_Endpoint {
$activated_text = $activated_count > 1 ? sprintf(
/* Translators: first variable is a list followed by the last item, which is the second variable. Example: dog, cat and bird. */
__( '%1$s and %2$s', 'jetpack' ),
- join( ', ', $activated ), $activated_last ) : $activated_last;
+ join( ', ', $activated ),
+ $activated_last
+ ) : $activated_last;
$error = sprintf(
/* Translators: the variable is a module name. */
_n( 'The module %s was activated.', 'The modules %s were activated.', $activated_count, 'jetpack' ),
- $activated_text ) . ' ';
+ $activated_text
+ ) . ' ';
}
$failed_count = count( $failed );
@@ -276,12 +297,15 @@ class Jetpack_Core_API_Module_List_Endpoint {
$failed_text = $failed_count > 1 ? sprintf(
/* Translators: first variable is a list followed by the last item, which is the second variable. Example: dog, cat and bird. */
__( '%1$s and %2$s', 'jetpack' ),
- join( ', ', $failed ), $failed_last ) : $failed_last;
+ join( ', ', $failed ),
+ $failed_last
+ ) : $failed_last;
$error = sprintf(
/* Translators: the variable is a module name. */
_n( 'The module %s failed to be activated.', 'The modules %s failed to be activated.', $failed_count, 'jetpack' ),
- $failed_text ) . ' ';
+ $failed_text
+ ) . ' ';
}
return new WP_Error(
@@ -318,8 +342,11 @@ class Jetpack_Core_API_Module_List_Endpoint {
* @since 4.4.0 Renamed Jetpack_Core_API_Module_Endpoint from to Jetpack_Core_API_Data.
*
* @author Automattic
+ *
+ * // phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
*/
class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
+ // phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound
/**
* Process request by returning the module or updating it.
@@ -327,7 +354,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
*
* @since 4.3.0
*
- * @param WP_REST_Request $request
+ * @param WP_REST_Request $request WP API request.
*
* @return bool|mixed|void|WP_Error
*/
@@ -376,7 +403,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
$module['name'] = $i18n['name'];
}
if ( isset( $module['description'] ) ) {
- $module['description'] = $i18n['description'];
+ $module['description'] = $i18n['description'];
$module['short_description'] = $i18n['description'];
}
@@ -403,13 +430,13 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
$modules = Jetpack::get_available_modules();
if ( is_array( $modules ) && ! empty( $modules ) ) {
foreach ( $modules as $module ) {
- // Add all module options
+ // Add all module options.
$options = Jetpack_Core_Json_Api_Endpoints::prepare_options_for_response( $module );
foreach ( $options as $option_name => $option ) {
$response[ $option_name ] = $option['current_value'];
}
- // Add the module activation state
+ // Add the module activation state.
$response[ $module ] = Jetpack::is_module_active( $module );
}
}
@@ -424,7 +451,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
switch ( $setting ) {
case 'lang_id':
if ( ! current_user_can( 'install_languages' ) ) {
- // The user doesn't have caps to install language packs, so warn the client
+ // The user doesn't have caps to install language packs, so warn the client.
$response[ $setting ] = 'error_cap';
break;
}
@@ -511,7 +538,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
public function update_data( $request ) {
// If it's null, we're trying to update many module options from different modules.
- if ( is_null( $request['slug'] ) ) {
+ if ( $request['slug'] === null ) {
// 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.
@@ -526,13 +553,16 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
}
- // Get parameters to update the module. We can not simply use $request->get_params() because when we registered
- // this route, we are adding the entire output of Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list() to
- // the current request object's params. We are interested in body of the actual request.
- // This may be JSON:
+ /*
+ * Get parameters to update the module.
+ * We can not simply use $request->get_params() because when we registered this route,
+ * we are adding the entire output of Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list()
+ * to the current request object's params. We are interested in body of the actual request.
+ * This may be JSON:
+ */
$params = $request->get_json_params();
if ( ! is_array( $params ) ) {
- // Or it may be standard POST key-value pairs:
+ // Or it may be standard POST key-value pairs.
$params = $request->get_body_params();
}
@@ -551,24 +581,25 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
// Get available module options.
- $options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list( 'any' === $request['slug']
+ $options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list(
+ 'any' === $request['slug']
? $params
: $request['slug']
);
- // Prepare to toggle module if needed
+ // 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 ) );
+ $invalid = array_keys( array_diff_key( $params, $options ) );
$not_updated = array();
- // Remove invalid options
+ // 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',
+ 'code' => 'success',
'message' => esc_html__( 'The requested Jetpack data updates were successful.', 'jetpack' ),
);
@@ -595,7 +626,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
&& 'already_inactive' === $toggle_result->get_error_code()
) {
- // If the module is already inactive, we don't fail
+ // If the module is already inactive, we don't fail.
$updated = true;
} elseif ( is_wp_error( $toggle_result ) ) {
$error = $toggle_result->get_error_message();
@@ -603,7 +634,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
$updated = true;
}
} else {
- $error = Jetpack_Core_Json_Api_Endpoints::$user_permissions_error_msg;
+ $error = REST_Connector::get_user_permissions_error_msg();
}
// The module was not toggled.
@@ -639,7 +670,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
&& ! Jetpack::is_module_active( $option_attrs['jp_group'] )
) {
- // We only take note of skipped options when updating one module
+ // We only take note of skipped options when updating one module.
$not_updated[ $option ] = esc_html__( 'The requested Jetpack module is inactive.', 'jetpack' );
continue;
}
@@ -651,26 +682,26 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
switch ( $option ) {
case 'lang_id':
if ( ! current_user_can( 'install_languages' ) ) {
- // We can't affect this setting
+ // We can't affect this setting.
$updated = false;
break;
}
- if ( $value === 'en_US' || empty( $value ) ) {
+ if ( 'en_US' === $value || empty( $value ) ) {
return delete_option( 'WPLANG' );
}
if ( ! function_exists( 'request_filesystem_credentials' ) ) {
- require_once( ABSPATH . 'wp-admin/includes/file.php' );
+ require_once ABSPATH . 'wp-admin/includes/file.php';
}
if ( ! function_exists( 'wp_download_language_pack' ) ) {
require_once ABSPATH . 'wp-admin/includes/translation-install.php';
}
- // `wp_download_language_pack` only tries to download packs if they're not already available
+ // `wp_download_language_pack` only tries to download packs if they're not already available.
$language = wp_download_language_pack( $value );
- if ( $language === false ) {
+ if ( false === $language ) {
// The language pack download failed.
$updated = false;
break;
@@ -690,9 +721,9 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
// If we got an email address (create or regenerate) or 1 (delete), consider it done.
if ( is_string( $result ) && preg_match( '/[a-z0-9]+@post.wordpress.com/', $result ) ) {
- $response[$option] = $result;
- $updated = true;
- } elseif ( 1 == $result ) {
+ $response[ $option ] = $result;
+ $updated = true;
+ } elseif ( 1 == $result ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
$updated = true;
} elseif ( is_array( $result ) && isset( $result['message'] ) ) {
$error = $result['message'];
@@ -701,7 +732,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
case 'jetpack_protect_key':
$protect = Jetpack_Protect_Module::instance();
- if ( 'create' == $value ) {
+ if ( 'create' === $value ) {
$result = $protect->get_protect_key();
} else {
$result = false;
@@ -709,8 +740,8 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
// If we got one of Protect keys, consider it done.
if ( preg_match( '/[a-z0-9]{40,}/i', $result ) ) {
- $response[$option] = $result;
- $updated = true;
+ $response[ $option ] = $result;
+ $updated = true;
}
break;
@@ -728,28 +759,34 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
case 'show_headline':
case 'show_thumbnails':
- $grouped_options = $grouped_options_current = (array) Jetpack_Options::get_option( 'relatedposts' );
- $grouped_options[$option] = $value;
+ $grouped_options_current = (array) Jetpack_Options::get_option( 'relatedposts' );
+ $grouped_options = $grouped_options_current;
+ $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;
+ $updated = $grouped_options_current !== $grouped_options ? Jetpack_Options::update_option( 'relatedposts', $grouped_options ) : true;
break;
case 'search_auto_config':
if ( ! $value ) {
+ // Skip execution if no value is specified.
$updated = true;
- } elseif ( class_exists( 'Jetpack_Search' ) ) {
- $jps = Jetpack_Search::instance();
- if ( is_a( $jps, 'Jetpack_Instant_Search' ) ) {
- $jps->auto_config_search();
- $updated = true;
- } else {
- $updated = new WP_Error( 'instant_search_disabled', 'Instant Search Disabled', array( 'status' => 400 ) );
+ } else {
+ $plan = new Automattic\Jetpack\Search\Plan();
+ if ( ! $plan->supports_instant_search() ) {
+ $updated = new WP_Error( 'instant_search_not_supported', 'Instant Search is not supported by this site', array( 'status' => 400 ) );
$error = $updated->get_error_message();
+ } else {
+ if ( ! Automattic\Jetpack\Search\Options::is_instant_enabled() ) {
+ $updated = new WP_Error( 'instant_search_disabled', 'Instant Search is disabled', array( 'status' => 400 ) );
+ $error = $updated->get_error_message();
+ } else {
+ $blog_id = Automattic\Jetpack\Search\Helper::get_wpcom_site_id();
+ $instance = Automattic\Jetpack\Search\Instant_Search::instance( $blog_id );
+ $instance->auto_config_search();
+ $updated = true;
+ }
}
- } else {
- $updated = new WP_Error( 'search_disabled', 'Search Disabled', array( 'status' => 400 ) );
- $error = $updated->get_error_message();
}
break;
@@ -758,9 +795,10 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
case 'pinterest':
case 'yandex':
case 'facebook':
- $grouped_options = $grouped_options_current = (array) get_option( 'verification_services_codes' );
+ $grouped_options_current = (array) get_option( 'verification_services_codes' );
+ $grouped_options = $grouped_options_current;
- // Extracts the content attribute from the HTML meta tag if needed
+ // Extracts the content attribute from the HTML meta tag if needed.
if ( preg_match( '#.*<meta name="(?:[^"]+)" content="([^"]+)" />.*#i', $value, $matches ) ) {
$grouped_options[ $option ] = $matches[1];
} else {
@@ -768,56 +806,60 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
// If option value was the same, consider it done.
- $updated = $grouped_options_current != $grouped_options ? update_option( 'verification_services_codes', $grouped_options ) : true;
+ $updated = $grouped_options_current !== $grouped_options
+ ? update_option( 'verification_services_codes', $grouped_options )
+ : true;
break;
case 'sharing_services':
- if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) {
+ if ( ! class_exists( 'Sharing_Service' ) && ! include_once 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;
+ $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_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) {
+ if ( ! class_exists( 'Sharing_Service' ) && ! include_once JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) {
break;
}
- $sharer = new Sharing_Service();
- $grouped_options = $sharer->get_global_options();
+ $sharer = new Sharing_Service();
+ $grouped_options = $sharer->get_global_options();
$grouped_options[ $option ] = $value;
- $updated = $sharer->set_global_options( $grouped_options );
+ $updated = $sharer->set_global_options( $grouped_options );
break;
case 'custom':
- if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) {
+ if ( ! class_exists( 'Sharing_Service' ) && ! include_once JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) {
break;
}
- $sharer = new Sharing_Service();
+ $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;
+ // Return new custom service.
+ $response[ $option ] = $updated;
break;
case 'sharing_delete_service':
- if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) {
+ if ( ! class_exists( 'Sharing_Service' ) && ! include_once JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) {
break;
}
- $sharer = new Sharing_Service();
+ $sharer = new Sharing_Service();
$updated = $sharer->delete_service( $value );
break;
case 'jetpack-twitter-cards-site-tag':
- $value = trim( ltrim( strip_tags( $value ), '@' ) );
+ $value = trim( ltrim( wp_strip_all_tags( $value ), '@' ) );
$updated = get_option( $option ) !== $value ? update_option( $option, $value ) : true;
break;
@@ -828,36 +870,41 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
case 'do_not_track':
case 'version':
case 'collapse_nudges':
- $grouped_options = $grouped_options_current = (array) get_option( 'stats_options' );
- $grouped_options[$option] = $value;
+ $grouped_options_current = (array) get_option( 'stats_options' );
+ $grouped_options = $grouped_options_current;
+ $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;
+ $updated = $grouped_options_current !== $grouped_options
+ ? update_option( 'stats_options', $grouped_options )
+ : true;
break;
case 'akismet_show_user_comments_approved':
-
- // Save Akismet option '1' or '0' like it's done in akismet/class.akismet-admin.php
- $updated = get_option( $option ) != $value ? update_option( $option, (bool) $value ? '1' : '0' ) : true;
+ // Save Akismet option '1' or '0' like it's done in akismet/class.akismet-admin.php.
+ $updated = get_option( $option ) != $value // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual
+ ? update_option( $option, $value ? '1' : '0' )
+ : true;
break;
case 'wordpress_api_key':
-
if ( ! file_exists( WP_PLUGIN_DIR . '/akismet/class.akismet.php' ) ) {
- $error = esc_html__( 'Please install Akismet.', 'jetpack' );
+ $error = esc_html__( 'Please install Akismet.', 'jetpack' );
$updated = false;
break;
}
if ( ! defined( 'AKISMET_VERSION' ) ) {
- $error = esc_html__( 'Please activate Akismet.', 'jetpack' );
+ $error = esc_html__( 'Please activate Akismet.', 'jetpack' );
$updated = false;
break;
}
- // Allow to clear the API key field
+ // Allow to clear the API key field.
if ( '' === $value ) {
- $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true;
+ $updated = get_option( $option ) !== $value
+ ? update_option( $option, $value )
+ : true;
break;
}
@@ -868,8 +915,10 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
if ( Akismet::verify_key( $value ) === 'valid' ) {
$akismet_user = Akismet_Admin::get_akismet_user( $value );
if ( $akismet_user ) {
- if ( in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) ) ) {
- $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true;
+ if ( in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ), true ) ) {
+ $updated = get_option( $option ) !== $value
+ ? update_option( $option, $value )
+ : true;
break;
} else {
$error = esc_html__( "Akismet user status doesn't allow to update the key", 'jetpack' );
@@ -887,27 +936,36 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
break;
case 'google_analytics_tracking_id':
- $grouped_options = $grouped_options_current = (array) get_option( 'jetpack_wga' );
- $grouped_options[ 'code' ] = $value;
+ $grouped_options_current = (array) get_option( 'jetpack_wga' );
+ $grouped_options = $grouped_options_current;
+ $grouped_options['code'] = $value;
// If option value was the same, consider it done.
- $updated = $grouped_options_current != $grouped_options ? update_option( 'jetpack_wga', $grouped_options ) : true;
+ $updated = $grouped_options_current !== $grouped_options
+ ? update_option( 'jetpack_wga', $grouped_options )
+ : true;
break;
case 'dismiss_dash_app_card':
case 'dismiss_empty_stats_card':
// If option value was the same, consider it done.
- $updated = get_option( $option ) != $value ? update_option( $option, (bool) $value ) : true;
+ $updated = get_option( $option ) != $value // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual -- ensure we support bools or strings saved by update_option.
+ ? update_option( $option, (bool) $value )
+ : true;
break;
case 'onboarding':
jetpack_require_lib( 'widgets' );
// Break apart and set Jetpack onboarding options.
- $result = $this->_process_onboarding( (array) $value );
+ $result = $this->process_onboarding( (array) $value );
if ( empty( $result ) ) {
$updated = true;
} else {
- $error = sprintf( esc_html__( 'Onboarding failed to process: %s', 'jetpack' ), $result );
+ $error = sprintf(
+ /* Translators: placeholder is a list of error codes. */
+ esc_html__( 'Onboarding failed to process: %s', 'jetpack' ),
+ $result
+ );
$updated = false;
}
break;
@@ -919,9 +977,15 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
$updated = (string) get_option( $option ) !== (string) $sub_value ? update_option( $option, $sub_value ) : true;
break;
+ case 'jetpack_blocks_disabled':
+ $updated = (bool) get_option( $option ) !== (bool) $value ? update_option( $option, (bool) $value ) : true;
+ break;
+
default:
// If option value was the same, consider it done.
- $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true;
+ $updated = get_option( $option ) != $value // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual -- ensure we support scalars or strings saved by update_option.
+ ? update_option( $option, $value )
+ : true;
break;
}
@@ -935,9 +999,9 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
// The option was updated.
return rest_ensure_response( $response );
} else {
- $invalid_count = count( $invalid );
+ $invalid_count = count( $invalid );
$not_updated_count = count( $not_updated );
- $error = '';
+ $error = '';
if ( $invalid_count > 0 ) {
$error = sprintf(
/* Translators: the plural variable is a comma-separated list. Example: dog, cat, bird. */
@@ -952,7 +1016,9 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
$not_updated_messages[] = sprintf(
/* Translators: the first variable is a module option or slug, or setting. The second is the error message . */
__( '%1$s: %2$s', 'jetpack' ),
- $not_updated_option, $not_updated_message );
+ $not_updated_option,
+ $not_updated_message
+ );
}
}
if ( ! empty( $error ) ) {
@@ -961,7 +1027,6 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
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 ) );
@@ -978,7 +1043,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
*
* @return string Result of onboarding processing and, if there is one, an error message.
*/
- private function _process_onboarding( $data ) {
+ private function process_onboarding( $data ) {
if ( isset( $data['end'] ) && $data['end'] ) {
return Jetpack::invalidate_onboarding_token()
? ''
@@ -989,69 +1054,102 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
if ( ! empty( $data['siteTitle'] ) ) {
// If option value was the same, consider it done.
- if ( ! ( update_option( 'blogname', $data['siteTitle'] ) || get_option( 'blogname' ) == $data['siteTitle'] ) ) {
+ if ( ! (
+ update_option( 'blogname', $data['siteTitle'] )
+ || get_option( 'blogname' ) === $data['siteTitle']
+ ) ) {
$error[] = 'siteTitle';
}
}
if ( isset( $data['siteDescription'] ) ) {
// If option value was the same, consider it done.
- if ( ! ( update_option( 'blogdescription', $data['siteDescription'] ) || get_option( 'blogdescription' ) == $data['siteDescription'] ) ) {
+ if ( ! (
+ update_option( 'blogdescription', $data['siteDescription'] )
+ || get_option( 'blogdescription' ) === $data['siteDescription']
+ ) ) {
$error[] = 'siteDescription';
}
}
$site_title = get_option( 'blogname' );
- $author = get_current_user_id() || 1;
+ $author = get_current_user_id() || 1;
if ( ! empty( $data['siteType'] ) ) {
- if ( ! ( update_option( 'jpo_site_type', $data['siteType'] ) || get_option( 'jpo_site_type' ) == $data['siteType'] ) ) {
+ if ( ! (
+ update_option( 'jpo_site_type', $data['siteType'] )
+ || get_option( 'jpo_site_type' ) === $data['siteType']
+ ) ) {
$error[] = 'siteType';
}
}
if ( isset( $data['homepageFormat'] ) ) {
- // If $data['homepageFormat'] is 'posts', we have nothing to do since it's WordPress' default
- // if it exists, just update
+ /*
+ * If $data['homepageFormat'] is 'posts',
+ * we have nothing to do since it's WordPress' default
+ * if it exists, just update
+ */
$homepage_format = get_option( 'jpo_homepage_format' );
if ( ! $homepage_format || $homepage_format !== $data['homepageFormat'] ) {
if ( 'page' === $data['homepageFormat'] ) {
- if ( ! ( update_option( 'show_on_front', 'page' ) || get_option( 'show_on_front' ) == 'page' ) ) {
+ if ( ! (
+ update_option( 'show_on_front', 'page' )
+ || get_option( 'show_on_front' ) === 'page'
+ ) ) {
$error[] = 'homepageFormat';
}
- $home = wp_insert_post( array(
- 'post_type' => 'page',
- /* translators: this references the home page of a site, also called front page. */
- 'post_title' => esc_html_x( 'Home Page', 'The home page of a website.', 'jetpack' ),
- 'post_content' => sprintf( esc_html__( 'Welcome to %s.', 'jetpack' ), $site_title ),
- 'post_status' => 'publish',
- 'post_author' => $author,
- ) );
- if ( 0 == $home ) {
+ $home = wp_insert_post(
+ array(
+ 'post_type' => 'page',
+ /* translators: this references the home page of a site, also called front page. */
+ 'post_title' => esc_html_x( 'Home Page', 'The home page of a website.', 'jetpack' ),
+ 'post_content' => sprintf(
+ /* Translators: placeholder is the site title. */
+ esc_html__( 'Welcome to %s.', 'jetpack' ),
+ $site_title
+ ),
+ 'post_status' => 'publish',
+ 'post_author' => $author,
+ )
+ );
+ if ( 0 === $home ) {
$error[] = 'home insert: 0';
} elseif ( is_wp_error( $home ) ) {
- $error[] = 'home creation: '. $home->get_error_message();
+ $error[] = 'home creation: ' . $home->get_error_message();
}
- if ( ! ( update_option( 'page_on_front', $home ) || get_option( 'page_on_front' ) == $home ) ) {
+ if ( ! (
+ update_option( 'page_on_front', $home )
+ || get_option( 'page_on_front' ) === $home
+ ) ) {
$error[] = 'home set';
}
- $blog = wp_insert_post( array(
- 'post_type' => 'page',
- /* translators: this references the page where blog posts are listed. */
- 'post_title' => esc_html_x( 'Blog', 'The blog of a website.', 'jetpack' ),
- 'post_content' => sprintf( esc_html__( 'These are the latest posts in %s.', 'jetpack' ), $site_title ),
- 'post_status' => 'publish',
- 'post_author' => $author,
- ) );
- if ( 0 == $blog ) {
+ $blog = wp_insert_post(
+ array(
+ 'post_type' => 'page',
+ /* translators: this references the page where blog posts are listed. */
+ 'post_title' => esc_html_x( 'Blog', 'The blog of a website.', 'jetpack' ),
+ 'post_content' => sprintf(
+ /* Translators: placeholder is the site title. */
+ esc_html__( 'These are the latest posts in %s.', 'jetpack' ),
+ $site_title
+ ),
+ 'post_status' => 'publish',
+ 'post_author' => $author,
+ )
+ );
+ if ( 0 === $blog ) {
$error[] = 'blog insert: 0';
} elseif ( is_wp_error( $blog ) ) {
- $error[] = 'blog creation: '. $blog->get_error_message();
+ $error[] = 'blog creation: ' . $blog->get_error_message();
}
- if ( ! ( update_option( 'page_for_posts', $blog ) || get_option( 'page_for_posts' ) == $blog ) ) {
+ if ( ! (
+ update_option( 'page_for_posts', $blog )
+ || get_option( 'page_for_posts' ) === $blog
+ ) ) {
$error[] = 'blog set';
}
} else {
@@ -1069,7 +1167,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
update_option( 'jpo_homepage_format', $data['homepageFormat'] );
}
- // Setup contact page and add a form and/or business info
+ // Setup contact page and add a form and/or business info.
$contact_page = '';
if ( ! empty( $data['addContactForm'] ) && ! get_option( 'jpo_contact_page' ) ) {
$contact_form_module_active = Jetpack::is_module_active( 'contact-form' );
@@ -1089,18 +1187,20 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
if ( ! empty( $contact_page ) ) {
- $form = wp_insert_post( array(
- 'post_type' => 'page',
- /* translators: this references a page with contact details and possibly a form. */
- 'post_title' => esc_html_x( 'Contact us', 'Contact page for your website.', 'jetpack' ),
- 'post_content' => esc_html__( 'Send us a message!', 'jetpack' ) . "\n" . $contact_page,
- 'post_status' => 'publish',
- 'post_author' => $author,
- ) );
- if ( 0 == $form ) {
+ $form = wp_insert_post(
+ array(
+ 'post_type' => 'page',
+ /* translators: this references a page with contact details and possibly a form. */
+ 'post_title' => esc_html_x( 'Contact us', 'Contact page for your website.', 'jetpack' ),
+ 'post_content' => esc_html__( 'Send us a message!', 'jetpack' ) . "\n" . $contact_page,
+ 'post_status' => 'publish',
+ 'post_author' => $author,
+ )
+ );
+ if ( 0 === $form ) {
$error[] = 'form insert: 0';
} elseif ( is_wp_error( $form ) ) {
- $error[] = 'form creation: '. $form->get_error_message();
+ $error[] = 'form creation: ' . $form->get_error_message();
} else {
update_option( 'jpo_contact_page', $form );
}
@@ -1114,9 +1214,8 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
if ( ! empty( $data['installWooCommerce'] ) ) {
- jetpack_require_lib( 'plugins' );
- $wc_install_result = Jetpack_Plugins::install_and_activate_plugin( 'woocommerce' );
- delete_transient( '_wc_activation_redirect' ); // Redirecting to WC setup would kill our users' flow
+ $wc_install_result = Plugins_Installer::install_and_activate_plugin( 'woocommerce' );
+ delete_transient( '_wc_activation_redirect' ); // Redirecting to WC setup would kill our users' flow.
if ( is_wp_error( $wc_install_result ) ) {
$error[] = 'woocommerce installation';
}
@@ -1148,8 +1247,8 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
* @param array $address Array of business address fields.
*
* @return WP_Error|true True if the data was saved correctly.
- */
- static function handle_business_address( $address ) {
+ */
+ private static function handle_business_address( $address ) {
$first_sidebar = Jetpack_Widgets::get_first_sidebar();
$widgets_module_active = Jetpack::is_module_active( 'widgets' );
@@ -1161,11 +1260,11 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
if ( $first_sidebar ) {
- $title = isset( $address['name'] ) ? sanitize_text_field( $address['name'] ) : '';
- $street = isset( $address['street'] ) ? sanitize_text_field( $address['street'] ) : '';
- $city = isset( $address['city'] ) ? sanitize_text_field( $address['city'] ) : '';
- $state = isset( $address['state'] ) ? sanitize_text_field( $address['state'] ) : '';
- $zip = isset( $address['zip'] ) ? sanitize_text_field( $address['zip'] ) : '';
+ $title = isset( $address['name'] ) ? sanitize_text_field( $address['name'] ) : '';
+ $street = isset( $address['street'] ) ? sanitize_text_field( $address['street'] ) : '';
+ $city = isset( $address['city'] ) ? sanitize_text_field( $address['city'] ) : '';
+ $state = isset( $address['state'] ) ? sanitize_text_field( $address['state'] ) : '';
+ $zip = isset( $address['zip'] ) ? sanitize_text_field( $address['zip'] ) : '';
$country = isset( $address['country'] ) ? sanitize_text_field( $address['country'] ) : '';
$full_address = implode( ' ', array_filter( array( $street, $city, $state, $zip, $country ) ) );
@@ -1176,12 +1275,12 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
'phone' => '',
'hours' => '',
'showmap' => false,
- 'email' => ''
+ 'email' => '',
);
$widget_updated = '';
if ( ! self::has_business_address_widget( $first_sidebar ) ) {
- $widget_updated = Jetpack_Widgets::insert_widget_in_sidebar( 'widget_contact_info', $widget_options, $first_sidebar );
+ $widget_updated = Jetpack_Widgets::insert_widget_in_sidebar( 'widget_contact_info', $widget_options, $first_sidebar );
} else {
$widget_updated = Jetpack_Widgets::update_widget_in_sidebar( 'widget_contact_info', $widget_options, $first_sidebar );
}
@@ -1190,29 +1289,29 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
$address_save = array(
- 'name' => $title,
- 'street' => $street,
- 'city' => $city,
- 'state' => $state,
- 'zip' => $zip,
- 'country' => $country
+ 'name' => $title,
+ 'street' => $street,
+ 'city' => $city,
+ 'state' => $state,
+ 'zip' => $zip,
+ 'country' => $country,
);
update_option( 'jpo_business_address', $address_save );
return true;
}
- // No sidebar to place the widget
+ // No sidebar to place the widget.
return new WP_Error( 'sidebar_not_found', 'No sidebar.', 400 );
}
/**
* Check whether "Contact Info & Map" widget is present in a given sidebar.
*
- * @param string $sidebar ID of the sidebar to which the widget will be added.
+ * @param string $sidebar ID of the sidebar to which the widget will be added.
*
* @return bool Whether the widget is present in a given sidebar.
- */
- static function has_business_address_widget( $sidebar ) {
+ */
+ private static function has_business_address_widget( $sidebar ) {
$sidebars_widgets = get_option( 'sidebars_widgets', array() );
if ( ! isset( $sidebars_widgets[ $sidebar ] ) ) {
return false;
@@ -1251,7 +1350,7 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
$options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list( $params );
foreach ( $options as $option => $definition ) {
- if ( in_array( $options[ $option ]['jp_group'], array( 'post-by-email' ) ) ) {
+ if ( in_array( $options[ $option ]['jp_group'], array( 'post-by-email' ), true ) ) {
$module = $options[ $option ]['jp_group'];
break;
}
@@ -1266,10 +1365,23 @@ class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
}
+/**
+ * Get detailed data from a specific module.
+ *
+ * phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
+ */
class Jetpack_Core_API_Module_Data_Endpoint {
+ // phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
+ /**
+ * Process request and return different data based on the module we are interested in.
+ *
+ * @param WP_REST_Request $request WP API request.
+ *
+ * @return WP_REST_Response|WP_Error A REST response if the request was served successfully, otherwise an error.
+ */
public function process( $request ) {
- switch( $request['slug'] ) {
+ switch ( $request['slug'] ) {
case 'protect':
return $this->get_protect_data();
case 'stats':
@@ -1290,12 +1402,12 @@ class Jetpack_Core_API_Module_Data_Endpoint {
*
* @since 4.8.0
*
- * @param WP_REST_Request $request
+ * @param WP_REST_Request $request WP API request.
*
* @return bool
*/
public function key_check( $request ) {
- switch( $request['service'] ) {
+ switch ( $request['service'] ) {
case 'akismet':
$params = $request->get_json_params();
if ( isset( $params['api_key'] ) && ! empty( $params['api_key'] ) ) {
@@ -1353,26 +1465,32 @@ class Jetpack_Core_API_Module_Data_Endpoint {
public function check_akismet_key( $api_key = '' ) {
$akismet_status = $this->akismet_class_exists();
if ( is_wp_error( $akismet_status ) ) {
- return rest_ensure_response( array(
- 'validKey' => false,
- 'invalidKeyCode' => $akismet_status->get_error_code(),
- 'invalidKeyMessage' => $akismet_status->get_error_message(),
- ) );
+ return rest_ensure_response(
+ array(
+ 'validKey' => false,
+ 'invalidKeyCode' => $akismet_status->get_error_code(),
+ 'invalidKeyMessage' => $akismet_status->get_error_message(),
+ )
+ );
}
$key_status = Akismet::check_key_status( empty( $api_key ) ? Akismet::get_api_key() : $api_key );
if ( ! $key_status || 'invalid' === $key_status || 'failed' === $key_status ) {
- return rest_ensure_response( array(
- 'validKey' => false,
- 'invalidKeyCode' => 'invalid_key',
- 'invalidKeyMessage' => esc_html__( 'Invalid Akismet key. Please contact support.', 'jetpack' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'validKey' => false,
+ 'invalidKeyCode' => 'invalid_key',
+ 'invalidKeyMessage' => esc_html__( 'Invalid Akismet key. Please contact support.', 'jetpack' ),
+ )
+ );
}
- return rest_ensure_response( array(
- 'validKey' => isset( $key_status[1] ) && 'valid' === $key_status[1]
- ) );
+ return rest_ensure_response(
+ array(
+ 'validKey' => isset( $key_status[1] ) && 'valid' === $key_status[1],
+ )
+ );
}
/**
@@ -1402,7 +1520,8 @@ class Jetpack_Core_API_Module_Data_Endpoint {
* @return bool|WP_Error True if Akismet is active and registered. Otherwise, a WP_Error instance with the corresponding error.
*/
private function akismet_is_active_and_registered() {
- if ( is_wp_error( $akismet_exists = $this->akismet_class_exists() ) ) {
+ $akismet_exists = $this->akismet_class_exists();
+ if ( is_wp_error( $akismet_exists ) ) {
return $akismet_exists;
}
@@ -1437,37 +1556,43 @@ class Jetpack_Core_API_Module_Data_Endpoint {
// If no parameters were passed.
if (
- empty ( $range )
+ empty( $range )
|| ! in_array( $range, array( 'day', 'week', 'month' ), true )
) {
$range = 'day';
}
if ( ! function_exists( 'stats_get_from_restapi' ) ) {
- require_once( JETPACK__PLUGIN_DIR . 'modules/stats.php' );
+ require_once JETPACK__PLUGIN_DIR . 'modules/stats.php';
}
switch ( $range ) {
- // This is always called first on page load
+ // This is always called first on page load.
case 'day':
$initial_stats = stats_get_from_restapi();
- return rest_ensure_response( array(
- 'general' => $initial_stats,
-
- // Build data for 'day' as if it was stats_get_from_restapi( array(), 'visits?unit=day&quantity=30' );
- 'day' => isset( $initial_stats->visits )
- ? $initial_stats->visits
- : array(),
- ) );
+ return rest_ensure_response(
+ array(
+ 'general' => $initial_stats,
+
+ // Build data for 'day' as if it was stats_get_from_restapi( array(), 'visits?unit=day&quantity=30' ).
+ 'day' => isset( $initial_stats->visits )
+ ? $initial_stats->visits
+ : array(),
+ )
+ );
case 'week':
- return rest_ensure_response( array(
- 'week' => stats_get_from_restapi( array(), 'visits?unit=week&quantity=14' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'week' => stats_get_from_restapi( array(), 'visits?unit=week&quantity=14' ),
+ )
+ );
case 'month':
- return rest_ensure_response( array(
- 'month' => stats_get_from_restapi( array(), 'visits?unit=month&quantity=12&' ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'month' => stats_get_from_restapi( array(), 'visits?unit=month&quantity=12&' ),
+ )
+ );
}
}
@@ -1491,16 +1616,20 @@ class Jetpack_Core_API_Module_Data_Endpoint {
$last_downtime = $monitor->monitor_get_last_downtime();
if ( is_wp_error( $last_downtime ) ) {
return $last_downtime;
- } else if ( false === strtotime( $last_downtime ) ) {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'date' => null,
- ) );
+ } elseif ( false === strtotime( $last_downtime ) ) {
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'date' => null,
+ )
+ );
} else {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'date' => human_time_diff( strtotime( $last_downtime ), strtotime( 'now' ) ),
- ) );
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'date' => human_time_diff( strtotime( $last_downtime ), strtotime( 'now' ) ),
+ )
+ );
}
}
@@ -1573,8 +1702,8 @@ class Jetpack_Core_API_Module_Data_Endpoint {
);
} else {
$copy_services = $services;
- $last = count( $copy_services ) - 1;
- $last_service = $copy_services[ $last ];
+ $last = count( $copy_services ) - 1;
+ $last_service = $copy_services[ $last ];
unset( $copy_services[ $last ] );
$message = esc_html(
sprintf(
@@ -1586,11 +1715,13 @@ class Jetpack_Core_API_Module_Data_Endpoint {
);
}
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => $message,
- 'services' => $services,
- ) );
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => $message,
+ 'services' => $services,
+ )
+ );
}
/**
@@ -1611,41 +1742,49 @@ class Jetpack_Core_API_Module_Data_Endpoint {
$vaultpress = new VaultPress();
if ( ! $vaultpress->is_registered() ) {
- return rest_ensure_response( array(
- 'code' => 'not_registered',
- 'message' => esc_html__( 'You need to register for VaultPress.', 'jetpack' )
- ) );
- }
-
- $data = json_decode( base64_decode( $vaultpress->contact_service( 'plugin_data' ) ) );
- if ( false == $data ) {
- return rest_ensure_response( array(
- 'code' => 'not_registered',
- 'message' => esc_html__( 'Could not connect to VaultPress.', 'jetpack' )
- ) );
- } else if ( is_wp_error( $data ) || ! isset( $data->backups->last_backup ) ) {
+ return rest_ensure_response(
+ array(
+ 'code' => 'not_registered',
+ 'message' => esc_html__( 'You need to register for VaultPress.', 'jetpack' ),
+ )
+ );
+ }
+
+ $data = json_decode( base64_decode( $vaultpress->contact_service( 'plugin_data' ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
+ if ( false === $data ) {
+ return rest_ensure_response(
+ array(
+ 'code' => 'not_registered',
+ 'message' => esc_html__( 'Could not connect to VaultPress.', 'jetpack' ),
+ )
+ );
+ } elseif ( is_wp_error( $data ) || ! isset( $data->backups->last_backup ) ) {
return $data;
- } else if ( empty( $data->backups->last_backup ) ) {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => esc_html__( 'VaultPress is active and will back up your site soon.', 'jetpack' ),
- 'data' => $data,
- ) );
+ } elseif ( empty( $data->backups->last_backup ) ) {
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html__( 'VaultPress is active and will back up your site soon.', 'jetpack' ),
+ 'data' => $data,
+ )
+ );
} else {
- return rest_ensure_response( array(
- 'code' => 'success',
- 'message' => esc_html(
- sprintf(
- /* translators: placeholder is a unit of time (1 hour, 5 days, ...) */
- esc_html__( 'Your site was successfully backed up %s ago.', 'jetpack' ),
- human_time_diff(
- $data->backups->last_backup,
- current_time( 'timestamp' )
+ return rest_ensure_response(
+ array(
+ 'code' => 'success',
+ 'message' => esc_html(
+ sprintf(
+ /* translators: placeholder is a unit of time (1 hour, 5 days, ...) */
+ esc_html__( 'Your site was successfully backed up %s ago.', 'jetpack' ),
+ human_time_diff(
+ $data->backups->last_backup,
+ current_time( 'timestamp' ) // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested -- We cannot switch to time() or another "unix" timestamp option as long as $data->backups->last_backup uses WP timestamps.
+ )
)
- )
- ),
- 'data' => $data,
- ) );
+ ),
+ 'data' => $data,
+ )
+ );
}
}
diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
index 10ae6ca8..f820a6f9 100644
--- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
+++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php
@@ -237,17 +237,19 @@ class Jetpack_Core_API_Site_Endpoint {
}
// Number of VideoPress videos on the site.
- $videopress_attachments = wp_count_attachments( 'video/videopress' );
- if (
- isset( $videopress_attachments->{'video/videopress'} )
- && $videopress_attachments->{'video/videopress'} > 0
- ) {
- $benefits[] = array(
- 'name' => 'video-hosting',
- 'title' => esc_html__( 'Video Hosting', 'jetpack' ),
- 'description' => esc_html__( 'Ad-free, lightning-fast videos delivered by Jetpack', 'jetpack' ),
- 'value' => absint( $videopress_attachments->{'video/videopress'} ),
- );
+ if ( Jetpack::is_module_active( 'videopress' ) ) {
+ $videopress_attachments = wp_count_attachments( 'video/videopress' );
+ if (
+ isset( $videopress_attachments->{'video/videopress'} )
+ && $videopress_attachments->{'video/videopress'} > 0
+ ) {
+ $benefits[] = array(
+ 'name' => 'video-hosting',
+ 'title' => esc_html__( 'Video Hosting', 'jetpack' ),
+ 'description' => esc_html__( 'Ad-free, lightning-fast videos delivered by Jetpack', 'jetpack' ),
+ 'value' => absint( $videopress_attachments->{'video/videopress'} ),
+ );
+ }
}
// Number of active Publicize connections.
@@ -280,6 +282,14 @@ class Jetpack_Core_API_Site_Endpoint {
);
}
+ if ( Jetpack::is_module_active( 'search' ) && ! class_exists( 'Automattic\\Jetpack\\Search_Plugin\\Jetpack_Search_Plugin' ) ) {
+ $benefits[] = array(
+ 'name' => 'search',
+ 'title' => esc_html__( 'Search', 'jetpack' ),
+ 'description' => esc_html__( 'Help your visitors find exactly what they are looking for, fast', 'jetpack' ),
+ );
+ }
+
// Finally, return the whole list of benefits.
return rest_ensure_response(
array(
diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php
index ffd62bb3..a9ac3409 100644
--- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php
+++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-widgets-endpoints.php
@@ -1,11 +1,19 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
- * Widget information getter endpoint.
+ * Interact with a specific widget via the REST API.
+ * Currently only supports the Milestone widget.
*
+ * @package automattic/jetpack
+ */
+
+/**
+ * Widget information getter endpoint.
*/
class Jetpack_Core_API_Widget_Endpoint {
/**
+ * Get information about a widget that is supported by this endpoint.
+ *
* @since 5.5.0
*
* @param WP_REST_Request $request {
@@ -18,9 +26,9 @@ class Jetpack_Core_API_Widget_Endpoint {
*/
public function process( $request ) {
$widget_base = _get_widget_id_base( $request['id'] );
- $widget_id = (int) substr( $request['id'], strlen( $widget_base ) + 1 );
+ $widget_id = (int) substr( $request['id'], strlen( $widget_base ) + 1 );
- switch( $widget_base ) {
+ switch ( $widget_base ) {
case 'milestone_widget':
$instances = get_option( 'widget_milestone_widget', array() );
@@ -30,7 +38,7 @@ class Jetpack_Core_API_Widget_Endpoint {
&& isset( $instances[ $widget_id ] )
) {
$instance = $instances[ $widget_id ];
- $widget = new Milestone_Widget();
+ $widget = new Milestone_Widget();
return $widget->get_widget_data( $instance );
}
}
diff --git a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php
index abfc8627..cf72f709 100644
--- a/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php
+++ b/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php
@@ -1,7 +1,12 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* This is the base class for every Core API endpoint that needs an XMLRPC client.
*
+ * @package automattic/jetpack
+ */
+
+/**
+ * Base class for every Core API endpoint that needs an XMLRPC client.
*/
abstract class Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
@@ -14,10 +19,11 @@ abstract class Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
protected $xmlrpc;
/**
+ * Constructor.
*
* @since 4.3.0
*
- * @param Jetpack_IXR_Client $xmlrpc
+ * @param Jetpack_IXR_Client $xmlrpc Jetpack_IXR_Client instance.
*/
public function __construct( $xmlrpc = null ) {
$this->xmlrpc = $xmlrpc;
@@ -36,4 +42,4 @@ abstract class Jetpack_Core_API_XMLRPC_Consumer_Endpoint {
}
return false;
}
-} \ No newline at end of file
+}
diff --git a/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php b/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php
index 778600ef..2c9089a8 100644
--- a/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php
+++ b/plugins/jetpack/_inc/lib/core-api/load-wpcom-endpoints.php
@@ -1,11 +1,12 @@
<?php
-
-/*
+/**
* Loader for WP REST API endpoints that are synced with WP.com.
*
* On WP.com see:
* - wp-content/mu-plugins/rest-api.php
* - wp-content/rest-api-plugins/jetpack-endpoints/
+ *
+ * @package automattic/jetpack
*/
/**
@@ -15,8 +16,13 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
+/**
+ * Loop through endpoint files and load them.
+ *
+ * @param string $file_pattern Path pattern to the endpoints (pattern must be supported by glob()).
+ */
function wpcom_rest_api_v2_load_plugin_files( $file_pattern ) {
- $plugins = glob( dirname( __FILE__ ) . '/' . $file_pattern );
+ $plugins = glob( __DIR__ . '/' . $file_pattern );
if ( ! is_array( $plugins ) ) {
return;
@@ -27,20 +33,25 @@ function wpcom_rest_api_v2_load_plugin_files( $file_pattern ) {
}
}
-// API v2 plugins: define a class, then call this function.
+/**
+ * API v2 plugins: define a class, then call this function.
+ *
+ * @param string $class_name The name of the class to load.
+ */
function wpcom_rest_api_v2_load_plugin( $class_name ) {
global $wpcom_rest_api_v2_plugins;
if ( ! isset( $wpcom_rest_api_v2_plugins ) ) {
- $_GLOBALS['wpcom_rest_api_v2_plugins'] = $wpcom_rest_api_v2_plugins = array();
+ $wpcom_rest_api_v2_plugins = array();
+ $_GLOBALS['wpcom_rest_api_v2_plugins'] = array(); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase,VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
}
if ( ! isset( $wpcom_rest_api_v2_plugins[ $class_name ] ) ) {
- $wpcom_rest_api_v2_plugins[ $class_name ] = new $class_name;
+ $wpcom_rest_api_v2_plugins[ $class_name ] = new $class_name();
}
}
-require dirname( __FILE__ ) . '/class-wpcom-rest-field-controller.php';
+require __DIR__ . '/class-wpcom-rest-field-controller.php';
/**
* Load the REST API v2 plugin files during the plugins_loaded action.
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php
index 34798f8e..18d4491f 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/business-hours.php
@@ -1,4 +1,9 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Build localized strings for use with the Business Hours Block.
+ *
+ * @package automattic/jetpack
+ */
/**
* Business Hours: Localized week
@@ -6,22 +11,32 @@
* @since 7.1
*/
class WPCOM_REST_API_V2_Endpoint_Business_Hours extends WP_REST_Controller {
- function __construct() {
+ /**
+ * Constructor.
+ */
+ public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'business-hours';
// This endpoint *does not* need to connect directly to Jetpack sites.
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
+ /**
+ * Register endpoint route.
+ */
public function register_routes() {
- // GET /sites/<blog_id>/business-hours/localized-week - Return the localized
- register_rest_route( $this->namespace, '/' . $this->rest_base . '/localized-week', array(
+ // GET /sites/<blog_id>/business-hours/localized-week - Return the localized.
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/localized-week',
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_localized_week' ),
- 'permission_callback' => '__return_true',
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_localized_week' ),
+ 'permission_callback' => '__return_true',
+ ),
)
- ) );
+ );
}
/**
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-external-media.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-external-media.php
index b8b33d55..1fb0b79a 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-external-media.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-external-media.php
@@ -82,7 +82,7 @@ class WPCOM_REST_API_V2_Endpoint_External_Media extends WP_REST_Controller {
*
* @var string
*/
- private static $services_regex = '(?P<service>google_photos|pexels)';
+ private static $services_regex = '(?P<service>google_photos|openverse|pexels)';
/**
* Temporary filename.
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php
index 1c25bb2d..fb10ffab 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php
@@ -1,4 +1,10 @@
<?php
+/**
+ * API endpoints to interact with WordPress.com
+ * to get info from the Mailchimp API for use with the Mailchimp block.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Redirect;
@@ -11,6 +17,9 @@ use Automattic\Jetpack\Redirect;
* @since 7.1
*/
class WPCOM_REST_API_V2_Endpoint_Mailchimp extends WP_REST_Controller {
+ /**
+ * Constructor.
+ */
public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'mailchimp';
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-videopress.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-videopress.php
index a7046c12..b4b83ee8 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-videopress.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-videopress.php
@@ -31,7 +31,7 @@ class WPCOM_REST_API_V2_Endpoint_VideoPress extends WP_REST_Controller {
$this->rest_base . '/meta',
array(
'args' => array(
- 'id' => array(
+ 'id' => array(
'description' => __( 'The post id for the attachment.', 'jetpack' ),
'type' => 'int',
'required' => true,
@@ -39,36 +39,44 @@ class WPCOM_REST_API_V2_Endpoint_VideoPress extends WP_REST_Controller {
return is_numeric( $param );
},
),
- 'title' => array(
+ 'title' => array(
'description' => __( 'The title of the video.', 'jetpack' ),
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
- 'description' => array(
+ 'description' => array(
'description' => __( 'The description of the video.', 'jetpack' ),
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
- 'rating' => array(
+ 'rating' => array(
'description' => __( 'The video content rating. One of G, PG-13 or R-17', 'jetpack' ),
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
),
- 'display_embed' => array(
+ 'display_embed' => array(
'description' => __( 'Display the share menu in the player.', 'jetpack' ),
'type' => 'boolean',
'required' => false,
'sanitize_callback' => 'rest_sanitize_boolean',
),
- 'allow_download' => array(
+ 'allow_download' => array(
'description' => __( 'Display download option and allow viewers to download this video', 'jetpack' ),
'type' => 'boolean',
'required' => false,
'sanitize_callback' => 'rest_sanitize_boolean',
),
+ 'privacy_setting' => array(
+ 'description' => __( 'How to determine if the video should be public or private', 'jetpack' ),
+ 'type' => 'int',
+ 'required' => false,
+ 'validate_callback' => function ( $param ) {
+ return is_numeric( $param );
+ },
+ ),
),
'methods' => WP_REST_Server::EDITABLE,
'callback' => array( $this, 'videopress_block_update_meta' ),
@@ -163,6 +171,14 @@ class WPCOM_REST_API_V2_Endpoint_VideoPress extends WP_REST_Controller {
}
}
+ if ( isset( $json_params['privacy_setting'] ) ) {
+ $privacy_setting = $json_params['privacy_setting'];
+ if ( ! isset( $meta['videopress']['privacy_setting'] ) || $meta['videopress']['privacy_setting'] !== $privacy_setting ) {
+ $meta['videopress']['privacy_setting'] = $privacy_setting;
+ $should_update_meta = true;
+ }
+ }
+
if ( $should_update_meta ) {
wp_update_attachment_metadata( $post_id, $meta );
}
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php
index a10a4056..3f005a8c 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php
@@ -1,6 +1,12 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Interact with the list of available block editor extensions (blocks, plugins)
+ * made available by the Jetpack plugin.
+ *
+ * @package automattic/jetpack
+ */
-/*
+/**
* Gutenberg: List Available Gutenberg Extensions (Blocks and Plugins)
*
* [
@@ -14,23 +20,33 @@
* @since 6.9
*/
class WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions extends WP_REST_Controller {
- function __construct() {
- $this->namespace = 'wpcom/v2';
- $this->rest_base = 'gutenberg';
+ /**
+ * Constructor.
+ */
+ public function __construct() {
+ $this->namespace = 'wpcom/v2';
+ $this->rest_base = 'gutenberg';
$this->wpcom_is_site_specific_endpoint = true;
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
+ /**
+ * Register the endpoint route.
+ */
public function register_routes() {
- register_rest_route( $this->namespace, $this->rest_base . '/available-extensions', array(
+ register_rest_route(
+ $this->namespace,
+ $this->rest_base . '/available-extensions',
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( 'Jetpack_Gutenberg', 'get_availability' ),
- 'permission_callback' => array( $this, 'get_items_permission_check' ),
- ),
- 'schema' => array( $this, 'get_item_schema' ),
- ) );
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( 'Jetpack_Gutenberg', 'get_availability' ),
+ 'permission_callback' => array( $this, 'get_items_permission_check' ),
+ ),
+ 'schema' => array( $this, 'get_item_schema' ),
+ )
+ );
}
/**
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/hello.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/hello.php
index ff3349b8..6b78e7ce 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/hello.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/hello.php
@@ -1,23 +1,45 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Example of a WP.com endpoint.
+ *
+ * @package automattic/jetpack
+ */
+/**
+ * Example endpoint.
+ */
class WPCOM_REST_API_V2_Endpoint_Hello {
+ /**
+ * Constructor.
+ */
public function __construct() {
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
+ /**
+ * Register endpoint route.
+ */
public function register_routes() {
- register_rest_route( 'wpcom/v2', '/hello', array(
+ register_rest_route(
+ 'wpcom/v2',
+ '/hello',
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_data' ),
- 'permission_callback' => '__return_true',
- ),
- ) );
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_data' ),
+ 'permission_callback' => '__return_true',
+ ),
+ )
+ );
}
- public function get_data( $request ) {
+ /**
+ * Get data in response to the endpoint request.
+ *
+ * @param WP_REST_Request $request API request.
+ */
+ public function get_data( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return array( 'hello' => 'world' );
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Hello' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php
index f56178cc..e26a16e0 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php
@@ -38,20 +38,24 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
'callback' => array( $this, 'get_status' ),
'permission_callback' => array( $this, 'get_status_permission_check' ),
'args' => array(
- 'type' => array(
+ 'type' => array(
'type' => 'string',
'required' => false,
'validate_callback' => function ( $param ) {
return in_array( $param, array( 'donation', 'all' ), true );
},
),
- 'source' => array(
+ 'source' => array(
'type' => 'string',
'required' => false,
'validate_callback' => function ( $param ) {
return in_array( $param, array( 'calypso', 'earn', 'gutenberg', 'gutenberg-wpcom' ), true );
},
),
+ 'is_editable' => array(
+ 'type' => 'boolean',
+ 'required' => false,
+ ),
),
),
)
@@ -65,22 +69,29 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
'callback' => array( $this, 'create_product' ),
'permission_callback' => array( $this, 'get_status_permission_check' ),
'args' => array(
- 'title' => array(
+ 'title' => array(
'type' => 'string',
'required' => true,
),
- 'price' => array(
+ 'price' => array(
'type' => 'float',
'required' => true,
),
- 'currency' => array(
+ 'currency' => array(
'type' => 'string',
'required' => true,
),
- 'interval' => array(
+ 'interval' => array(
'type' => 'string',
'required' => true,
),
+ 'is_editable' => array(
+ 'type' => 'boolean',
+ 'required' => false,
+ ),
+ 'buyer_can_change_amount' => array(
+ 'type' => 'boolean',
+ ),
),
),
)
@@ -110,27 +121,39 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
/**
* Do create a product based on data, or pass request to wpcom.
*
- * @param object $request - request passed from WP.
+ * @param WP_REST_Request $request - request passed from WP.
*
* @return array|WP_Error
*/
- public function create_product( $request ) {
+ public function create_product( WP_REST_Request $request ) {
+ $is_editable = isset( $request['is_editable'] ) ? (bool) $request['is_editable'] : null;
+ $type = isset( $request['type'] ) ? $request['type'] : null;
+ $buyer_can_change_amount = isset( $request['buyer_can_change_amount'] ) && (bool) $request['buyer_can_change_amount'];
+
+ $payload = array(
+ 'title' => $request['title'],
+ 'price' => $request['price'],
+ 'currency' => $request['currency'],
+ 'buyer_can_change_amount' => $buyer_can_change_amount,
+ 'interval' => $request['interval'],
+ 'type' => $type,
+ );
+
+ // If we pass directly the value "null", it will break the argument validation.
+ if ( null !== $is_editable ) {
+ $payload['is_editable'] = $is_editable;
+ }
+
if ( ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
jetpack_require_lib( 'memberships' );
$connected_destination_account_id = Jetpack_Memberships::get_connected_account_id();
if ( ! $connected_destination_account_id ) {
return new WP_Error( 'no-destination-account', __( 'Please set up a Stripe account for this site first', 'jetpack' ) );
}
- $product = Memberships_Product::create(
- get_current_blog_id(),
- array(
- 'title' => $request['title'],
- 'price' => $request['price'],
- 'currency' => $request['currency'],
- 'interval' => $request['interval'],
- 'connected_destination_account_id' => $connected_destination_account_id,
- )
- );
+
+ $payload['connected_destination_account_id'] = $connected_destination_account_id;
+
+ $product = Memberships_Product::create( get_current_blog_id(), $payload );
if ( is_wp_error( $product ) ) {
return new WP_Error( $product->get_error_code(), __( 'Creating product has failed.', 'jetpack' ) );
}
@@ -143,12 +166,7 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
array(
'method' => 'POST',
),
- array(
- 'title' => $request['title'],
- 'price' => $request['price'],
- 'currency' => $request['currency'],
- 'interval' => $request['interval'],
- )
+ $payload
);
if ( is_wp_error( $response ) ) {
if ( $response->get_error_code() === 'missing_token' ) {
@@ -175,19 +193,33 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
* @return array|WP_Error
*/
public function create_products( $request ) {
+ $is_editable = isset( $request['is_editable'] ) ? (bool) $request['is_editable'] : null;
+
if ( ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
jetpack_require_lib( 'memberships' );
$connected_destination_account_id = Jetpack_Memberships::get_connected_account_id();
if ( ! $connected_destination_account_id ) {
return new WP_Error( 'no-destination-account', __( 'Please set up a Stripe account for this site first', 'jetpack' ) );
}
- $result = Memberships_Product::generate_default_products( get_current_blog_id(), $request['type'], $request['currency'], $connected_destination_account_id );
+
+ $result = Memberships_Product::generate_default_products( get_current_blog_id(), $request['type'], $request['currency'], $connected_destination_account_id, $is_editable );
+
if ( is_wp_error( $result ) ) {
$status = 'invalid_param' === $result->get_error_code() ? 400 : 500;
return new WP_Error( $result->get_error_code(), $result->get_error_message(), array( 'status' => $status ) );
}
return $result;
} else {
+ $payload = array(
+ 'type' => $request['type'],
+ 'currency' => $request['currency'],
+ );
+
+ // If we pass directly is_editable as null, it would break API argument validation.
+ if ( null !== $is_editable ) {
+ $payload['is_editable'] = $is_editable;
+ }
+
$blog_id = Jetpack_Options::get_option( 'id' );
$response = Client::wpcom_json_api_request_as_user(
"/sites/$blog_id/{$this->rest_base}/products",
@@ -195,10 +227,7 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
array(
'method' => 'POST',
),
- array(
- 'type' => $request['type'],
- 'currency' => $request['currency'],
- )
+ $payload
);
if ( is_wp_error( $response ) ) {
if ( $response->get_error_code() === 'missing_token' ) {
@@ -227,19 +256,29 @@ class WPCOM_REST_API_V2_Endpoint_Memberships extends WP_REST_Controller {
public function get_status( \WP_REST_Request $request ) {
$product_type = $request['type'];
$source = $request['source'];
+ $is_editable = ! isset( $request['is_editable'] ) ? null : (bool) $request['is_editable'];
+
if ( ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
jetpack_require_lib( 'memberships' );
$blog_id = get_current_blog_id();
- return (array) get_memberships_settings_for_site( $blog_id, $product_type );
+ return (array) get_memberships_settings_for_site( $blog_id, $product_type, $is_editable );
} else {
+ $payload = array(
+ 'type' => $request['type'],
+ 'source' => $source,
+ );
+
+ // If we pass directly is_editable as null, it would break API argument validation.
+ // This also needs to be converted to int because boolean false is ignored by add_query_arg.
+ if ( null !== $is_editable ) {
+ $payload['is_editable'] = (int) $is_editable;
+ }
+
$blog_id = Jetpack_Options::get_option( 'id' );
$path = "/sites/$blog_id/{$this->rest_base}/status";
if ( $product_type ) {
$path = add_query_arg(
- array(
- 'type' => $product_type,
- 'source' => $source,
- ),
+ $payload,
$path
);
}
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php
index 6e04a289..affa601c 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connection-test-results.php
@@ -1,6 +1,11 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Fetch information about Publicize connections on a site, including tests and connection status.
+ *
+ * @package automattic/jetpack
+ */
-require_once dirname( __FILE__ ) . '/publicize-connections.php';
+require_once __DIR__ . '/publicize-connections.php';
/**
* Publicize: List Connection Test Result Data
@@ -10,6 +15,9 @@ require_once dirname( __FILE__ ) . '/publicize-connections.php';
* @since 6.8
*/
class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connection_Test_Results extends WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections {
+ /**
+ * Constructor.
+ */
public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'publicize/connection-test-results';
@@ -74,11 +82,14 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connection_Test_Results extends
}
/**
- * @param WP_REST_Request
+ * Get list of Publicize Connections.
+ *
+ * @param WP_REST_Request $request Full details about the request.
+ *
* @see Publicize::get_publicize_conns_test_results()
* @return WP_REST_Response suitable for 1-page collection
*/
- public function get_items( $request ) {
+ public function get_items( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
global $publicize;
$items = $this->get_connections();
@@ -117,5 +128,4 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connection_Test_Results extends
return $response;
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_List_Publicize_Connection_Test_Results' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php
index 78cb3178..ac6dccf4 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-connections.php
@@ -1,4 +1,9 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Fetch information about Publicize connections on a site.
+ *
+ * @package automattic/jetpack
+ */
/**
* Publicize: List Connections
@@ -24,6 +29,9 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
*/
public $wpcom_is_wpcom_only_endpoint = true;
+ /**
+ * Constructor.
+ */
public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'publicize/connections';
@@ -86,6 +94,8 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
}
/**
+ * Schema for the endpoint.
+ *
* @return array
*/
public function get_item_schema() {
@@ -122,7 +132,7 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
'display_name' => $publicize->get_display_name( $service_name, $connection ),
'profile_display_name' => ! empty( $connection_meta['profile_display_name'] ) ? $connection_meta['profile_display_name'] : '',
'profile_picture' => ! empty( $connection_meta['profile_picture'] ) ? $connection_meta['profile_picture'] : '',
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison -- We expect an integer, but do loose comparison below in case some other type is stored.
+ // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- We expect an integer, but do loose comparison below in case some other type is stored.
'global' => 0 == $connection_data['user_id'],
);
}
@@ -132,7 +142,10 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
}
/**
- * @param WP_REST_Request $request
+ * Get list of connected Publicize connections.
+ *
+ * @param WP_REST_Request $request Full details about the request.
+ *
* @return WP_REST_Response suitable for 1-page collection
*/
public function get_items( $request ) {
@@ -152,8 +165,9 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
/**
* Filters out data based on ?_fields= request parameter
*
- * @param array $connection
- * @param WP_REST_Request $request
+ * @param array $connection Array of info about a specific Publicize connection.
+ * @param WP_REST_Request $request Full details about the request.
+ *
* @return array filtered $connection
*/
public function prepare_item_for_response( $connection, $request ) {
@@ -200,5 +214,4 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections extends WP_REST_Cont
);
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_List_Publicize_Connections' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php
index da93dd6e..6fdd1231 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/publicize-services.php
@@ -1,4 +1,9 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Endpoint used to fetch information to connect to a Publicize service.
+ *
+ * @package automattic/jetpack
+ */
/**
* Publicize: List Publicize Services
@@ -23,6 +28,9 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control
*/
public $wpcom_is_wpcom_only_endpoint = true;
+ /**
+ * Constructor.
+ */
public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'publicize/services';
@@ -49,6 +57,8 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control
}
/**
+ * Schema for the publicize services endpoint.
+ *
* @return array
*/
public function get_item_schema() {
@@ -81,7 +91,8 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control
*
* @see Publicize::get_available_service_data()
*
- * @param WP_REST_Request $request
+ * @param WP_REST_Request $request Full details about the request.
+ *
* @return WP_REST_Response suitable for 1-page collection
*/
public function get_items( $request ) {
@@ -113,8 +124,9 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control
/**
* Filters out data based on ?_fields= request parameter
*
- * @param array $service
- * @param WP_REST_Request $request
+ * @param array $service UI service connection data for a specific Publicize service.
+ * @param WP_REST_Request $request Full details about the request.
+ *
* @return array filtered $service
*/
public function prepare_item_for_response( $service, $request ) {
@@ -161,5 +173,4 @@ class WPCOM_REST_API_V2_Endpoint_List_Publicize_Services extends WP_REST_Control
);
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_List_Publicize_Services' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php
index 8f279ea9..fde032ca 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/service-api-keys.php
@@ -1,4 +1,10 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Get and save API keys for a site.
+ *
+ * @package automattic/jetpack
+ */
+
/**
* Service API Keys: Exposes 3rd party api keys that are used on a site.
*
@@ -17,13 +23,19 @@
*/
class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
- function __construct() {
+ /**
+ * Constructor.
+ */
+ public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'service-api-keys';
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
+ /**
+ * Register endpoint routes.
+ */
public function register_routes() {
register_rest_route(
'wpcom/v2',
@@ -54,6 +66,9 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
);
}
+ /**
+ * Permission check.
+ */
public static function edit_others_posts_check() {
if ( current_user_can( 'edit_others_posts' ) ) {
return true;
@@ -133,7 +148,7 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
$option = self::key_for_api_service( $service );
$service_api_key = Jetpack_Options::get_option( $option, '' );
$service_api_key_source = 'site';
- };
+ }
$message = esc_html__( 'API key retrieved successfully.', 'jetpack' );
@@ -160,10 +175,10 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
if ( ! $service ) {
return self::service_api_invalid_service_response();
}
- $json_params = $request->get_json_params();
- $params = ! empty( $json_params ) ? $json_params : $request->get_body_params();
- $service_api_key = trim( $params['service_api_key'] );
- $option = self::key_for_api_service( $service );
+ $json_params = $request->get_json_params();
+ $params = ! empty( $json_params ) ? $json_params : $request->get_body_params();
+ $service_api_key = trim( $params['service_api_key'] );
+ $option = self::key_for_api_service( $service );
$validation = self::validate_service_api_key( $service_api_key, $service, $params );
if ( ! $validation['status'] ) {
@@ -211,7 +226,7 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
default:
$service_api_key = Jetpack_Options::get_option( $option, '' );
$service_api_key_source = 'site';
- };
+ }
return array(
'code' => 'success',
@@ -298,9 +313,9 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
$mapbox_geocode_response = wp_safe_remote_get( esc_url_raw( $mapbox_geocode_url ) );
$mapbox_geocode_body = wp_remote_retrieve_body( $mapbox_geocode_response );
$mapbox_geocode_json = json_decode( $mapbox_geocode_body );
- if ( isset( $mapbox_geocode_json->message ) && ! isset( $mapbox_geocode_json->query ) ) {
+ if ( isset( $mapbox_geocode_json->message ) || ! isset( $mapbox_geocode_json->query ) ) {
$status = false;
- $msg = $mapbox_geocode_json->message;
+ $msg = isset( $mapbox_geocode_json->message ) ? $mapbox_geocode_json->message : 'Unknown error';
}
return array(
'status' => $status,
@@ -317,5 +332,4 @@ class WPCOM_REST_API_V2_Endpoint_Service_API_Keys extends WP_REST_Controller {
return $service . '_api_key';
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Service_API_Keys' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/sites-posts-featured-media-url.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/sites-posts-featured-media-url.php
index 4c34161c..26be9838 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/sites-posts-featured-media-url.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/sites-posts-featured-media-url.php
@@ -1,18 +1,29 @@
-<?php
-
-/*
- * Plugin Name: WPCOM Add Featured Media URL
- *
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * WPCOM Add Featured Media URL
* Adds `jetpack_featured_media_url` to post responses
+ *
+ * @package automattic/jetpack
*/
+/**
+ * Add featured media url to API post responses.
+ */
class WPCOM_REST_API_V2_Sites_Posts_Add_Featured_Media_URL {
- function __construct() {
+ /**
+ * Constructor.
+ */
+ public function __construct() {
add_action( 'rest_api_init', array( $this, 'add_featured_media_url' ) );
}
- function add_featured_media_url() {
- register_rest_field( 'post', 'jetpack_featured_media_url',
+ /**
+ * Add featured media url to post responses.
+ */
+ public function add_featured_media_url() {
+ register_rest_field(
+ 'post',
+ 'jetpack_featured_media_url',
array(
'get_callback' => array( $this, 'get_featured_media_url' ),
'update_callback' => null,
@@ -21,9 +32,16 @@ class WPCOM_REST_API_V2_Sites_Posts_Add_Featured_Media_URL {
);
}
- function get_featured_media_url( $object, $field_name, $request ) {
+ /**
+ * Get featured media url.
+ *
+ * @param mixed $object What the endpoint returns.
+ * @param string $field_name Should always match `->field_name`.
+ * @param WP_REST_Request $request WP API request.
+ */
+ public function get_featured_media_url( $object, $field_name, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$featured_media_url = '';
- $image_attributes = wp_get_attachment_image_src(
+ $image_attributes = wp_get_attachment_image_src(
get_post_thumbnail_id( $object['id'] ),
'full'
);
@@ -33,5 +51,4 @@ class WPCOM_REST_API_V2_Sites_Posts_Add_Featured_Media_URL {
return $featured_media_url;
}
}
-
wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Sites_Posts_Add_Featured_Media_URL' );
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php
index 47c95b26..acc5a050 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php
@@ -1,5 +1,9 @@
-<?php
-
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Get subscriber count from Jetpack's Subscriptions module.
+ *
+ * @package automattic/jetpack
+ */
use Automattic\Jetpack\Constants;
/**
@@ -8,7 +12,10 @@ use Automattic\Jetpack\Constants;
* @since 6.9
*/
class WPCOM_REST_API_V2_Endpoint_Subscribers extends WP_REST_Controller {
- function __construct() {
+ /**
+ * Constructor.
+ */
+ public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'subscribers';
// This endpoint *does not* need to connect directly to Jetpack sites.
@@ -16,17 +23,27 @@ class WPCOM_REST_API_V2_Endpoint_Subscribers extends WP_REST_Controller {
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
+ /**
+ * Register API routes.
+ */
public function register_routes() {
// GET /sites/<blog_id>/subscribers/count - Return number of subscribers for this site.
- register_rest_route( $this->namespace, '/' . $this->rest_base . '/count', array(
+ register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/count',
array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'get_subscriber_count' ),
- 'permission_callback' => array( $this, 'readable_permission_check' ),
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'get_subscriber_count' ),
+ 'permission_callback' => array( $this, 'readable_permission_check' ),
+ ),
)
- ) );
+ );
}
+ /**
+ * Permission check. Only authors can access this endpoint.
+ */
public function readable_permission_check() {
if ( ! current_user_can_for_blog( get_current_blog_id(), 'edit_posts' ) ) {
return new WP_Error( 'authorization_required', 'Only users with the permission to edit posts can see the subscriber count.', array( 'status' => 401 ) );
@@ -38,20 +55,20 @@ class WPCOM_REST_API_V2_Endpoint_Subscribers extends WP_REST_Controller {
/**
* Retrieves subscriber count
*
- * @param WP_REST_Request $request incoming API request info
+ * @param WP_REST_Request $request incoming API request info.
* @return array data object containing subscriber count
*/
- public function get_subscriber_count( $request ) {
- // Get the most up to date subscriber count when request is not a test
+ public function get_subscriber_count( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ // Get the most up to date subscriber count when request is not a test.
if ( ! Constants::is_defined( 'TESTING_IN_JETPACK' ) ) {
delete_transient( 'wpcom_subscribers_total' );
}
- $subscriber_info = Jetpack_Subscriptions_Widget::fetch_subscriber_count();
+ $subscriber_info = Jetpack_Subscriptions_Widget::fetch_subscriber_count();
$subscriber_count = $subscriber_info['value'];
return array(
- 'count' => $subscriber_count
+ 'count' => $subscriber_count,
);
}
}
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php
index 84890c3c..636a1ebe 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/attachment-fields-videopress.php
@@ -1,4 +1,4 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* Extend the REST API functionality for VideoPress users.
*
@@ -62,7 +62,7 @@ class WPCOM_REST_API_V2_Attachment_VideoPress_Field extends WPCOM_REST_API_V2_Fi
*
* @return string
*/
- public function get( $attachment, $request ) {
+ public function get( $attachment, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
$blog_id = get_current_blog_id();
} else {
@@ -131,7 +131,7 @@ class WPCOM_REST_API_V2_Attachment_VideoPress_Field extends WPCOM_REST_API_V2_Fi
*
* @return null
*/
- public function update( $value, $object, $request ) {
+ public function update( $value, $object, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return null;
}
@@ -144,7 +144,7 @@ class WPCOM_REST_API_V2_Attachment_VideoPress_Field extends WPCOM_REST_API_V2_Fi
*
* @return true
*/
- public function get_permission_check( $object, $request ) {
+ public function get_permission_check( $object, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return true;
}
@@ -158,7 +158,7 @@ class WPCOM_REST_API_V2_Attachment_VideoPress_Field extends WPCOM_REST_API_V2_Fi
*
* @return true
*/
- public function update_permission_check( $value, $object, $request ) {
+ public function update_permission_check( $value, $object, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return true;
}
}
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/class-wpcom-rest-api-v2-attachment-videopress-data.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/class-wpcom-rest-api-v2-attachment-videopress-data.php
index 9e508ff5..41ad8ab3 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/class-wpcom-rest-api-v2-attachment-videopress-data.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/class-wpcom-rest-api-v2-attachment-videopress-data.php
@@ -93,8 +93,11 @@ class WPCOM_REST_API_V2_Attachment_VideoPress_Data extends WPCOM_REST_API_V2_Fie
public function get_videopress_data( $attachment_id, $blog_id ) {
$info = video_get_info_by_blogpostid( $blog_id, $attachment_id );
return array(
- 'guid' => $info->guid,
- 'rating' => $info->rating,
+ 'guid' => $info->guid,
+ 'rating' => $info->rating,
+ 'allow_download' =>
+ isset( $info->allow_download ) && $info->allow_download ? 1 : 0,
+ 'privacy_setting' => ! isset( $info->privacy_setting ) ? VIDEOPRESS_PRIVACY::SITE_DEFAULT : intval( $info->privacy_setting ),
);
}
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php
index 8e4b282d..e9935fc0 100644
--- a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php
@@ -1,4 +1,9 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Handle Publicize connection information for each post.
+ *
+ * @package automattic/jetpack
+ */
/**
* Add per-post Publicize Connection data.
@@ -25,11 +30,32 @@
* @since 6.8.0
*/
class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_V2_Field_Controller {
+ /**
+ * Array of post types that can handle Publicize.
+ *
+ * @var array
+ */
protected $object_type = array( 'post' );
- protected $field_name = 'jetpack_publicize_connections';
- private $_meta_saved = array();
+ /**
+ * Field name
+ *
+ * @var string
+ */
+ protected $field_name = 'jetpack_publicize_connections';
+
+ /**
+ * Array of post IDs that have been updated.
+ *
+ * @var array
+ */
+ private $meta_saved = array();
+ /**
+ * Used to memoize the updates for a given post.
+ *
+ * @var array
+ */
public $memoized_updates = array();
/**
@@ -39,6 +65,9 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
public function register_fields() {
$this->object_type = get_post_types_by_support( 'publicize' );
foreach ( $this->object_type as $post_type ) {
+ if ( $this->is_registered( $post_type ) ) {
+ continue;
+ }
// Adds meta support for those post types that don't already have it.
// Only runs during REST API requests, so it doesn't impact UI.
if ( ! post_type_supports( $post_type, 'custom-fields' ) ) {
@@ -66,6 +95,9 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
);
}
+ /**
+ * Schema for the endpoint.
+ */
private function post_connection_schema() {
return array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
@@ -118,10 +150,13 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
}
/**
- * @param int $post_id
+ * Permission check, based on module availability and user capabilities.
+ *
+ * @param int $post_id Post ID.
+ *
* @return true|WP_Error
*/
- function permission_check( $post_id ) {
+ public function permission_check( $post_id ) {
global $publicize;
if ( ! $publicize ) {
@@ -146,21 +181,26 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
/**
* Getter permission check
*
- * @param array $post_array Response data from Post Endpoint
+ * @param mixed $post_array Response from the post endpoint.
+ * @param WP_REST_Request $request API request.
+ *
* @return true|WP_Error
*/
- function get_permission_check( $post_array, $request ) {
+ public function get_permission_check( $post_array, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return $this->permission_check( isset( $post_array['id'] ) ? $post_array['id'] : 0 );
}
/**
- * Setter permission check
+ * Setter permission check.
+ *
+ * @param mixed $value The new value for the field.
+ * @param WP_Post $post The post object.
+ * @param WP_REST_Request $request API request.
*
- * @param WP_Post $post
* @return true|WP_Error
*/
- public function update_permission_check( $value, $post, $request ) {
+ public function update_permission_check( $value, $post, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return $this->permission_check( isset( $post->ID ) ? $post->ID : 0 );
}
@@ -169,12 +209,12 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
*
* @see Publicize::get_filtered_connection_data()
*
- * @param array $post_array Response from Post Endpoint
- * @param WP_REST_Request
+ * @param array $post_array Response from Post Endpoint.
+ * @param WP_REST_Request $request API request.
*
* @return array List of connections
*/
- public function get( $post_array, $request ) {
+ public function get( $post_array, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
global $publicize;
if ( ! $publicize ) {
@@ -207,8 +247,9 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
* Prior to updating the post, first calculate which Services to
* Publicize to and which to skip.
*
- * @param object $post Post data to insert/update.
- * @param WP_REST_Request $request
+ * @param object $post Post data to insert/update.
+ * @param WP_REST_Request $request API request.
+ *
* @return Filtered $post
*/
public function rest_pre_insert( $post, $request ) {
@@ -220,7 +261,7 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
if ( is_wp_error( $permission_check ) ) {
return $permission_check;
}
- // memoize
+ // memoize.
$this->get_meta_to_update( $request['jetpack_publicize_connections'], isset( $post->ID ) ? $post->ID : 0 );
if ( isset( $post->ID ) ) {
@@ -236,9 +277,9 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
* After creating a new post, update our cached data to reflect
* the new post ID.
*
- * @param WP_Post $post
- * @param WP_REST_Request $request
- * @param bool $is_new
+ * @param WP_Post $post Post data to update.
+ * @param WP_REST_Request $request API request.
+ * @param bool $is_new Is this a new post.
*/
public function rest_insert( $post, $request, $is_new ) {
if ( ! $is_new ) {
@@ -260,6 +301,13 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
unset( $this->memoized_updates[0] );
}
+ /**
+ * Get list of meta data to update per post ID.
+ *
+ * @param array $requested_connections Publicize conenctions to update.
+ * Items are either `{ id: (string) }` or `{ service_name: (string) }`.
+ * @param int $post_id Post ID.
+ */
protected function get_meta_to_update( $requested_connections, $post_id = 0 ) {
global $publicize;
@@ -267,15 +315,15 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
return array();
}
- if ( isset( $this->memoized_updates[$post_id] ) ) {
- return $this->memoized_updates[$post_id];
+ if ( isset( $this->memoized_updates[ $post_id ] ) ) {
+ return $this->memoized_updates[ $post_id ];
}
$available_connections = $publicize->get_filtered_connection_data( $post_id );
$changed_connections = array();
- // Build lookup mappings
+ // Build lookup mappings.
$available_connections_by_unique_id = array();
$available_connections_by_service_name = array();
foreach ( $available_connections as $available_connection ) {
@@ -287,7 +335,8 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
$available_connections_by_service_name[ $available_connection['service_name'] ][] = $available_connection;
}
- // Handle { service_name: $service_name, enabled: (bool) }
+ // Handle { service_name: $service_name, enabled: (bool) }.
+ // If the service is not available, it will be skipped.
foreach ( $requested_connections as $requested_connection ) {
if ( ! isset( $requested_connection['service_name'] ) ) {
continue;
@@ -303,7 +352,7 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
}
// Handle { id: $id, enabled: (bool) }
- // These override the service_name settings
+ // These override the service_name settings.
foreach ( $requested_connections as $requested_connection ) {
if ( ! isset( $requested_connection['id'] ) ) {
continue;
@@ -316,7 +365,7 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
$changed_connections[ $requested_connection['id'] ] = $requested_connection['enabled'];
}
- // Set all changed connections to their new value
+ // Set all changed connections to their new value.
foreach ( $changed_connections as $unique_id => $enabled ) {
$connection = $available_connections_by_unique_id[ $unique_id ];
@@ -328,16 +377,16 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
}
$meta_to_update = array();
- // For all connections, ensure correct post_meta
+ // For all connections, ensure correct post_meta.
foreach ( $available_connections_by_unique_id as $unique_id => $available_connection ) {
if ( $available_connection['enabled'] ) {
- $meta_to_update[$publicize->POST_SKIP . $unique_id] = null;
+ $meta_to_update[ $publicize->POST_SKIP . $unique_id ] = null; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
} else {
- $meta_to_update[$publicize->POST_SKIP . $unique_id] = 1;
+ $meta_to_update[ $publicize->POST_SKIP . $unique_id ] = 1; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
}
- $this->memoized_updates[$post_id] = $meta_to_update;
+ $this->memoized_updates[ $post_id ] = $meta_to_update;
return $meta_to_update;
}
@@ -345,23 +394,23 @@ class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_
/**
* Update the connections slated to be shared to.
*
- * @param array $requested_connections
- * Items are either `{ id: (string) }` or `{ service_name: (string) }`
- * @param WP_Post $post
- * @param WP_REST_Request
+ * @param array $requested_connections Publicize conenctions to update.
+ * Items are either `{ id: (string) }` or `{ service_name: (string) }`.
+ * @param WP_Post $post Post data.
+ * @param WP_REST_Request $request API request.
*/
- public function update( $requested_connections, $post, $request ) {
- if ( isset( $this->_meta_saved[ $post->ID ] ) ) { // Make sure we only save it once - per request.
+ public function update( $requested_connections, $post, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ if ( isset( $this->meta_saved[ $post->ID ] ) ) { // Make sure we only save it once - per request.
return;
}
foreach ( $this->get_meta_to_update( $requested_connections, $post->ID ) as $meta_key => $meta_value ) {
- if ( is_null( $meta_value ) ) {
+ if ( $meta_value === null ) {
delete_post_meta( $post->ID, $meta_key );
} else {
update_post_meta( $post->ID, $meta_key, $meta_value );
}
}
- $this->_meta_saved[ $post->ID ] = true;
+ $this->meta_saved[ $post->ID ] = true;
}
}
diff --git a/plugins/jetpack/_inc/lib/debugger.php b/plugins/jetpack/_inc/lib/debugger.php
index a0e13e76..60eba5cb 100644
--- a/plugins/jetpack/_inc/lib/debugger.php
+++ b/plugins/jetpack/_inc/lib/debugger.php
@@ -6,15 +6,15 @@
*/
/* Jetpack Connection Testing Framework */
-require_once 'debugger/class-jetpack-cxn-test-base.php';
+require_once __DIR__ . '/debugger/class-jetpack-cxn-test-base.php';
/* Jetpack Connection Tests */
-require_once 'debugger/class-jetpack-cxn-tests.php';
+require_once __DIR__ . '/debugger/class-jetpack-cxn-tests.php';
/* Jetpack Debug Data */
-require_once 'debugger/class-jetpack-debug-data.php';
+require_once __DIR__ . '/debugger/class-jetpack-debug-data.php';
/* The "In-Plugin Debugger" admin page. */
-require_once 'debugger/class-jetpack-debugger.php';
+require_once __DIR__ . '/debugger/class-jetpack-debugger.php';
/* General Debugging Functions */
-require_once 'debugger/debug-functions.php';
+require_once __DIR__ . '/debugger/debug-functions.php';
add_filter( 'debug_information', array( 'Jetpack_Debug_Data', 'core_debug_data' ) );
add_filter( 'site_status_tests', 'jetpack_debugger_site_status_tests' );
diff --git a/plugins/jetpack/_inc/lib/debugger/0-load.php b/plugins/jetpack/_inc/lib/debugger/0-load.php
deleted file mode 100644
index ad069244..00000000
--- a/plugins/jetpack/_inc/lib/debugger/0-load.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Loading the various functions used for Jetpack Debugging.
- *
- * @package Jetpack.
- */
-
-/* Jetpack Connection Testing Framework */
-require_once 'class-jetpack-cxn-test-base.php';
-/* Jetpack Connection Tests */
-require_once 'class-jetpack-cxn-tests.php';
-/* Jetpack Debug Data */
-require_once 'class-jetpack-debug-data.php';
-/* The "In-Plugin Debugger" admin page. */
-require_once 'class-jetpack-debugger.php';
-/* General Debugging Functions */
-require_once 'debug-functions.php';
-
-add_filter( 'debug_information', array( 'Jetpack_Debug_Data', 'core_debug_data' ) );
-add_filter( 'site_status_tests', 'jetpack_debugger_site_status_tests' );
-add_action( 'wp_ajax_health-check-jetpack-local_testing_suite', 'jetpack_debugger_ajax_local_testing_suite' );
diff --git a/plugins/jetpack/_inc/lib/debugger/class-jetpack-debug-data.php b/plugins/jetpack/_inc/lib/debugger/class-jetpack-debug-data.php
index b67fc472..370d1d1e 100644
--- a/plugins/jetpack/_inc/lib/debugger/class-jetpack-debug-data.php
+++ b/plugins/jetpack/_inc/lib/debugger/class-jetpack-debug-data.php
@@ -265,7 +265,7 @@ class Jetpack_Debug_Data {
if ( isset( $_SERVER[ $header ] ) ) {
$debug_info[ $header ] = array(
'label' => 'Server Variable ' . $header,
- 'value' => ( $_SERVER[ $header ] ) ? $_SERVER[ $header ] : 'false',
+ 'value' => empty( $_SERVER[ $header ] ) ? 'false' : filter_var( wp_unslash( $_SERVER[ $header ] ) ),
'private' => true, // This isn't really 'private' information, but we don't want folks to easily paste these into public forums.
);
}
diff --git a/plugins/jetpack/_inc/lib/debugger/class-jetpack-debugger.php b/plugins/jetpack/_inc/lib/debugger/class-jetpack-debugger.php
index 6534c4d3..f8c83a90 100644
--- a/plugins/jetpack/_inc/lib/debugger/class-jetpack-debugger.php
+++ b/plugins/jetpack/_inc/lib/debugger/class-jetpack-debugger.php
@@ -20,11 +20,11 @@ class Jetpack_Debugger {
* Used in class.jetpack-admin.php.
*/
public static function disconnect_and_redirect() {
- if ( ! ( isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], 'jp_disconnect' ) ) ) {
+ if ( ! ( isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], 'jp_disconnect' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
return;
}
- if ( isset( $_GET['disconnect'] ) && $_GET['disconnect'] ) {
+ if ( ! empty( $_GET['disconnect'] ) ) {
if ( Jetpack::is_connection_ready() ) {
Jetpack::disconnect();
wp_safe_redirect( Jetpack::admin_url() );
diff --git a/plugins/jetpack/_inc/lib/functions.wp-notify.php b/plugins/jetpack/_inc/lib/functions.wp-notify.php
index 4963b0f1..344818a7 100644
--- a/plugins/jetpack/_inc/lib/functions.wp-notify.php
+++ b/plugins/jetpack/_inc/lib/functions.wp-notify.php
@@ -13,7 +13,8 @@
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Redirect;
-// phpcs:disable WordPress.WP.I18n.MissingArgDomain --reason: WP Core string.
+// phpcs:disable WordPress.WP.I18n.MissingArgDomain --reason: Code copied from Core, so using Core strings.
+// phpcs:disable WordPress.Utils.I18nTextDomainFixer.MissingArgDomain --reason: Code copied from Core, so using Core strings.
/**
* Short circuits the {@see `wp_notify_postauthor`} function via the `comment_notification_recipients` filter.
@@ -50,12 +51,12 @@ function jetpack_notify_postauthor( $emails, $comment_id ) {
$notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
// The comment was left by the author.
- if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
+ if ( $author && ! $notify_author && $comment->user_id === $post->post_author ) {
unset( $emails[ $author->user_email ] );
}
// The author moderated a comment on their own post.
- if ( $author && ! $notify_author && get_current_user_id() == $post->post_author ) {
+ if ( $author && ! $notify_author && get_current_user_id() === $post->post_author ) {
unset( $emails[ $author->user_email ] );
}
@@ -84,7 +85,10 @@ function jetpack_notify_postauthor( $emails, $comment_id ) {
$comment_content = wp_specialchars_decode( $comment->comment_content );
// Original function modified.
- $moderate_on_wpcom = ! in_array( false, array_map( 'jetpack_notify_is_user_connected_by_email', $emails ) );
+ $moderate_on_wpcom = ! in_array( // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
+ false,
+ array_map( 'jetpack_notify_is_user_connected_by_email', $emails )
+ );
switch ( $comment->comment_type ) {
case 'trackback':
@@ -179,16 +183,16 @@ function jetpack_notify_postauthor( $emails, $comment_id ) {
) . "\r\n";
}
- $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
+ $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( isset( $_SERVER['SERVER_NAME'] ) ? filter_var( wp_unslash( $_SERVER['SERVER_NAME'] ) ) : '' ) );
- if ( '' == $comment->comment_author ) {
+ if ( '' === $comment->comment_author ) {
$from = "From: \"$blogname\" <$wp_email>";
- if ( '' != $comment->comment_author_email ) {
+ if ( '' !== $comment->comment_author_email ) {
$reply_to = "Reply-To: $comment->comment_author_email";
}
} else {
$from = "From: \"$comment->comment_author\" <$wp_email>";
- if ( '' != $comment->comment_author_email ) {
+ if ( '' !== $comment->comment_author_email ) {
$reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
}
}
@@ -324,7 +328,10 @@ function jetpack_notify_moderator( $notify_moderator, $comment_id ) {
$emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
// Original function modified.
- $moderate_on_wpcom = ! in_array( false, array_map( 'jetpack_notify_is_user_connected_by_email', $emails ) );
+ $moderate_on_wpcom = ! in_array( // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
+ false,
+ array_map( 'jetpack_notify_is_user_connected_by_email', $emails )
+ );
$base_wpcom_edit_comment_url = Redirect::get_url(
'calypso-edit-comment',
diff --git a/plugins/jetpack/_inc/lib/icalendar-reader.php b/plugins/jetpack/_inc/lib/icalendar-reader.php
index 998f4c13..c9f30991 100644
--- a/plugins/jetpack/_inc/lib/icalendar-reader.php
+++ b/plugins/jetpack/_inc/lib/icalendar-reader.php
@@ -1,15 +1,46 @@
-<?php
-
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
- * Gets and renders iCal feeds for the Upcoming Events widget and shortcode
+ * Get and render iCal feeds.
+ * Used by the Upcoming Events widget and the [upcomingevents] shortcode.
+ *
+ * @package automattic/jetpack
*/
+/**
+ * Calendar utilities class.
+ *
+ * phpcs:disable PEAR.NamingConventions.ValidClassName.StartWithCapital
+ */
class iCalendarReader {
-
+ // phpcs:enable PEAR.NamingConventions.ValidClassName.StartWithCapital
+ // phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date -- we manually handle timezones all over the file.
+ // @todo Verify that we're manually handling timezones *correctly*. We probably need more `DateTime` with `$this->timezone` and maybe `wp_date()` and less `strtotime()` and `date()` and `date_i18n()`.
+ /**
+ * Count To Do events in calendar.
+ *
+ * @var int
+ */
public $todo_count = 0;
+
+ /**
+ * How many events can be found in calendar.
+ *
+ * @var int
+ */
public $event_count = 0;
+
+ /**
+ * Details about our calendar.
+ *
+ * @var array
+ */
public $cal = array();
- public $_lastKeyWord = '';
+
+ /**
+ * Timezone parsed from the iCalendar feed, if any.
+ *
+ * @var null|DateTimeZone
+ */
public $timezone = null;
/**
@@ -22,24 +53,28 @@ class iCalendarReader {
/**
* Return an array of events
*
- * @param string $url (default: '')
+ * @param string $url (default: '') URL of the iCal feed.
+ * @param int $count Count the number of events.
+ *
* @return array | false on failure
*/
public function get_events( $url = '', $count = 5 ) {
- $count = (int) $count;
+ $count = (int) $count;
$transient_id = 'icalendar_vcal_' . md5( $url ) . '_' . $count;
$vcal = get_transient( $transient_id );
-
+ $vcal = false;
if ( ! empty( $vcal ) ) {
- if ( isset( $vcal['TIMEZONE'] ) )
+ if ( isset( $vcal['TIMEZONE'] ) ) {
$this->timezone = $this->timezone_from_string( $vcal['TIMEZONE'] );
+ }
if ( isset( $vcal['VEVENT'] ) ) {
$vevent = $vcal['VEVENT'];
- if ( $count > 0 )
+ if ( $count > 0 ) {
$vevent = array_slice( $vevent, 0, $count );
+ }
$this->cal['VEVENT'] = $vevent;
@@ -47,8 +82,9 @@ class iCalendarReader {
}
}
- if ( ! $this->parse( $url ) )
+ if ( ! $this->parse( $url ) ) {
return false;
+ }
$vcal = array();
@@ -61,13 +97,13 @@ class iCalendarReader {
if ( ! empty( $this->cal['VEVENT'] ) ) {
$vevent = $this->cal['VEVENT'];
- // check for recurring events
- // $vevent = $this->add_recurring_events( $vevent );
+ // check for recurring events.
+ // $vevent = $this->add_recurring_events( $vevent );.
- // remove before caching - no sense in hanging onto the past
+ // remove before caching - no sense in hanging onto the past.
$vevent = $this->filter_past_and_recurring_events( $vevent );
- // order by soonest start date
+ // order by soonest start date.
$vevent = $this->sort_by_recent( $vevent );
$vcal['VEVENT'] = $vevent;
@@ -75,16 +111,25 @@ class iCalendarReader {
set_transient( $transient_id, $vcal, HOUR_IN_SECONDS );
- if ( !isset( $vcal['VEVENT'] ) )
+ if ( ! isset( $vcal['VEVENT'] ) ) {
return false;
+ }
- if ( $count > 0 )
+ if ( $count > 0 ) {
return array_slice( $vcal['VEVENT'], 0, $count );
+ }
return $vcal['VEVENT'];
}
- function apply_timezone_offset( $events ) {
+ /**
+ * Adjust event's time based on site's timezone.
+ *
+ * @param array $events Array of events.
+ *
+ * @return array
+ */
+ public function apply_timezone_offset( $events ) {
if ( ! $events ) {
return $events;
}
@@ -95,7 +140,7 @@ class iCalendarReader {
$offsetted_events = array();
foreach ( $events as $event ) {
- // Don't handle all-day events
+ // Don't handle all-day events.
if ( 8 < strlen( $event['DTSTART'] ) ) {
$start_time = preg_replace( '/Z$/', '', $event['DTSTART'] );
$start_time = new DateTime( $start_time, $this->timezone );
@@ -106,7 +151,7 @@ class iCalendarReader {
$end_time->setTimeZone( $timezone );
$event['DTSTART'] = $start_time->format( 'YmdHis\Z' );
- $event['DTEND'] = $end_time->format( 'YmdHis\Z' );
+ $event['DTEND'] = $end_time->format( 'YmdHis\Z' );
}
$offsetted_events[] = $event;
@@ -115,10 +160,16 @@ class iCalendarReader {
return $offsetted_events;
}
+ /**
+ * Reorganize events into an array of events with standardized data.
+ *
+ * @param array $events Array of events.
+ *
+ * @return array
+ */
protected function filter_past_and_recurring_events( $events ) {
- $upcoming = array();
+ $upcoming = array();
$set_recurring_events = array();
- $recurrences = array();
/**
* This filter allows any time to be passed in for testing or changing timezones, etc...
*
@@ -139,31 +190,31 @@ class iCalendarReader {
$duration = 0;
}
- if ( isset( $event['RRULE'] ) && $this->timezone->getName() && 8 != strlen( $event['DTSTART'] ) ) {
+ if ( isset( $event['RRULE'] ) && $this->timezone->getName() && 8 !== strlen( $event['DTSTART'] ) ) {
try {
- $adjusted_time = new DateTime( $event['DTSTART'], new DateTimeZone('UTC') );
+ $adjusted_time = new DateTime( $event['DTSTART'], new DateTimeZone( 'UTC' ) );
$adjusted_time->setTimeZone( new DateTimeZone( $this->timezone->getName() ) );
- $event['DTSTART'] = $adjusted_time->format('Ymd\THis');
- $date_from_ics = strtotime( $event['DTSTART'] );
+ $event['DTSTART'] = $adjusted_time->format( 'Ymd\THis' );
+ $date_from_ics = strtotime( $event['DTSTART'] );
$event['DTEND'] = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) + $duration );
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
if ( isset( $event['EXDATE'] ) ) {
$exdates = array();
foreach ( (array) $event['EXDATE'] as $exdate ) {
try {
- $adjusted_time = new DateTime( $exdate, new DateTimeZone('UTC') );
+ $adjusted_time = new DateTime( $exdate, new DateTimeZone( 'UTC' ) );
$adjusted_time->setTimeZone( new DateTimeZone( $this->timezone->getName() ) );
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$exdates[] = $adjusted_time->format( 'Ymd' );
} else {
$exdates[] = $adjusted_time->format( 'Ymd\THis' );
}
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
}
$event['EXDATE'] = $exdates;
@@ -176,76 +227,95 @@ class iCalendarReader {
continue;
}
- // Process events with RRULE before other events
- $rrule = isset( $event['RRULE'] ) ? $event['RRULE'] : false ;
- $uid = $event['UID'];
+ // Process events with RRULE before other events.
+ $rrule = isset( $event['RRULE'] ) ? $event['RRULE'] : false;
+ $uid = $event['UID'];
- if ( $rrule && ! in_array( $uid, $set_recurring_events ) ) {
+ if ( $rrule && ! in_array( $uid, $set_recurring_events, true ) ) {
- // Break down the RRULE into digestible chunks
+ // Break down the RRULE into digestible chunks.
$rrule_array = array();
- foreach ( explode( ";", $event['RRULE'] ) as $rline ) {
- list( $rkey, $rvalue ) = explode( "=", $rline, 2 );
- $rrule_array[$rkey] = $rvalue;
+ foreach ( explode( ';', $event['RRULE'] ) as $rline ) {
+ list( $rkey, $rvalue ) = explode( '=', $rline, 2 );
+ $rrule_array[ $rkey ] = $rvalue;
}
- $interval = ( isset( $rrule_array['INTERVAL'] ) ) ? $rrule_array['INTERVAL'] : 1;
+ $interval = ( isset( $rrule_array['INTERVAL'] ) ) ? $rrule_array['INTERVAL'] : 1;
$rrule_count = ( isset( $rrule_array['COUNT'] ) ) ? $rrule_array['COUNT'] : 0;
- $until = ( isset( $rrule_array['UNTIL'] ) ) ? strtotime( $rrule_array['UNTIL'] ) : strtotime( '+1 year', $current );
+ $until = ( isset( $rrule_array['UNTIL'] ) ) ? strtotime( $rrule_array['UNTIL'] ) : strtotime( '+1 year', $current );
- // Used to bound event checks
+ // Used to bound event checks.
$echo_limit = 10;
- $noop = false;
+ $noop = false;
- // Set bydays for the event
+ // Set bydays for the event.
$weekdays = array( 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' );
- $bydays = $weekdays;
+ $bydays = $weekdays;
- // Calculate a recent start date for incrementing depending on the frequency and interval
+ // Calculate a recent start date for incrementing depending on the frequency and interval.
switch ( $rrule_array['FREQ'] ) {
case 'DAILY':
- $frequency = 'day';
+ $frequency = 'day';
$echo_limit = 10;
if ( $date_from_ics >= $current ) {
$recurring_event_date_start = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) );
} else {
- // Interval and count
+ // Interval and count.
$catchup = floor( ( $current - strtotime( $event['DTSTART'] ) ) / ( $interval * DAY_IN_SECONDS ) );
if ( $rrule_count && $catchup > 0 ) {
if ( $catchup < $rrule_count ) {
- $rrule_count = $rrule_count - $catchup;
- $recurring_event_date_start = date( 'Ymd', strtotime( '+ ' . ( $interval * $catchup ) . ' days', strtotime( $event['DTSTART'] ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
+ $rrule_count = $rrule_count - $catchup;
+ $recurring_event_date_start = date(
+ 'Ymd',
+ strtotime(
+ '+ ' . ( $interval * $catchup ) . ' days',
+ strtotime( $event['DTSTART'] )
+ )
+ ) . date(
+ '\THis',
+ strtotime( $event['DTSTART'] )
+ );
} else {
$noop = true;
}
} else {
- $recurring_event_date_start = date( 'Ymd', strtotime( '+ ' . ( $interval * $catchup ) . ' days', strtotime( $event['DTSTART'] ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
+ $recurring_event_date_start = date(
+ 'Ymd',
+ strtotime(
+ '+ ' . ( $interval * $catchup ) . ' days',
+ strtotime( $event['DTSTART'] )
+ )
+ ) . date(
+ '\THis',
+ strtotime( $event['DTSTART'] )
+ );
}
}
break;
case 'WEEKLY':
- $frequency = 'week';
+ $frequency = 'week';
$echo_limit = 4;
- // BYDAY exception to current date
+ // BYDAY exception to current date.
$day = false;
if ( ! isset( $rrule_array['BYDAY'] ) ) {
- $day = $rrule_array['BYDAY'] = strtoupper( substr( date( 'D', strtotime( $event['DTSTART'] ) ), 0, 2 ) );
+ $rrule_array['BYDAY'] = strtoupper( substr( date( 'D', strtotime( $event['DTSTART'] ) ), 0, 2 ) );
+ $day = $rrule_array['BYDAY'];
}
$bydays = explode( ',', $rrule_array['BYDAY'] );
if ( $date_from_ics >= $current ) {
$recurring_event_date_start = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) );
} else {
- // Interval and count
+ // Interval and count.
$catchup = floor( ( $current - strtotime( $event['DTSTART'] ) ) / ( $interval * WEEK_IN_SECONDS ) );
if ( $rrule_count && $catchup > 0 ) {
if ( ( $catchup * count( $bydays ) ) < $rrule_count ) {
- $rrule_count = $rrule_count - ( $catchup * count( $bydays ) ); // Estimate current event count
+ $rrule_count = $rrule_count - ( $catchup * count( $bydays ) ); // Estimate current event count.
$recurring_event_date_start = date( 'Ymd', strtotime( '+ ' . ( $interval * $catchup ) . ' weeks', strtotime( $event['DTSTART'] ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
} else {
$noop = true;
@@ -255,34 +325,48 @@ class iCalendarReader {
}
}
- // Set to Sunday start
+ // Set to Sunday start.
if ( ! $noop && 'SU' !== strtoupper( substr( date( 'D', strtotime( $recurring_event_date_start ) ), 0, 2 ) ) ) {
- $recurring_event_date_start = date( 'Ymd', strtotime( "last Sunday", strtotime( $recurring_event_date_start ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
+ $recurring_event_date_start = date( 'Ymd', strtotime( 'last Sunday', strtotime( $recurring_event_date_start ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
}
break;
case 'MONTHLY':
- $frequency = 'month';
+ $frequency = 'month';
$echo_limit = 1;
if ( $date_from_ics >= $current ) {
$recurring_event_date_start = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) );
} else {
- // Describe the date in the month
+ // Describe the date in the month.
if ( isset( $rrule_array['BYDAY'] ) ) {
- $day_number = substr( $rrule_array['BYDAY'], 0, 1 );
- $week_day = substr( $rrule_array['BYDAY'], 1 );
- $day_cardinals = array( 1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth' );
- $weekdays = array( 'SU' => 'Sunday', 'MO' => 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday' );
+ $day_number = substr( $rrule_array['BYDAY'], 0, 1 );
+ $week_day = substr( $rrule_array['BYDAY'], 1 );
+ $day_cardinals = array(
+ 1 => 'first',
+ 2 => 'second',
+ 3 => 'third',
+ 4 => 'fourth',
+ 5 => 'fifth',
+ );
+ $weekdays = array(
+ 'SU' => 'Sunday',
+ 'MO' => 'Monday',
+ 'TU' => 'Tuesday',
+ 'WE' => 'Wednesday',
+ 'TH' => 'Thursday',
+ 'FR' => 'Friday',
+ 'SA' => 'Saturday',
+ );
$event_date_desc = "{$day_cardinals[$day_number]} {$weekdays[$week_day]} of ";
} else {
$event_date_desc = date( 'd ', strtotime( $event['DTSTART'] ) );
}
- // Interval only
+ // Interval only.
if ( $interval > 1 ) {
$catchup = 0;
- $maybe = strtotime( $event['DTSTART'] );
+ $maybe = strtotime( $event['DTSTART'] );
while ( $maybe < $current ) {
$maybe = strtotime( '+ ' . ( $interval * $catchup ) . ' months', strtotime( $event['DTSTART'] ) );
$catchup++;
@@ -292,7 +376,7 @@ class iCalendarReader {
$recurring_event_date_start = date( 'Ymd', strtotime( $event_date_desc . date( 'F Y', $current ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
}
- // Add one interval if necessary
+ // Add one interval if necessary.
if ( strtotime( $recurring_event_date_start ) < $current ) {
if ( $interval > 1 ) {
$recurring_event_date_start = date( 'Ymd', strtotime( $event_date_desc . date( 'F Y', strtotime( '+ ' . ( $interval * $catchup ) . ' months', strtotime( $event['DTSTART'] ) ) ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
@@ -301,8 +385,8 @@ class iCalendarReader {
$adjustment = new DateTime( date( 'Y-m-d', $current ) );
$adjustment->modify( 'first day of next month' );
$recurring_event_date_start = date( 'Ymd', strtotime( $event_date_desc . $adjustment->format( 'F Y' ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) );
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
}
}
@@ -310,20 +394,20 @@ class iCalendarReader {
break;
case 'YEARLY':
- $frequency = 'year';
+ $frequency = 'year';
$echo_limit = 1;
if ( $date_from_ics >= $current ) {
- $recurring_event_date_start = date( "Ymd\THis", strtotime( $event['DTSTART'] ) );
+ $recurring_event_date_start = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) );
} else {
- $recurring_event_date_start = date( 'Y', $current ) . date( "md\THis", strtotime( $event['DTSTART'] ) );
+ $recurring_event_date_start = date( 'Y', $current ) . date( 'md\THis', strtotime( $event['DTSTART'] ) );
if ( strtotime( $recurring_event_date_start ) < $current ) {
try {
$next = new DateTime( date( 'Y-m-d', $current ) );
$next->modify( 'first day of next year' );
- $recurring_event_date_start = $next->format( 'Y' ) . date ( 'md\THis', strtotime( $event['DTSTART'] ) );
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ $recurring_event_date_start = $next->format( 'Y' ) . date( 'md\THis', strtotime( $event['DTSTART'] ) );
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
}
}
@@ -333,94 +417,107 @@ class iCalendarReader {
$frequency = false;
}
- if ( $frequency !== false && ! $noop ) {
+ if ( false !== $frequency && ! $noop ) {
$count_counter = 1;
- // If no COUNT limit, go to 10
+ // If no COUNT limit, go to 10.
if ( empty( $rrule_count ) ) {
$rrule_count = 10;
}
- // Set up EXDATE handling for the event
+ // Set up EXDATE handling for the event.
$exdates = ( isset( $event['EXDATE'] ) ) ? $event['EXDATE'] : array();
for ( $i = 1; $i <= $echo_limit; $i++ ) {
- // Weeks need a daily loop and must check for inclusion in BYDAYS
- if ( 'week' == $frequency ) {
+ // Weeks need a daily loop and must check for inclusion in BYDAYS.
+ if ( 'week' === $frequency ) {
$byday_event_date_start = strtotime( $recurring_event_date_start );
foreach ( $weekdays as $day ) {
$event_start_timestamp = $byday_event_date_start;
- $start_time = date( 'His', $event_start_timestamp );
- $event_end_timestamp = $event_start_timestamp + $duration;
- $end_time = date( 'His', $event_end_timestamp );
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ $start_time = date( 'His', $event_start_timestamp );
+ $event_end_timestamp = $event_start_timestamp + $duration;
+ $end_time = date( 'His', $event_end_timestamp );
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$exdate_compare = date( 'Ymd', $event_start_timestamp );
} else {
$exdate_compare = date( 'Ymd\THis', $event_start_timestamp );
}
- if ( in_array( $day, $bydays ) && $event_end_timestamp > $current && $event_start_timestamp < $until && $count_counter <= $rrule_count && $event_start_timestamp >= $date_from_ics && ! in_array( $exdate_compare, $exdates ) ) {
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ if (
+ in_array( $day, $bydays, true )
+ && $event_end_timestamp > $current
+ && $event_start_timestamp < $until
+ && $count_counter <= $rrule_count
+ && $event_start_timestamp >= $date_from_ics
+ && ! in_array( $exdate_compare, $exdates, true )
+ ) {
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$event['DTSTART'] = date( 'Ymd', $event_start_timestamp );
- $event['DTEND'] = date( 'Ymd', $event_end_timestamp );
+ $event['DTEND'] = date( 'Ymd', $event_end_timestamp );
} else {
$event['DTSTART'] = date( 'Ymd\THis', $event_start_timestamp );
- $event['DTEND'] = date( 'Ymd\THis', $event_end_timestamp );
+ $event['DTEND'] = date( 'Ymd\THis', $event_end_timestamp );
}
- if ( $this->timezone->getName() && 8 != strlen( $event['DTSTART'] ) ) {
+ if ( $this->timezone->getName() && 8 !== strlen( $event['DTSTART'] ) ) {
try {
$adjusted_time = new DateTime( $event['DTSTART'], new DateTimeZone( $this->timezone->getName() ) );
$adjusted_time->setTimeZone( new DateTimeZone( 'UTC' ) );
- $event['DTSTART'] = $adjusted_time->format('Ymd\THis');
+ $event['DTSTART'] = $adjusted_time->format( 'Ymd\THis' );
$event['DTEND'] = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) + $duration );
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
}
$upcoming[] = $event;
$count_counter++;
}
- // Move forward one day
+ // Move forward one day.
$byday_event_date_start = strtotime( date( 'Ymd\T', strtotime( '+ 1 day', $event_start_timestamp ) ) . $start_time );
}
- // Restore first event timestamp
+ // Restore first event timestamp.
$event_start_timestamp = strtotime( $recurring_event_date_start );
} else {
$event_start_timestamp = strtotime( $recurring_event_date_start );
- $start_time = date( 'His', $event_start_timestamp );
- $event_end_timestamp = $event_start_timestamp + $duration;
- $end_time = date( 'His', $event_end_timestamp );
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ $start_time = date( 'His', $event_start_timestamp );
+ $event_end_timestamp = $event_start_timestamp + $duration;
+ $end_time = date( 'His', $event_end_timestamp );
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$exdate_compare = date( 'Ymd', $event_start_timestamp );
} else {
$exdate_compare = date( 'Ymd\THis', $event_start_timestamp );
}
- if ( $event_end_timestamp > $current && $event_start_timestamp < $until && $count_counter <= $rrule_count && $event_start_timestamp >= $date_from_ics && ! in_array( $exdate_compare, $exdates ) ) {
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ if (
+ $event_end_timestamp > $current
+ && $event_start_timestamp < $until
+ && $count_counter <= $rrule_count
+ && $event_start_timestamp >= $date_from_ics
+ && ! in_array( $exdate_compare, $exdates, true )
+ ) {
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$event['DTSTART'] = date( 'Ymd', $event_start_timestamp );
- $event['DTEND'] = date( 'Ymd', $event_end_timestamp );
+ $event['DTEND'] = date( 'Ymd', $event_end_timestamp );
} else {
$event['DTSTART'] = date( 'Ymd\T', $event_start_timestamp ) . $start_time;
- $event['DTEND'] = date( 'Ymd\T', $event_end_timestamp ) . $end_time;
+ $event['DTEND'] = date( 'Ymd\T', $event_end_timestamp ) . $end_time;
}
- if ( $this->timezone->getName() && 8 != strlen( $event['DTSTART'] ) ) {
+ if ( $this->timezone->getName() && 8 !== strlen( $event['DTSTART'] ) ) {
try {
$adjusted_time = new DateTime( $event['DTSTART'], new DateTimeZone( $this->timezone->getName() ) );
$adjusted_time->setTimeZone( new DateTimeZone( 'UTC' ) );
- $event['DTSTART'] = $adjusted_time->format('Ymd\THis');
+ $event['DTSTART'] = $adjusted_time->format( 'Ymd\THis' );
$event['DTEND'] = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) + $duration );
- } catch ( Exception $e ) {
- // Invalid argument to DateTime
+ } catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
+ // Invalid argument to DateTime.
}
}
$upcoming[] = $event;
@@ -428,25 +525,24 @@ class iCalendarReader {
}
}
- // Set up next interval and reset $event['DTSTART'] and $event['DTEND'], keeping timestamps intact
+ // Set up next interval and reset $event['DTSTART'] and $event['DTEND'], keeping timestamps intact.
$next_start_timestamp = strtotime( "+ {$interval} {$frequency}s", $event_start_timestamp );
- if ( 8 == strlen( $event['DTSTART'] ) ) {
+ if ( 8 === strlen( $event['DTSTART'] ) ) {
$event['DTSTART'] = date( 'Ymd', $next_start_timestamp );
- $event['DTEND'] = date( 'Ymd', strtotime( $event['DTSTART'] ) + $duration );
+ $event['DTEND'] = date( 'Ymd', strtotime( $event['DTSTART'] ) + $duration );
} else {
$event['DTSTART'] = date( 'Ymd\THis', $next_start_timestamp );
- $event['DTEND'] = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) + $duration );
+ $event['DTEND'] = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) + $duration );
}
- // Move recurring event date forward
+ // Move recurring event date forward.
$recurring_event_date_start = $event['DTSTART'];
}
$set_recurring_events[] = $uid;
}
-
} else {
- // Process normal events
+ // Process normal events.
if ( strtotime( isset( $event['DTEND'] ) ? $event['DTEND'] : $event['DTSTART'] ) >= $current ) {
$upcoming[] = $event;
}
@@ -458,42 +554,53 @@ class iCalendarReader {
/**
* Parse events from an iCalendar feed
*
- * @param string $url (default: '')
+ * @param string $url (default: '').
* @return array | false on failure
*/
public function parse( $url = '' ) {
- $cache_group = 'icalendar_reader_parse';
+ $cache_group = 'icalendar_reader_parse';
$disable_get_key = 'disable:' . md5( $url );
- // Check to see if previous attempts have failed
- if ( false !== wp_cache_get( $disable_get_key, $cache_group ) )
+ // Check to see if previous attempts have failed.
+ if ( false !== wp_cache_get( $disable_get_key, $cache_group ) ) {
return false;
+ }
- // rewrite webcal: URI schem to HTTP
- $url = preg_replace('/^webcal/', 'http', $url );
- // try to fetch
- $r = wp_remote_get( $url, array( 'timeout' => 3, 'sslverify' => false ) );
+ // rewrite webcal: URI schem to HTTP.
+ $url = preg_replace( '/^webcal/', 'http', $url );
+ // try to fetch.
+ $r = wp_remote_get(
+ $url,
+ array(
+ 'timeout' => 3,
+ 'sslverify' => false,
+ )
+ );
if ( 200 !== wp_remote_retrieve_response_code( $r ) ) {
- // We were unable to fetch any content, so don't try again for another 60 seconds
+ // We were unable to fetch any content, so don't try again for another 60 seconds.
wp_cache_set( $disable_get_key, 1, $cache_group, 60 );
return false;
}
$body = wp_remote_retrieve_body( $r );
- if ( empty( $body ) )
+ if ( empty( $body ) ) {
return false;
+ }
- $body = str_replace( "\r\n", "\n", $body );
+ $body = str_replace( "\r\n", "\n", $body );
$lines = preg_split( "/\n(?=[A-Z])/", $body );
- if ( empty( $lines ) )
+ if ( empty( $lines ) ) {
return false;
+ }
- if ( false === stristr( $lines[0], 'BEGIN:VCALENDAR' ) )
+ if ( false === stristr( $lines[0], 'BEGIN:VCALENDAR' ) ) {
return false;
+ }
+ $type = '';
foreach ( $lines as $line ) {
- $add = $this->key_value_from_string( $line );
+ $add = $this->key_value_from_string( $line );
if ( ! $add ) {
$this->add_component( $type, false, $line );
continue;
@@ -529,12 +636,17 @@ class iCalendarReader {
}
break;
case 'TZID':
- if ( 'VTIMEZONE' == $type && ! $this->timezone )
+ if (
+ 'VTIMEZONE' === $type
+ && ! $this->timezone
+ ) {
$this->timezone = $this->timezone_from_string( $value );
+ }
break;
case 'X-WR-TIMEZONE':
- if ( ! $this->timezone )
+ if ( ! $this->timezone ) {
$this->timezone = $this->timezone_from_string( $value );
+ }
break;
default:
$this->add_component( $type, $keyword, $value );
@@ -542,7 +654,7 @@ class iCalendarReader {
}
}
- // Filter for RECURRENCE-IDs
+ // Filter for RECURRENCE-IDs.
$recurrences = array();
if ( array_key_exists( 'VEVENT', $this->cal ) ) {
foreach ( $this->cal['VEVENT'] as $event ) {
@@ -551,8 +663,12 @@ class iCalendarReader {
}
}
foreach ( $recurrences as $recurrence ) {
- for ( $i = 0; $i < count( $this->cal['VEVENT'] ); $i++ ) {
- if ( $this->cal['VEVENT'][ $i ]['UID'] == $recurrence['UID'] && ! isset( $this->cal['VEVENT'][ $i ]['RECURRENCE-ID'] ) ) {
+ $count_vevent = count( $this->cal['VEVENT'] );
+ for ( $i = 0; $i < $count_vevent; $i++ ) {
+ if (
+ $this->cal['VEVENT'][ $i ]['UID'] === $recurrence['UID']
+ && ! isset( $this->cal['VEVENT'][ $i ]['RECURRENCE-ID'] )
+ ) {
$this->cal['VEVENT'][ $i ]['EXDATE'][] = $recurrence['RECURRENCE-ID'];
break;
}
@@ -566,14 +682,15 @@ class iCalendarReader {
/**
* Parse key:value from a string
*
- * @param string $text (default: '')
+ * @param string $text (default: '').
* @return array
*/
public function key_value_from_string( $text = '' ) {
preg_match( '/([^:]+)(;[^:]+)?[:]([\w\W]*)/', $text, $matches );
- if ( 0 == count( $matches ) )
+ if ( 0 === count( $matches ) ) {
return false;
+ }
return array( $matches[1], $matches[3] );
}
@@ -581,7 +698,7 @@ class iCalendarReader {
/**
* Convert a timezone name into a timezone object.
*
- * @param string $text Timezone name. Example: America/Chicago
+ * @param string $text Timezone name. Example: America/Chicago.
* @return object|null A DateTimeZone object if the conversion was successful.
*/
private function timezone_from_string( $text ) {
@@ -602,21 +719,21 @@ class iCalendarReader {
/**
* Add a component to the calendar array
*
- * @param string $component (default: '')
- * @param string $keyword (default: '')
- * @param string $value (default: '')
+ * @param string $component (default: '').
+ * @param bool|string $keyword (default: '').
+ * @param string $value (default: '').
* @return void
*/
public function add_component( $component = '', $keyword = '', $value = '' ) {
- if ( false == $keyword ) {
+ if ( ! $keyword ) {
$keyword = $this->last_keyword;
switch ( $component ) {
- case 'VEVENT':
- $value = $this->cal[ $component ][ $this->event_count - 1 ][ $keyword ] . $value;
- break;
- case 'VTODO' :
- $value = $this->cal[ $component ][ $this->todo_count - 1 ][ $keyword ] . $value;
- break;
+ case 'VEVENT':
+ $value = $this->cal[ $component ][ $this->event_count - 1 ][ $keyword ] . $value;
+ break;
+ case 'VTODO':
+ $value = $this->cal[ $component ][ $this->todo_count - 1 ][ $keyword ] . $value;
+ break;
}
}
@@ -632,58 +749,58 @@ class iCalendarReader {
* EXDATE;TZID=Pacific Standard Time:20120615T140000,20120629T140000,20120706T140000
*/
- // Always store EXDATE as an array
+ // Always store EXDATE as an array.
if ( stristr( $keyword, 'EXDATE' ) ) {
$value = explode( ',', $value );
}
- // Adjust DTSTART, DTEND, and EXDATE according to their TZID if set
+ // Adjust DTSTART, DTEND, and EXDATE according to their TZID if set.
if ( strpos( $keyword, ';' ) && ( stristr( $keyword, 'DTSTART' ) || stristr( $keyword, 'DTEND' ) || stristr( $keyword, 'EXDATE' ) || stristr( $keyword, 'RECURRENCE-ID' ) ) ) {
$keyword = explode( ';', $keyword );
$tzid = false;
- if ( 2 == count( $keyword ) ) {
+ if ( 2 === count( $keyword ) ) {
$tparam = $keyword[1];
- if ( strpos( $tparam, "TZID" ) !== false ) {
+ if ( strpos( $tparam, 'TZID' ) !== false ) {
$tzid = $this->timezone_from_string( str_replace( 'TZID=', '', $tparam ) );
}
}
- // Normalize all times to default UTC
+ // Normalize all times to default UTC.
if ( $tzid ) {
$adjusted_times = array();
foreach ( (array) $value as $v ) {
try {
$adjusted_time = new DateTime( $v, $tzid );
$adjusted_time->setTimeZone( new DateTimeZone( 'UTC' ) );
- $adjusted_times[] = $adjusted_time->format('Ymd\THis');
+ $adjusted_times[] = $adjusted_time->format( 'Ymd\THis' );
} catch ( Exception $e ) {
- // Invalid argument to DateTime
+ // Invalid argument to DateTime.
return;
}
}
$value = $adjusted_times;
}
- // Format for adding to event
+ // Format for adding to event.
$keyword = $keyword[0];
- if ( 'EXDATE' != $keyword ) {
+ if ( 'EXDATE' !== $keyword ) {
$value = implode( (array) $value );
}
}
foreach ( (array) $value as $v ) {
- switch ($component) {
+ switch ( $component ) {
case 'VTODO':
- if ( 'EXDATE' == $keyword ) {
+ if ( 'EXDATE' === $keyword ) {
$this->cal[ $component ][ $this->todo_count - 1 ][ $keyword ][] = $v;
} else {
$this->cal[ $component ][ $this->todo_count - 1 ][ $keyword ] = $v;
}
break;
case 'VEVENT':
- if ( 'EXDATE' == $keyword ) {
+ if ( 'EXDATE' === $keyword ) {
$this->cal[ $component ][ $this->event_count - 1 ][ $keyword ][] = $v;
} else {
$this->cal[ $component ][ $this->event_count - 1 ][ $keyword ] = $v;
@@ -700,19 +817,19 @@ class iCalendarReader {
/**
* Escape strings with wp_kses, allow links
*
- * @param string $string (default: '')
+ * @param string $string (default: '') The string to escape.
* @return string
*/
public function escape( $string = '' ) {
- // Unfold content lines per RFC 5545
+ // Unfold content lines per RFC 5545.
$string = str_replace( "\n\t", '', $string );
$string = str_replace( "\n ", '', $string );
$allowed_html = array(
'a' => array(
'href' => array(),
- 'title' => array()
- )
+ 'title' => array(),
+ ),
);
$allowed_tags = '';
@@ -729,43 +846,62 @@ class iCalendarReader {
/**
* Render the events
*
- * @param string $url (default: '')
- * @param string $context (default: 'widget') or 'shortcode'
+ * @param string $url (default: '') URL of the iCal feed.
+ * @param array $args Event options.
+ *
* @return mixed bool|string false on failure, rendered HTML string on success.
*/
public function render( $url = '', $args = array() ) {
- $args = wp_parse_args( $args, array(
- 'context' => 'widget',
- 'number' => 5
- ) );
+ $args = wp_parse_args(
+ $args,
+ array(
+ 'context' => 'widget',
+ 'number' => 5,
+ )
+ );
$events = $this->get_events( $url, $args['number'] );
$events = $this->apply_timezone_offset( $events );
- if ( empty( $events ) )
+ if ( empty( $events ) ) {
return false;
+ }
ob_start();
- if ( 'widget' == $args['context'] ) : ?>
+ if ( 'widget' === $args['context'] ) : ?>
<ul class="upcoming-events">
<?php foreach ( $events as $event ) : ?>
<li>
- <strong class="event-summary"><?php echo $this->escape( stripslashes( $event['SUMMARY'] ) ); ?></strong>
- <span class="event-when"><?php echo $this->formatted_date( $event ); ?></span>
+ <strong class="event-summary">
+ <?php
+ echo $this->escape( stripslashes( $event['SUMMARY'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </strong>
+ <span class="event-when"><?php echo esc_html( $this->formatted_date( $event ) ); ?></span>
<?php if ( ! empty( $event['LOCATION'] ) ) : ?>
- <span class="event-location"><?php echo $this->escape( stripslashes( $event['LOCATION'] ) ); ?></span>
+ <span class="event-location">
+ <?php
+ echo $this->escape( stripslashes( $event['LOCATION'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </span>
<?php endif; ?>
<?php if ( ! empty( $event['DESCRIPTION'] ) ) : ?>
- <span class="event-description"><?php echo wp_trim_words( $this->escape( stripcslashes( $event['DESCRIPTION'] ) ) ); ?></span>
+ <span class="event-description">
+ <?php
+ echo wp_trim_words( $this->escape( stripcslashes( $event['DESCRIPTION'] ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </span>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
- <?php endif;
+ <?php
+ endif;
- if ( 'shortcode' == $args['context'] ) : ?>
+ if ( 'shortcode' === $args['context'] ) :
+ ?>
<table class="upcoming-events">
<thead>
<tr>
@@ -778,68 +914,102 @@ class iCalendarReader {
<tbody>
<?php foreach ( $events as $event ) : ?>
<tr>
- <td><?php echo empty( $event['LOCATION'] ) ? '&nbsp;' : $this->escape( stripslashes( $event['LOCATION'] ) ); ?></td>
- <td><?php echo $this->formatted_date( $event ); ?></td>
- <td><?php echo empty( $event['SUMMARY'] ) ? '&nbsp;' : $this->escape( stripslashes( $event['SUMMARY'] ) ); ?></td>
- <td><?php echo empty( $event['DESCRIPTION'] ) ? '&nbsp;' : wp_trim_words( $this->escape( stripcslashes( $event['DESCRIPTION'] ) ) ); ?></td>
+ <td>
+ <?php
+ echo empty( $event['LOCATION'] )
+ ? '&nbsp;'
+ : $this->escape( stripslashes( $event['LOCATION'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </td>
+ <td><?php echo esc_html( $this->formatted_date( $event ) ); ?></td>
+ <td>
+ <?php
+ echo empty( $event['SUMMARY'] )
+ ? '&nbsp;'
+ : $this->escape( stripslashes( $event['SUMMARY'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </td>
+ <td>
+ <?php
+ echo empty( $event['DESCRIPTION'] )
+ ? '&nbsp;'
+ : wp_trim_words( $this->escape( stripcslashes( $event['DESCRIPTION'] ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- this method is built to escape.
+ ?>
+ </td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
- <?php endif;
+ <?php
+ endif;
$rendered = ob_get_clean();
- if ( empty( $rendered ) )
+ if ( empty( $rendered ) ) {
return false;
+ }
return $rendered;
}
+ /**
+ * Return a localized string with information about the event's date and time,
+ * or starting date and end date.
+ *
+ * @param array $event Info about the event.
+ *
+ * @return string
+ */
public function formatted_date( $event ) {
-
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
- $start = strtotime( $event['DTSTART'] );
- $end = isset( $event['DTEND'] ) ? strtotime( $event['DTEND'] ) : false;
+ $start = strtotime( $event['DTSTART'] );
+ $end = isset( $event['DTEND'] ) ? strtotime( $event['DTEND'] ) : false;
- $all_day = ( 8 == strlen( $event['DTSTART'] ) );
+ $all_day = ( 8 === strlen( $event['DTSTART'] ) );
- if ( !$all_day && $this->timezone ) {
+ if ( ! $all_day && $this->timezone ) {
try {
- $start_time = new DateTime( $event['DTSTART'] );
+ $start_time = new DateTime( $event['DTSTART'] );
$timezone_offset = $this->timezone->getOffset( $start_time );
- $start += $timezone_offset;
+ $start += $timezone_offset;
if ( $end ) {
$end += $timezone_offset;
}
} catch ( Exception $e ) {
- // Invalid argument to DateTime
+ // Invalid argument to DateTime.
+ return '';
}
}
$single_day = $end ? ( $end - $start ) <= DAY_IN_SECONDS : true;
/* translators: Date and time */
- $date_with_time = __( '%1$s at %2$s' , 'jetpack' );
+ $date_with_time = __( '%1$s at %2$s', 'jetpack' );
/* translators: Two dates with a separator */
- $two_dates = __( '%1$s &ndash; %2$s' , 'jetpack' );
+ $two_dates = __( '%1$s &ndash; %2$s', 'jetpack' );
- // we'll always have the start date. Maybe with time
- if ( $all_day )
+ // we'll always have the start date. Maybe with time.
+ if ( $all_day ) {
$date = date_i18n( $date_format, $start );
- else
- $date = sprintf( $date_with_time, date_i18n( $date_format, $start ), date_i18n( $time_format, $start ) );
+ } else {
+ $date = sprintf(
+ $date_with_time,
+ date_i18n( $date_format, $start ),
+ date_i18n( $time_format, $start )
+ );
+ }
- // single day, timed
- if ( $single_day && ! $all_day && false !== $end )
+ // single day, timed.
+ if ( $single_day && ! $all_day && false !== $end ) {
$date = sprintf( $two_dates, $date, date_i18n( $time_format, $end ) );
+ }
- // multi-day
+ // multi-day.
if ( ! $single_day ) {
if ( $all_day ) {
- // DTEND for multi-day events represents "until", not "including", so subtract one minute
+ // DTEND for multi-day events represents "until", not "including", so subtract one minute.
$end_date = date_i18n( $date_format, $end - 60 );
} else {
$end_date = sprintf( $date_with_time, date_i18n( $date_format, $end ), date_i18n( $time_format, $end ) );
@@ -852,35 +1022,48 @@ class iCalendarReader {
return $date;
}
+ /**
+ * Sort list of events by event date.
+ *
+ * @param array $list List of events.
+ *
+ * @return array
+ */
protected function sort_by_recent( $list ) {
- $dates = $sorted_list = array();
+ $dates = array();
+ $sorted_list = array();
foreach ( $list as $key => $row ) {
$date = $row['DTSTART'];
- // pad some time onto an all day date
- if ( 8 === strlen( $date ) )
+ // pad some time onto an all day date.
+ if ( 8 === strlen( $date ) ) {
$date .= 'T000000Z';
- $dates[$key] = $date;
+ }
+ $dates[ $key ] = $date;
}
asort( $dates );
- foreach( $dates as $key => $value ) {
- $sorted_list[$key] = $list[$key];
+ foreach ( $dates as $key => $value ) {
+ $sorted_list[ $key ] = $list[ $key ];
}
- unset($list);
+ unset( $list );
return $sorted_list;
}
+ // phpcs:enable WordPress.DateTime.RestrictedFunctions.date_date
}
-
/**
* Wrapper function for iCalendarReader->get_events()
*
- * @param string $url (default: '')
+ * @param string $url (default: '').
+ * @param int $count Number of events to fetch.
* @return array
*/
function icalendar_get_events( $url = '', $count = 5 ) {
- // Find your calendar's address https://support.google.com/calendar/bin/answer.py?hl=en&answer=37103
+ /*
+ * Find your calendar's address
+ * https://support.google.com/calendar/bin/answer.py?hl=en&answer=37103
+ */
$ical = new iCalendarReader();
return $ical->get_events( $url, $count );
}
@@ -888,8 +1071,9 @@ function icalendar_get_events( $url = '', $count = 5 ) {
/**
* Wrapper function for iCalendarReader->render()
*
- * @param string $url (default: '')
- * @param string $context (default: 'widget') or 'shortcode'
+ * @param string $url (default: '').
+ * @param array $args Options when rendering events.
+ *
* @return mixed bool|string false on failure, rendered HTML string on success.
*/
function icalendar_render_events( $url = '', $args = array() ) {
diff --git a/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-builder.php b/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-builder.php
deleted file mode 100644
index 62b0ddda..00000000
--- a/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-builder.php
+++ /dev/null
@@ -1,400 +0,0 @@
-<?php
-
-/**
- * Provides an interface for easily building a complex search query that
- * combines multiple ranking signals.
- *
- *
- * $bldr = new Jetpack_WPES_Query_Builder();
- * $bldr->add_filter( ... );
- * $bldr->add_filter( ... );
- * $bldr->add_query( ... );
- * $es_query = $bldr->build_query();
- *
- *
- * All ES queries take a standard form with main query (with some filters),
- * wrapped in a function_score
- *
- * Most functions are chainable, e.g. $bldr->add_filter( ... )->add_query( ... )->build_query();
- *
- * Bucketed queries use an aggregation to diversify results. eg a bunch
- * of separate filters where to get different sets of results.
- *
- */
-
-class Jetpack_WPES_Query_Builder {
-
- protected $es_filters = array();
-
- // Custom boosting with function_score
- protected $functions = array();
- protected $weighting_functions = array();
- protected $decays = array();
- protected $scripts = array();
- protected $functions_max_boost = 2.0;
- protected $functions_score_mode = 'multiply';
- protected $functions_boost_mode = 'multiply';
- protected $query_bool_boost = null;
-
- // General aggregations for buckets and metrics
- protected $aggs_query = false;
- protected $aggs = array();
-
- // The set of top level text queries to combine
- protected $must_queries = array();
- protected $should_queries = array();
- protected $dis_max_queries = array();
-
- protected $diverse_buckets_query = false;
- protected $bucket_filters = array();
- protected $bucket_sub_aggs = array();
-
- public function get_langs() {
- if ( isset( $this->langs ) ) {
- return $this->langs;
- }
- return false;
- }
-
- ////////////////////////////////////
- // Methods for building a query
-
- public function add_filter( $filter ) {
- $this->es_filters[] = $filter;
-
- return $this;
- }
-
- public function add_query( $query, $type = 'must' ) {
- switch ( $type ) {
- case 'dis_max':
- $this->dis_max_queries[] = $query;
- break;
-
- case 'should':
- $this->should_queries[] = $query;
- break;
-
- case 'must':
- default:
- $this->must_queries[] = $query;
- break;
- }
-
- return $this;
- }
-
- /**
- * Add any weighting function to the query
- *
- * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
- *
- * @param $function array A function structure to apply to the query
- *
- * @return void
- */
- public function add_weighting_function( $function ) {
- $this->weighting_functions[] = $function;
-
- return $this;
- }
-
- /**
- * Add a scoring function to the query
- *
- * NOTE: For decays (linear, exp, or gauss), use Jetpack_WPES_Query_Builder::add_decay() instead
- *
- * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
- *
- * @param $function string name of the function
- * @param $params array functions parameters
- *
- * @return void
- */
- public function add_function( $function, $params ) {
- $this->functions[ $function ][] = $params;
-
- return $this;
- }
-
- /**
- * Add a decay function to score results
- *
- * This method should be used instead of Jetpack_WPES_Query_Builder::add_function() for decays, as the internal ES structure
- * is slightly different for them.
- *
- * @see https://www.elastic.co/guide/en/elasticsearch/guide/current/decay-functions.html
- *
- * @param $function string name of the decay function - linear, exp, or gauss
- * @param $params array The decay functions parameters, passed to ES directly
- *
- * @return void
- */
- public function add_decay( $function, $params ) {
- $this->decays[ $function ][] = $params;
-
- return $this;
- }
-
- /**
- * Add a scoring mode to the query
- *
- * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
- *
- * @param $mode string name of how to score
- *
- * @return void
- */
- public function add_score_mode_to_functions( $mode='multiply' ) {
- $this->functions_score_mode = $mode;
-
- return $this;
- }
-
- public function add_boost_mode_to_functions( $mode='multiply' ) {
- $this->functions_boost_mode = $mode;
-
- return $this;
- }
-
- public function add_max_boost_to_functions( $boost ) {
- $this->functions_max_boost = $boost;
-
- return $this;
- }
-
- public function add_boost_to_query_bool( $boost ) {
- $this->query_bool_boost = $boost;
-
- return $this;
- }
-
- public function add_aggs( $aggs_name, $aggs ) {
- $this->aggs_query = true;
- $this->aggs[$aggs_name] = $aggs;
-
- return $this;
- }
-
- public function set_all_aggs( $aggs ) {
- $this->aggs_query = true;
- $this->aggs = $aggs;
-
- return $this;
- }
-
- public function add_aggs_sub_aggs( $aggs_name, $sub_aggs ) {
- if ( ! array_key_exists( 'aggs', $this->aggs[$aggs_name] ) ) {
- $this->aggs[$aggs_name]['aggs'] = array();
- }
- $this->aggs[$aggs_name]['aggs'] = $sub_aggs;
-
- return $this;
- }
-
- public function add_bucketed_query( $name, $query ) {
- $this->_add_bucket_filter( $name, $query );
-
- $this->add_query( $query, 'dis_max' );
-
- return $this;
- }
-
- public function add_bucketed_terms( $name, $field, $terms, $boost = 1 ) {
- if ( ! is_array( $terms ) ) {
- $terms = array( $terms );
- }
-
- $this->_add_bucket_filter( $name, array(
- 'terms' => array(
- $field => $terms,
- ),
- ));
-
- $this->add_query( array(
- 'constant_score' => array(
- 'filter' => array(
- 'terms' => array(
- $field => $terms,
- ),
- ),
- 'boost' => $boost,
- ),
- ), 'dis_max' );
-
- return $this;
- }
-
- public function add_bucket_sub_aggs( $agg ) {
- $this->bucket_sub_aggs = array_merge( $this->bucket_sub_aggs, $agg );
-
- return $this;
- }
-
- protected function _add_bucket_filter( $name, $filter ) {
- $this->diverse_buckets_query = true;
- $this->bucket_filters[ $name ] = $filter;
- }
-
- ////////////////////////////////////
- // Building Final Query
-
- /**
- * Combine all the queries, functions, decays, scripts, and max_boost into an ES query
- *
- * @return array Array representation of the built ES query
- */
- public function build_query() {
- $query = array();
-
- //dis_max queries just become a single must query
- if ( ! empty( $this->dis_max_queries ) ) {
- $this->must_queries[] = array(
- 'dis_max' => array(
- 'queries' => $this->dis_max_queries,
- ),
- );
- }
-
- if ( empty( $this->must_queries ) ) {
- $this->must_queries = array(
- array(
- 'match_all' => array(),
- ),
- );
- }
-
- if ( empty( $this->should_queries ) ) {
- $query = array(
- 'bool' => array(
- 'must' => $this->must_queries,
- ),
- );
- } else {
- $query = array(
- 'bool' => array(
- 'must' => $this->must_queries,
- 'should' => $this->should_queries,
- ),
- );
- }
-
- if ( ! is_null( $this->query_bool_boost ) && isset( $query['bool'] ) ) {
- $query['bool']['boost'] = $this->query_bool_boost;
- }
-
- // If there are any function score adjustments, then combine those
- if ( $this->functions || $this->decays || $this->scripts || $this->weighting_functions ) {
- $weighting_functions = array();
-
- if ( $this->functions ) {
- foreach ( $this->functions as $function_type => $configs ) {
- foreach ( $configs as $config ) {
- foreach ( $config as $field => $params ) {
- $func_arr = $params;
-
- $func_arr['field'] = $field;
-
- $weighting_functions[] = array(
- $function_type => $func_arr,
- );
- }
- }
- }
- }
-
- if ( $this->decays ) {
- foreach ( $this->decays as $decay_type => $configs ) {
- foreach ( $configs as $config ) {
- foreach ( $config as $field => $params ) {
- $weighting_functions[] = array(
- $decay_type => array(
- $field => $params,
- ),
- );
- }
- }
- }
- }
-
- if ( $this->scripts ) {
- foreach ( $this->scripts as $script ) {
- $weighting_functions[] = array(
- 'script_score' => array(
- 'script' => $script,
- ),
- );
- }
- }
-
- $query = array(
- 'function_score' => array(
- 'query' => $query,
- 'functions' => $weighting_functions,
- 'max_boost' => $this->functions_max_boost,
- 'score_mode' => $this->functions_score_mode,
- 'boost_mode' => $this->functions_boost_mode,
- ),
- );
- } // End if().
-
- return $query;
- }
-
- /**
- * Assemble the 'filter' portion of an ES query, from all registered filters
- *
- * @return array|null Combined ES filters, or null if none have been defined
- */
- public function build_filter() {
- if ( empty( $this->es_filters ) ) {
- $filter = null;
- } elseif ( 1 == count( $this->es_filters ) ) {
- $filter = $this->es_filters[0];
- } else {
- $filter = array(
- 'and' => $this->es_filters,
- );
- }
-
- return $filter;
- }
-
- /**
- * Assemble the 'aggregation' portion of an ES query, from all general aggregations.
- *
- * @return array An aggregation query as an array of topics, filters, and bucket names
- */
- public function build_aggregation() {
- if ( empty( $this->bucket_sub_aggs ) && empty( $this->aggs_query ) ) {
- return array();
- }
-
- if ( ! $this->diverse_buckets_query && empty( $this->aggs_query ) ) {
- return $this->bucket_sub_aggs;
- }
-
- $aggregations = array(
- 'topics' => array(
- 'filters' => array(
- 'filters' => array(),
- ),
- ),
- );
-
- if ( ! empty( $this->bucket_sub_aggs ) ) {
- $aggregations['topics']['aggs'] = $this->bucket_sub_aggs;
- }
-
- foreach ( $this->bucket_filters as $bucket_name => $filter ) {
- $aggregations['topics']['filters']['filters'][ $bucket_name ] = $filter;
- }
-
- if ( ! empty( $this->aggs_query ) ) {
- $aggregations = $this->aggs;
- }
-
- return $aggregations;
- }
-
-}
diff --git a/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-parser.php b/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-parser.php
deleted file mode 100644
index 42a82ede..00000000
--- a/plugins/jetpack/_inc/lib/jetpack-wpes-query-builder/jetpack-wpes-query-parser.php
+++ /dev/null
@@ -1,691 +0,0 @@
-<?php
-
-/**
- * Parse a pure text query into WordPress Elasticsearch query. This builds on
- * the Jetpack_WPES_Query_Builder() to provide search query parsing.
- *
- * The key part of this parser is taking a user's query string typed into a box
- * and converting it into an ES search query.
- *
- * This varies by application, but roughly it means extracting some parts of the query
- * (authors, tags, and phrases) that are treated as a filter. Then taking the
- * remaining words and building the correct query (possibly with prefix searching
- * if we are doing search as you type)
- *
- * This class only supports ES 2.x+
- *
- * This parser builds queries of the form:
- * bool:
- * must:
- * AND match of a single field (ideally an edgengram field)
- * filter:
- * filter clauses from context (eg @gibrown, #news, etc)
- * should:
- * boosting of results by various fields
- *
- * Features supported:
- * - search as you type
- * - phrases
- * - supports querying across multiple languages at once
- *
- * Example usage (from Search on Reader Manage):
- *
- * require_lib( 'jetpack-wpes-query-builder/jetpack-wpes-search-query-parser' );
- * $parser = new Jetpack_WPES_Search_Query_Parser( $args['q'], array( $lang ) );
- *
- * //author
- * $parser->author_field_filter( array(
- * 'prefixes' => array( '@' ),
- * 'wpcom_id_field' => 'author_id',
- * 'must_query_fields' => array( 'author.engram', 'author_login.engram' ),
- * 'boost_query_fields' => array( 'author^2', 'author_login^2', 'title.default.engram' ),
- * ) );
- *
- * //remainder of query
- * $match_content_fields = $parser->merge_ml_fields(
- * array(
- * 'all_content' => 0.1,
- * ),
- * array(
- * 'all_content.default.engram^0.1',
- * )
- * );
- * $boost_content_fields = $parser->merge_ml_fields(
- * array(
- * 'title' => 2,
- * 'description' => 1,
- * 'tags' => 1,
- * ),
- * array(
- * 'author_login^2',
- * 'author^2',
- * )
- * );
- *
- * $parser->phrase_filter( array(
- * 'must_query_fields' => $match_content_fields,
- * 'boost_query_fields' => $boost_content_fields,
- * ) );
- * $parser->remaining_query( array(
- * 'must_query_fields' => $match_content_fields,
- * 'boost_query_fields' => $boost_content_fields,
- * ) );
- *
- * //Boost on phrases
- * $parser->remaining_query( array(
- * 'boost_query_fields' => $boost_content_fields,
- * 'boost_query_type' => 'phrase',
- * ) );
- *
- * //boosting
- * $parser->add_max_boost_to_functions( 20 );
- * $parser->add_function( 'field_value_factor', array(
- * 'follower_count' => array(
- * 'modifier' => 'sqrt',
- * 'factor' => 1,
- * 'missing' => 0,
- * ) ) );
- *
- * //Filtering
- * $parser->add_filter( array(
- * 'exists' => array( 'field' => 'langs.' . $lang )
- * ) );
- *
- * //run the query
- * $es_query_args = array(
- * 'name' => 'feeds',
- * 'blog_id' => false,
- * 'security_strategy' => 'a8c',
- * 'type' => 'feed,blog',
- * 'fields' => array( 'blog_id', 'feed_id' ),
- * 'query' => $parser->build_query(),
- * 'filter' => $parser->build_filter(),
- * 'size' => $size,
- * 'from' => $from
- * );
- * $es_results = es_api_search_index( $es_query_args, 'api-feed-find' );
- *
- */
-
-jetpack_require_lib( 'jetpack-wpes-query-builder' );
-
-class Jetpack_WPES_Search_Query_Parser extends Jetpack_WPES_Query_Builder {
-
- protected $orig_query = '';
- protected $current_query = '';
- protected $langs;
- protected $avail_langs = array( 'ar', 'bg', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'eu', 'fa', 'fi', 'fr', 'he', 'hi', 'hu', 'hy', 'id', 'it', 'ja', 'ko', 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' );
-
- public function __construct( $user_query, $langs ) {
- $this->orig_query = $user_query;
- $this->current_query = $this->orig_query;
- $this->langs = $this->norm_langs( $langs );
- }
-
- protected $extracted_phrases = array();
-
- public function get_current_query() {
- return $this->current_query;
- }
-
- public function set_current_query( $q ) {
- $this->current_query = $q;
- }
-
- ///////////////////////////////////////////////////////
- // Methods for Building arrays of multilingual fields
-
- /*
- * Normalize language codes
- */
- public function norm_langs( $langs ) {
- $lst = array();
- foreach( $langs as $l ) {
- $l = strtok( $l, '-_' );
- if ( in_array( $l, $this->avail_langs ) ) {
- $lst[$l] = true;
- } else {
- $lst['default'] = true;
- }
- }
- return array_keys( $lst );
- }
-
- /*
- * Take a list of field prefixes and expand them for multi-lingual
- * with the provided boostings.
- */
- public function merge_ml_fields( $fields2boosts, $additional_fields ) {
- $flds = array();
- foreach( $fields2boosts as $f => $b ) {
- foreach( $this->langs as $l ) {
- $flds[] = $f . '.' . $l . '^' . $b;
- }
- }
- foreach( $additional_fields as $f ) {
- $flds[] = $f;
- }
- return $flds;
- }
-
- ////////////////////////////////////
- // Extract Fields for Filtering on
-
- /*
- * Extract any @mentions from the user query
- * use them as a filter if we can find a wp.com id
- * otherwise use them as a
- *
- * args:
- * wpcom_id_field: wp.com id field
- * must_query_fields: array of fields to search for matching results (optional)
- * boost_query_fields: array of fields to search in for boosting results (optional)
- * prefixes: array of prefixes that the user can use to indicate an author
- *
- * returns true/false of whether any were found
- *
- * See also: https://github.com/twitter/twitter-text/blob/master/java/src/com/twitter/Regex.java
- */
- public function author_field_filter( $args ) {
- $defaults = array(
- 'wpcom_id_field' => 'author_id',
- 'must_query_fields' => null,
- 'boost_query_fields' => null,
- 'prefixes' => array( '@' ),
- );
- $args = wp_parse_args( $args, $defaults );
-
- $names = array();
- foreach( $args['prefixes'] as $p ) {
- $found = $this->get_fields( $p );
- if ( $found ) {
- foreach( $found as $f ) {
- $names[] = $f;
- }
- }
- }
-
- if ( empty( $names ) ) {
- return false;
- }
-
- foreach( $args['prefixes'] as $p ) {
- $this->remove_fields( $p );
- }
-
- $user_ids = array();
- $query_names = array();
-
- //loop through the matches and separate into filters and queries
- foreach( $names as $n ) {
- //check for exact match on login
- $userdata = get_user_by( 'login', strtolower( $n ) );
- $filtering = false;
- if ( $userdata ) {
- $user_ids[ $userdata->ID ] = true;
- $filtering = true;
- }
-
- $is_phrase = false;
- if ( preg_match( '/"/', $n ) ) {
- $is_phrase = true;
- $n = preg_replace( '/"/', '', $n );
- }
-
- if ( !empty( $args['must_query_fields'] ) && !$filtering ) {
- if ( $is_phrase ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $n,
- 'type' => 'phrase',
- ) ) );
- } else {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $n,
- ) ) );
- }
- }
-
- if ( !empty( $args['boost_query_fields'] ) ) {
- if ( $is_phrase ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $n,
- 'type' => 'phrase',
- ) ), 'should' );
- } else {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $n,
- ) ), 'should' );
- }
- }
- }
-
- if ( ! empty( $user_ids ) ) {
- $user_ids = array_keys( $user_ids );
- $this->add_filter( array( 'terms' => array( $args['wpcom_id_field'] => $user_ids ) ) );
- }
-
- return true;
- }
-
- /*
- * Extract any prefix followed by text use them as a must clause,
- * and optionally as a boost to the should query
- * This can be used for hashtags. eg #News, or #"current events",
- * but also works for any arbitrary field. eg from:Greg
- *
- * args:
- * must_query_fields: array of fields that must match the tag (optional)
- * boost_query_fields: array of fields to boost search on (optional)
- * prefixes: array of prefixes that the user can use to indicate a tag
- *
- * returns true/false of whether any were found
- *
- */
- public function text_field_filter( $args ) {
- $defaults = array(
- 'must_query_fields' => array( 'tag.name' ),
- 'boost_query_fields' => array( 'tag.name' ),
- 'prefixes' => array( '#' ),
- );
- $args = wp_parse_args( $args, $defaults );
-
- $tags = array();
- foreach( $args['prefixes'] as $p ) {
- $found = $this->get_fields( $p );
- if ( $found ) {
- foreach( $found as $f ) {
- $tags[] = $f;
- }
- }
- }
-
- if ( empty( $tags ) ) {
- return false;
- }
-
- foreach( $args['prefixes'] as $p ) {
- $this->remove_fields( $p );
- }
-
- foreach( $tags as $t ) {
- $is_phrase = false;
- if ( preg_match( '/"/', $t ) ) {
- $is_phrase = true;
- $t = preg_replace( '/"/', '', $t );
- }
-
- if ( ! empty( $args['must_query_fields'] ) ) {
- if ( $is_phrase ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $t,
- 'type' => 'phrase',
- ) ) );
- } else {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $t,
- ) ) );
- }
- }
-
- if ( ! empty( $args['boost_query_fields'] ) ) {
- if ( $is_phrase ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $t,
- 'type' => 'phrase',
- ) ), 'should' );
- } else {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $t,
- ) ), 'should' );
- }
- }
- }
-
- return true;
- }
-
- /*
- * Extract anything surrounded by quotes or if there is an opening quote
- * that is not complete, and add them to the query as a phrase query.
- * Quotes can be either '' or ""
- *
- * args:
- * must_query_fields: array of fields that must match the phrases
- * boost_query_fields: array of fields to boost the phrases on (optional)
- *
- * returns true/false of whether any were found
- *
- */
- public function phrase_filter( $args ) {
- $defaults = array(
- 'must_query_fields' => array( 'all_content' ),
- 'boost_query_fields' => array( 'title' ),
- );
- $args = wp_parse_args( $args, $defaults );
-
- $phrases = array();
- if ( preg_match_all( '/"([^"]+)"/', $this->current_query, $matches ) ) {
- foreach ( $matches[1] as $match ) {
- $phrases[] = $match;
- }
- $this->current_query = preg_replace( '/"([^"]+)"/', '', $this->current_query );
- }
-
- if ( preg_match_all( "/'([^']+)'/", $this->current_query, $matches ) ) {
- foreach ( $matches[1] as $match ) {
- $phrases[] = $match;
- }
- $this->current_query = preg_replace( "/'([^']+)'/", '', $this->current_query );
- }
-
- //look for a final, uncompleted phrase
- $phrase_prefix = false;
- if ( preg_match_all( '/"([^"]+)$/', $this->current_query, $matches ) ) {
- $phrase_prefix = $matches[1][0];
- $this->current_query = preg_replace( '/"([^"]+)$/', '', $this->current_query );
- }
- if ( preg_match_all( "/(?:'\B|\B')([^']+)$/", $this->current_query, $matches ) ) {
- $phrase_prefix = $matches[1][0];
- $this->current_query = preg_replace( "/(?:'\B|\B')([^']+)$/", '', $this->current_query );
- }
-
- if ( $phrase_prefix ) {
- $phrases[] = $phrase_prefix;
- }
- if ( empty( $phrases ) ) {
- return false;
- }
-
- foreach ( $phrases as $p ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $p,
- 'type' => 'phrase',
- ) ) );
-
- if ( ! empty( $args['boost_query_fields'] ) ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $p,
- 'operator' => 'and',
- ) ), 'should' );
- }
- }
-
- return true;
- }
-
- /*
- * Query fields based on the remaining parts of the query
- * This could be the final AND part of the query terms to match, or it
- * could be boosting certain elements of the query
- *
- * args:
- * must_query_fields: array of fields that must match the remaining terms (optional)
- * boost_query_fields: array of fields to boost the remaining terms on (optional)
- *
- */
- public function remaining_query( $args ) {
- $defaults = array(
- 'must_query_fields' => null,
- 'boost_query_fields' => null,
- 'boost_operator' => 'and',
- 'boost_query_type' => 'best_fields',
- );
- $args = wp_parse_args( $args, $defaults );
-
- if ( empty( $this->current_query ) || ctype_space( $this->current_query ) ) {
- return;
- }
-
- if ( ! empty( $args['must_query_fields'] ) ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $this->current_query,
- 'operator' => 'and',
- ) ) );
- }
-
- if ( ! empty( $args['boost_query_fields'] ) ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $this->current_query,
- 'operator' => $args['boost_operator'],
- 'type' => $args['boost_query_type'],
- ) ), 'should' );
- }
-
- }
-
- /*
- * Query fields using a prefix query (alphabetical expansions on the index).
- * This is not recommended. Slower performance and worse relevancy.
- *
- * (UNTESTED! Copied from old prefix expansion code)
- *
- * args:
- * must_query_fields: array of fields that must match the remaining terms (optional)
- * boost_query_fields: array of fields to boost the remaining terms on (optional)
- *
- */
- public function remaining_prefix_query( $args ) {
- $defaults = array(
- 'must_query_fields' => array( 'all_content' ),
- 'boost_query_fields' => array( 'title' ),
- 'boost_operator' => 'and',
- 'boost_query_type' => 'best_fields',
- );
- $args = wp_parse_args( $args, $defaults );
-
- if ( empty( $this->current_query ) || ctype_space( $this->current_query ) ) {
- return;
- }
-
- //////////////////////////////////
- // Example cases to think about:
- // "elasticse"
- // "elasticsearch"
- // "elasticsearch "
- // "elasticsearch lucen"
- // "elasticsearch lucene"
- // "the future" - note the stopword which will match nothing!
- // "F1" - an exact match that also has tons of expansions
- // "こんにちは" ja "hello"
- // "こんにちは友人" ja "hello friend" - we just rely on the prefix phrase and ES to split words
- // - this could still be better I bet. Maybe we need to analyze with ES first?
- //
-
- /////////////////////////////
- //extract pieces of query
- // eg: "PREFIXREMAINDER PREFIXWORD"
- // "elasticsearch lucen"
-
- $prefix_word = false;
- $prefix_remainder = false;
- if ( preg_match_all( '/([^ ]+)$/', $this->current_query, $matches ) ) {
- $prefix_word = $matches[1][0];
- }
-
- $prefix_remainder = preg_replace( '/([^ ]+)$/', '', $this->current_query );
- if ( ctype_space( $prefix_remainder ) ) {
- $prefix_remainder = false;
- }
-
- if ( ! $prefix_word ) {
- //Space at the end of the query, so skip using a prefix query
- if ( ! empty( $args['must_query_fields'] ) ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['must_query_fields'],
- 'query' => $this->current_query,
- 'operator' => 'and',
- ) ) );
- }
-
- if ( ! empty( $args['boost_query_fields'] ) ) {
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $this->current_query,
- 'operator' => $args['boost_operator'],
- 'type' => $args['boost_query_type'],
- ) ), 'should' );
- }
- } else {
-
- //must match the prefix word and the prefix remainder
- if ( ! empty( $args['must_query_fields'] ) ) {
- //need to do an OR across a few fields to handle all cases
- $must_q = array( 'bool' => array( 'should' => array( ), 'minimum_should_match' => 1 ) );
-
- //treat all words as an exact search (boosts complete word like "news"
- //from prefixes of "newspaper")
- $must_q['bool']['should'][] = array( 'multi_match' => array(
- 'fields' => $this->all_fields,
- 'query' => $full_text,
- 'operator' => 'and',
- 'type' => 'cross_fields',
- ) );
-
- //always optimistically try and match the full text as a phrase
- //prefix "the futu" should try to match "the future"
- //otherwise the first stopword kinda breaks
- //This also works as the prefix match for a single word "elasticsea"
- $must_q['bool']['should'][] = array( 'multi_match' => array(
- 'fields' => $this->phrase_fields,
- 'query' => $full_text,
- 'operator' => 'and',
- 'type' => 'phrase_prefix',
- 'max_expansions' => 100,
- ) );
-
- if ( $prefix_remainder ) {
- //Multiple words found, so treat each word on its own and not just as
- //a part of a phrase
- //"elasticsearch lucen" => "elasticsearch" exact AND "lucen" prefix
- $q['bool']['should'][] = array( 'bool' => array(
- 'must' => array(
- array( 'multi_match' => array(
- 'fields' => $this->phrase_fields,
- 'query' => $prefix_word,
- 'operator' => 'and',
- 'type' => 'phrase_prefix',
- 'max_expansions' => 100,
- ) ),
- array( 'multi_match' => array(
- 'fields' => $this->all_fields,
- 'query' => $prefix_remainder,
- 'operator' => 'and',
- 'type' => 'cross_fields',
- ) ),
- )
- ) );
- }
-
- $this->add_query( $must_q );
- }
-
- //Now add any boosting of the query
- if ( ! empty( $args['boost_query_fields'] ) ) {
- //treat all words as an exact search (boosts complete word like "news"
- //from prefixes of "newspaper")
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $this->current_query,
- 'operator' => $args['boost_query_operator'],
- 'type' => $args['boost_query_type'],
- ) ), 'should' );
-
- //optimistically boost the full phrase prefix match
- $this->add_query( array(
- 'multi_match' => array(
- 'fields' => $args['boost_query_fields'],
- 'query' => $this->current_query,
- 'operator' => 'and',
- 'type' => 'phrase_prefix',
- 'max_expansions' => 100,
- ) ) );
- }
- }
- }
-
- /*
- * Boost results based on the lang probability overlaps
- *
- * args:
- * langs2prob: list of languages to search in with associated boosts
- */
- public function boost_lang_probs( $langs2prob ) {
- foreach( $langs2prob as $l => $p ) {
- $this->add_function( 'field_value_factor', array(
- 'modifier' => 'none',
- 'factor' => $p,
- 'missing' => 0.01, //1% chance doc did not have right lang detected
- ) );
- }
- }
-
- ////////////////////////////////////
- // Helper Methods
-
- //Get the text after some prefix. eg @gibrown, or @"Greg Brown"
- protected function get_fields( $field_prefix ) {
- $regex = '/' . $field_prefix . '(("[^"]+")|([^\\p{Z}]+))/';
- if ( preg_match_all( $regex, $this->current_query, $match ) ) {
- return $match[1];
- }
- return false;
- }
-
- //Remove the prefix and text from the query
- protected function remove_fields( $field_name ) {
- $regex = '/' . $field_name . '(("[^"]+")|([^\\p{Z}]+))/';
- $this->current_query = preg_replace( $regex, '', $this->current_query );
- }
-
- //Best effort string truncation that splits on word breaks
- protected function truncate_string( $string, $limit, $break=" " ) {
- if ( mb_strwidth( $string ) <= $limit ) {
- return $string;
- }
-
- // walk backwards from $limit to find first break
- $breakpoint = $limit;
- $broken = false;
- while ( $breakpoint > 0 ) {
- if ( $break === mb_strimwidth( $string, $breakpoint, 1 ) ) {
- $string = mb_strimwidth( $string, 0, $breakpoint );
- $broken = true;
- break;
- }
- $breakpoint--;
- }
- // if we weren't able to find a break, need to chop mid-word
- if ( !$broken ) {
- $string = mb_strimwidth( $string, 0, $limit );
- }
- return $string;
- }
-
-}
diff --git a/plugins/jetpack/_inc/lib/markdown/0-load.php b/plugins/jetpack/_inc/lib/markdown/0-load.php
deleted file mode 100644
index bf5993e3..00000000
--- a/plugins/jetpack/_inc/lib/markdown/0-load.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-if ( ! class_exists( 'MarkdownExtra_Parser' ) )
- jetpack_require_lib( 'markdown/extra' );
-
-jetpack_require_lib( 'markdown/gfm' );
diff --git a/plugins/jetpack/_inc/lib/plans.php b/plugins/jetpack/_inc/lib/plans.php
index 6dc43fca..f1867dab 100644
--- a/plugins/jetpack/_inc/lib/plans.php
+++ b/plugins/jetpack/_inc/lib/plans.php
@@ -36,7 +36,7 @@ class Jetpack_Plans {
array(
'method' => 'GET',
'headers' => array(
- 'X-Forwarded-For' => Jetpack::current_user_ip( true ),
+ 'X-Forwarded-For' => ( new Automattic\Jetpack\Status\Visitor() )->get_ip( true ),
),
),
null,
diff --git a/plugins/jetpack/_inc/lib/plugins.php b/plugins/jetpack/_inc/lib/plugins.php
index 0bffc529..cc8e8bb5 100644
--- a/plugins/jetpack/_inc/lib/plugins.php
+++ b/plugins/jetpack/_inc/lib/plugins.php
@@ -1,205 +1,10 @@
-<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+<?php
/**
- * Plugins Library
+ * This file has been moved to the jetpack-plugins-installer package
*
- * Helper functions for installing and activating plugins.
+ * @deprecated 10.7
*
- * Used by the REST API
- *
- * @autounit api plugins
- */
-
-require_once 'class.jetpack-automatic-install-skin.php';
-
-use Automattic\Jetpack\A8c_Mc_Stats;
-
-/**
- * Plugins management tools.
+ * @package jetpack
*/
-class Jetpack_Plugins {
-
- /**
- * Install and activate a plugin.
- *
- * @since 5.8.0
- *
- * @param string $slug Plugin slug.
- *
- * @return bool|WP_Error True if installation succeeded, error object otherwise.
- */
- public static function install_and_activate_plugin( $slug ) {
- $plugin_id = self::get_plugin_id_by_slug( $slug );
-
- if ( ! $plugin_id ) {
- $installed = self::install_plugin( $slug );
- if ( is_wp_error( $installed ) ) {
- return $installed;
- }
- $plugin_id = self::get_plugin_id_by_slug( $slug );
- } elseif ( is_plugin_active( $plugin_id ) ) {
- return true; // Already installed and active.
- }
-
- if ( ! current_user_can( 'activate_plugins' ) ) {
- return new WP_Error( 'not_allowed', __( 'You are not allowed to activate plugins on this site.', 'jetpack' ) );
- }
- $activated = activate_plugin( $plugin_id );
- if ( is_wp_error( $activated ) ) {
- return $activated;
- }
-
- return true;
- }
-
- /**
- * Install a plugin.
- *
- * @since 5.8.0
- *
- * @param string $slug Plugin slug.
- *
- * @return bool|WP_Error True if installation succeeded, error object otherwise.
- */
- public static function install_plugin( $slug ) {
- if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
- return new WP_Error( 'not_allowed', __( 'You are not allowed to install plugins on this site.', 'jetpack' ) );
- }
-
- $skin = new Jetpack_Automatic_Install_Skin();
- $upgrader = new Plugin_Upgrader( $skin );
- $zip_url = self::generate_wordpress_org_plugin_download_link( $slug );
- $mc_stats = new A8c_Mc_Stats();
-
- $result = $upgrader->install( $zip_url );
-
- if ( is_wp_error( $result ) ) {
- $mc_stats->add( 'install-plugin', "fail-$slug" );
- return $result;
- }
-
- $plugin = self::get_plugin_id_by_slug( $slug );
- $error_code = 'install_error';
- if ( ! $plugin ) {
- $error = __( 'There was an error installing your plugin', 'jetpack' );
- }
-
- if ( ! $result ) {
- $error_code = $upgrader->skin->get_main_error_code();
- $message = $upgrader->skin->get_main_error_message();
- $error = $message ? $message : __( 'An unknown error occurred during installation', 'jetpack' );
- }
-
- if ( ! empty( $error ) ) {
- if ( 'download_failed' === $error_code ) {
- // For backwards compatibility: versions prior to 3.9 would return no_package instead of download_failed.
- $error_code = 'no_package';
- }
-
- $mc_stats->add( 'install-plugin', "fail-$slug" );
- return new WP_Error( $error_code, $error, 400 );
- }
-
- $mc_stats->add( 'install-plugin', "success-$slug" );
- return (array) $upgrader->skin->get_upgrade_messages();
- }
-
- /**
- * Get WordPress.org zip download link from a plugin slug
- *
- * @param string $plugin_slug Plugin slug.
- */
- protected static function generate_wordpress_org_plugin_download_link( $plugin_slug ) {
- return "https://downloads.wordpress.org/plugin/$plugin_slug.latest-stable.zip";
- }
-
- /**
- * Get the plugin ID (composed of the plugin slug and the name of the main plugin file) from a plugin slug.
- *
- * @param string $slug Plugin slug.
- */
- public static function get_plugin_id_by_slug( $slug ) {
- // Check if get_plugins() function exists. This is required on the front end of the
- // site, since it is in a file that is normally only loaded in the admin.
- if ( ! function_exists( 'get_plugins' ) ) {
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
- }
-
- /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
- $plugins = apply_filters( 'all_plugins', get_plugins() );
- if ( ! is_array( $plugins ) ) {
- return false;
- }
-
- foreach ( $plugins as $plugin_file => $plugin_data ) {
- if ( self::get_slug_from_file_path( $plugin_file ) === $slug ) {
- return $plugin_file;
- }
- }
-
- return false;
- }
-
- /**
- * Get the plugin slug from the plugin ID (composed of the plugin slug and the name of the main plugin file)
- *
- * @param string $plugin_file Plugin file (ID -- e.g. hello-dolly/hello.php).
- */
- protected static function get_slug_from_file_path( $plugin_file ) {
- // Similar to get_plugin_slug() method.
- $slug = dirname( $plugin_file );
- if ( '.' === $slug ) {
- $slug = preg_replace( '/(.+)\.php$/', '$1', $plugin_file );
- }
-
- return $slug;
- }
-
- /**
- * Get the activation status for a plugin.
- *
- * @since 8.9.0
- *
- * @param string $plugin_file The plugin file to check.
- * @return string Either 'network-active', 'active' or 'inactive'.
- */
- public static function get_plugin_status( $plugin_file ) {
- if ( is_plugin_active_for_network( $plugin_file ) ) {
- return 'network-active';
- }
-
- if ( is_plugin_active( $plugin_file ) ) {
- return 'active';
- }
-
- return 'inactive';
- }
-
- /**
- * Returns a list of all plugins in the site.
- *
- * @since 8.9.0
- * @uses get_plugins()
- *
- * @return array
- */
- public static function get_plugins() {
- if ( ! function_exists( 'get_plugins' ) ) {
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
- }
- /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
- $plugins = apply_filters( 'all_plugins', get_plugins() );
-
- if ( is_array( $plugins ) && ! empty( $plugins ) ) {
- foreach ( $plugins as $plugin_slug => $plugin_data ) {
- $plugins[ $plugin_slug ]['active'] = in_array(
- self::get_plugin_status( $plugin_slug ),
- array( 'active', 'network-active' ),
- true
- );
- }
- return $plugins;
- }
- return array();
- }
-}
+class_alias( Automattic\Jetpack\Plugins_Installer::class, 'Jetpack_Plugins' );
diff --git a/plugins/jetpack/_inc/lib/tonesque.php b/plugins/jetpack/_inc/lib/tonesque.php
index 0e148e5c..fcf970fd 100644
--- a/plugins/jetpack/_inc/lib/tonesque.php
+++ b/plugins/jetpack/_inc/lib/tonesque.php
@@ -1,22 +1,45 @@
-<?php
-/*
-Plugin Name: Tonesque
-Plugin URI: https://automattic.com/
-Description: Grab an average color representation from an image.
-Version: 1.0
-Author: Automattic, Matias Ventura
-Author URI: https://automattic.com/
-License: GNU General Public License v2 or later
-License URI: https://www.gnu.org/licenses/gpl-2.0.html
-*/
-
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
+/**
+ * Tonesque
+ * Grab an average color representation from an image.
+ * Author: Automattic, Matias Ventura
+ * Author URI: https://automattic.com/
+ * License: GNU General Public License v2 or later
+ * License URI: https://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * @package automattic/jetpack
+ */
+
+/**
+ * Color representation class.
+ */
class Tonesque {
+ /**
+ * Image URL.
+ *
+ * @var string
+ */
private $image_url = '';
- private $image_obj = NULL;
+ /**
+ * Image identifier representing the image.
+ *
+ * @var null|object
+ */
+ private $image_obj = null;
+ /**
+ * Color code.
+ *
+ * @var string
+ */
private $color = '';
- function __construct( $image_url ) {
+ /**
+ * Constructor.
+ *
+ * @param string $image_url Image URL.
+ */
+ public function __construct( $image_url ) {
if ( ! class_exists( 'Jetpack_Color' ) ) {
jetpack_require_lib( 'class.color' );
}
@@ -37,23 +60,29 @@ class Tonesque {
$this->image_obj = self::imagecreatefromurl( $this->image_url );
}
+ /**
+ * Get an image object from a URL.
+ *
+ * @param string $image_url Image URL.
+ *
+ * @return object Image object.
+ */
public static function imagecreatefromurl( $image_url ) {
$data = null;
- // If it's a URL:
+ // If it's a URL.
if ( preg_match( '#^https?://#i', $image_url ) ) {
- // If it's a url pointing to a local media library url:
+ // If it's a url pointing to a local media library url.
$content_url = content_url();
$_image_url = set_url_scheme( $image_url );
if ( wp_startswith( $_image_url, $content_url ) ) {
$_image_path = str_replace( $content_url, WP_CONTENT_DIR, $_image_url );
if ( file_exists( $_image_path ) ) {
$filetype = wp_check_filetype( $_image_path );
- $ext = $filetype['ext'];
- $type = $filetype['type'];
+ $type = $filetype['type'];
if ( wp_startswith( $type, 'image/' ) ) {
- $data = file_get_contents( $_image_path );
+ $data = file_get_contents( $_image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
}
}
}
@@ -67,14 +96,13 @@ class Tonesque {
}
}
- // If it's a local path in our WordPress install:
+ // If it's a local path in our WordPress install.
if ( file_exists( $image_url ) ) {
$filetype = wp_check_filetype( $image_url );
- $ext = $filetype['ext'];
- $type = $filetype['type'];
+ $type = $filetype['type'];
if ( wp_startswith( $type, 'image/' ) ) {
- $data = file_get_contents( $image_url );
+ $data = file_get_contents( $image_url ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
}
}
@@ -83,44 +111,45 @@ class Tonesque {
}
/**
- *
* Construct object from image.
*
- * @param optional $type (hex, rgb, hsv)
- * @return color as a string formatted as $type
+ * @param string $type Type (hex, rgb, hsv) (optional).
*
- */
- function color( $type = 'hex' ) {
- // Bail if there is no image to work with
- if ( ! $this->image_obj )
+ * @return color as a string formatted as $type
+ */
+ public function color( $type = 'hex' ) {
+ // Bail if there is no image to work with.
+ if ( ! $this->image_obj ) {
return false;
+ }
- // Finds dominant color
+ // Finds dominant color.
$color = self::grab_color();
- // Passes value to Color class
+ // Passes value to Color class.
$color = self::get_color( $color, $type );
return $color;
}
/**
- *
* Grabs the color index for each of five sample points of the image
*
- * @param $image
- * @param $type can be 'index' or 'hex'
- * @return array() with color indices
+ * @param string $type can be 'index' or 'hex'.
*
- */
- function grab_points( $type = 'index' ) {
+ * @return array with color indices
+ */
+ public function grab_points( $type = 'index' ) {
$img = $this->image_obj;
- if ( ! $img )
+ if ( ! $img ) {
return false;
+ }
$height = imagesy( $img );
$width = imagesx( $img );
- // Sample five points in the image
- // Based on rule of thirds and center
+ /*
+ * Sample five points in the image
+ * based on rule of thirds and center.
+ */
$topy = round( $height / 3 );
$bottomy = round( ( $height / 3 ) * 2 );
$leftx = round( $width / 3 );
@@ -128,7 +157,7 @@ class Tonesque {
$centery = round( $height / 2 );
$centerx = round( $width / 2 );
- // Cast those colors into an array
+ // Cast those colors into an array.
$points = array(
imagecolorat( $img, $leftx, $topy ),
imagecolorat( $img, $rightx, $topy ),
@@ -137,14 +166,17 @@ class Tonesque {
imagecolorat( $img, $centerx, $centery ),
);
- if ( 'hex' == $type ) {
+ if ( 'hex' === $type ) {
foreach ( $points as $i => $p ) {
- $c = imagecolorsforindex( $img, $p );
- $points[ $i ] = self::get_color( array(
- 'r' => $c['red'],
- 'g' => $c['green'],
- 'b' => $c['blue'],
- ), 'hex' );
+ $c = imagecolorsforindex( $img, $p );
+ $points[ $i ] = self::get_color(
+ array(
+ 'r' => $c['red'],
+ 'g' => $c['green'],
+ 'b' => $c['blue'],
+ ),
+ 'hex'
+ );
}
}
@@ -152,34 +184,37 @@ class Tonesque {
}
/**
- *
* Finds the average color of the image based on five sample points
*
- * @param $image
- * @return array() with rgb color
- *
- */
- function grab_color() {
+ * @return array with rgb color
+ */
+ public function grab_color() {
$img = $this->image_obj;
- if ( ! $img )
+ if ( ! $img ) {
return false;
+ }
$rgb = self::grab_points();
- // Process the color points
- // Find the average representation
+ $r = array();
+ $g = array();
+ $b = array();
+
+ /*
+ * Process the color points
+ * Find the average representation
+ */
foreach ( $rgb as $color ) {
$index = imagecolorsforindex( $img, $color );
- $r[] = $index['red'];
- $g[] = $index['green'];
- $b[] = $index['blue'];
-
- $red = round( array_sum( $r ) / 5 );
- $green = round( array_sum( $g ) / 5 );
- $blue = round( array_sum( $b ) / 5 );
+ $r[] = $index['red'];
+ $g[] = $index['green'];
+ $b[] = $index['blue'];
}
+ $red = round( array_sum( $r ) / 5 );
+ $green = round( array_sum( $g ) / 5 );
+ $blue = round( array_sum( $b ) / 5 );
- // The average color of the image as rgb array
+ // The average color of the image as rgb array.
$color = array(
'r' => $red,
'g' => $green,
@@ -190,29 +225,31 @@ class Tonesque {
}
/**
- *
* Get a Color object using /lib class.color
* Convert to appropriate type
*
- * @return string
+ * @param string $color Color code.
+ * @param string $type Color type (rgb, hex, hsv).
*
+ * @return string
*/
- function get_color( $color, $type ) {
- $c = new Jetpack_Color( $color, 'rgb' );
+ public function get_color( $color, $type ) {
+ $c = new Jetpack_Color( $color, 'rgb' );
$this->color = $c;
switch ( $type ) {
- case 'rgb' :
+ case 'rgb':
$color = implode( ',', $c->toRgbInt() );
break;
- case 'hex' :
+ case 'hex':
$color = $c->toHex();
break;
- case 'hsv' :
+ case 'hsv':
$color = implode( ',', $c->toHsvInt() );
break;
default:
- return $color = $c->toHex();
+ $color = $c->toHex();
+ return $color;
}
return $color;
@@ -224,14 +261,14 @@ class Tonesque {
* Gives either black or white for using with opacity
*
* @return string
- *
- */
- function contrast() {
- if ( ! $this->color )
+ */
+ public function contrast() {
+ if ( ! $this->color ) {
return false;
+ }
$c = $this->color->getMaxContrastColor();
return implode( ',', $c->toRgbInt() );
}
-};
+}
diff --git a/plugins/jetpack/_inc/lib/tracks/tracks-ajax.js b/plugins/jetpack/_inc/lib/tracks/tracks-ajax.js
deleted file mode 100644
index 98a9aaac..00000000
--- a/plugins/jetpack/_inc/lib/tracks/tracks-ajax.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/* global jpTracksAJAX, jQuery */
-( function( $, jpTracksAJAX ) {
- window.jpTracksAJAX = window.jpTracksAJAX || {};
- var debugSet = localStorage.getItem( 'debug' ) === 'dops:analytics';
-
- window.jpTracksAJAX.record_ajax_event = function( eventName, eventType, eventProp ) {
- var data = {
- tracksNonce: jpTracksAJAX.jpTracksAJAX_nonce,
- action: 'jetpack_tracks',
- tracksEventType: eventType,
- tracksEventName: eventName,
- tracksEventProp: eventProp || false,
- };
-
- return $.ajax( {
- type: 'POST',
- url: jpTracksAJAX.ajaxurl,
- data: data,
- success: function( response ) {
- if ( debugSet ) {
- // eslint-disable-next-line
- console.log( 'AJAX tracks event recorded: ', data, response );
- }
- },
- } );
- };
-
- $( document ).ready( function() {
- $( 'body' ).on( 'click', '.jptracks a, a.jptracks', function( event ) {
- var $this = $( event.target );
- // We know that the jptracks element is either this, or its ancestor
- var $jptracks = $this.closest( '.jptracks' );
- // We need an event name at least
- var eventName = $jptracks.attr( 'data-jptracks-name' );
- if ( undefined === eventName ) {
- return;
- }
-
- var eventProp = $jptracks.attr( 'data-jptracks-prop' ) || false;
-
- var url = $this.attr( 'href' );
- var target = $this.get( 0 ).target;
- if ( url && target && '_self' !== target ) {
- var newTabWindow = window.open( '', target );
- newTabWindow.opener = null;
- }
-
- event.preventDefault();
-
- window.jpTracksAJAX.record_ajax_event( eventName, 'click', eventProp ).always( function() {
- // Continue on to whatever url they were trying to get to.
- if ( url && ! $this.hasClass( 'thickbox' ) ) {
- if ( newTabWindow ) {
- newTabWindow.location = url;
- return;
- }
- window.location = url;
- }
- } );
- } );
- } );
-} )( jQuery, jpTracksAJAX );
diff --git a/plugins/jetpack/_inc/lib/tracks/tracks-callables.js b/plugins/jetpack/_inc/lib/tracks/tracks-callables.js
deleted file mode 100644
index 4e033d2c..00000000
--- a/plugins/jetpack/_inc/lib/tracks/tracks-callables.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * This was abstracted from wp-calypso's analytics lib: https://github.com/Automattic/wp-calypso/blob/master/client/lib/analytics/README.md
- * Some stuff was removed like GA tracking and other things not necessary for Jetpack tracking.
- *
- * This library should only be used and loaded if the Jetpack site is connected.
- */
-
-// Load tracking scripts
-window._tkq = window._tkq || [];
-
-var _user;
-var debug = console.error; // eslint-disable-line no-console
-
-function buildQuerystring( group, name ) {
- var uriComponent = '';
-
- if ( 'object' === typeof group ) {
- for ( var key in group ) {
- uriComponent += '&x_' + encodeURIComponent( key ) + '=' + encodeURIComponent( group[ key ] );
- }
- } else {
- uriComponent = '&x_' + encodeURIComponent( group ) + '=' + encodeURIComponent( name );
- }
-
- return uriComponent;
-}
-
-var analytics = {
- initialize: function( userId, username ) {
- analytics.setUser( userId, username );
- analytics.identifyUser();
- },
-
- mc: {
- bumpStat: function( group, name ) {
- var uriComponent = buildQuerystring( group, name ); // prints debug info
- new Image().src =
- document.location.protocol +
- '//pixel.wp.com/g.gif?v=wpcom-no-pv' +
- uriComponent +
- '&t=' +
- Math.random();
- },
- },
-
- tracks: {
- recordEvent: function( eventName, eventProperties ) {
- eventProperties = eventProperties || {};
-
- if ( eventName.indexOf( 'jetpack_' ) !== 0 ) {
- debug( '- Event name must be prefixed by "jetpack_"' );
- return;
- }
-
- window._tkq.push( [ 'recordEvent', eventName, eventProperties ] );
- },
-
- recordPageView: function( urlPath ) {
- analytics.tracks.recordEvent( 'jetpack_page_view', {
- path: urlPath,
- } );
- },
- },
-
- setUser: function( userId, username ) {
- _user = { ID: userId, username: username };
- },
-
- identifyUser: function() {
- // Don't identify the user if we don't have one
- if ( _user ) {
- window._tkq.push( [ 'identifyUser', _user.ID, _user.username ] );
- }
- },
-
- clearedIdentity: function() {
- window._tkq.push( [ 'clearIdentity' ] );
- },
-};
diff --git a/plugins/jetpack/_inc/lib/widgets.php b/plugins/jetpack/_inc/lib/widgets.php
index 6215a98a..d2cd5eda 100644
--- a/plugins/jetpack/_inc/lib/widgets.php
+++ b/plugins/jetpack/_inc/lib/widgets.php
@@ -1,4 +1,4 @@
-<?php
+<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* Widgets and Sidebars Library
*
@@ -7,9 +7,14 @@
*
* Used by the REST API
*
+ * @package automattic/jetpack
+ *
* @autounit api widgets
*/
+/**
+ * Widgets and Sidebars Library
+ */
class Jetpack_Widgets {
/**
@@ -31,18 +36,17 @@ class Jetpack_Widgets {
* The output looks like:
*
* array(
- * 'id' => 'text-3',
- * 'sidebar' => 'sidebar-1',
- * 'position' => '0',
- * 'settings' => array(
- * 'title' => 'hello world'
- * )
+ * 'id' => 'text-3',
+ * 'sidebar' => 'sidebar-1',
+ * 'position' => '0',
+ * 'settings' => array(
+ * 'title' => 'hello world'
+ * )
* )
*
- *
- * @param string|integer $position The position of the widget in its sidebar.
- * @param string $widget_id The widget's id (eg: 'text-3').
- * @param string $sidebar The widget's sidebar id (eg: 'sidebar-1').
+ * @param string|integer $position The position of the widget in its sidebar.
+ * @param string $widget_id The widget's id (eg: 'text-3').
+ * @param string $sidebar The widget's sidebar id (eg: 'sidebar-1').
* @param array (Optional) $settings The settings for the widget.
*
* @return array A normalized array representing this widget.
@@ -50,8 +54,8 @@ class Jetpack_Widgets {
public static function format_widget( $position, $widget_id, $sidebar, $settings = null ) {
if ( ! $settings ) {
$all_settings = get_option( self::get_widget_option_name( $widget_id ) );
- $instance = self::get_widget_instance_key( $widget_id );
- $settings = $all_settings[$instance];
+ $instance = self::get_widget_instance_key( $widget_id );
+ $settings = $all_settings[ $instance ];
}
$widget = array();
@@ -67,7 +71,7 @@ class Jetpack_Widgets {
/**
* Return a widget's id_base from its id.
*
- * @param string $widget_id The id of a widget. (eg: 'text-3')
+ * @param string $widget_id The id of a widget. (eg: 'text-3').
*
* @return string The id_base of a widget (eg: 'text').
*/
@@ -80,7 +84,7 @@ class Jetpack_Widgets {
* Determine a widget's option name (the WP option where the widget's settings
* are stored - generally `widget_` + the widget's id_base).
*
- * @param string $widget_id The id of a widget. (eg: 'text-3')
+ * @param string $widget_id The id of a widget. (eg: 'text-3').
*
* @return string The option name of the widget's settings. (eg: 'widget_text')
*/
@@ -98,7 +102,7 @@ class Jetpack_Widgets {
*/
public static function get_widget_instance_key( $widget_id ) {
// Grab all numbers from the end of the id.
- preg_match('/(\d+)$/', $widget_id, $matches );
+ preg_match( '/(\d+)$/', $widget_id, $matches );
return (int) $matches[0];
}
@@ -126,7 +130,7 @@ class Jetpack_Widgets {
* @return array An array of all widgets (see format_widget).
*/
public static function get_all_widgets() {
- $all_widgets = array();
+ $all_widgets = array();
$sidebars_widgets = self::get_all_sidebars();
foreach ( $sidebars_widgets as $sidebar => $widgets ) {
@@ -148,8 +152,8 @@ class Jetpack_Widgets {
*/
public static function get_active_widgets() {
$active_widgets = array();
- $all_widgets = self::get_all_widgets();
- foreach( $all_widgets as $widget ) {
+ $all_widgets = self::get_all_widgets();
+ foreach ( $all_widgets as $widget ) {
if ( 'wp_inactive_widgets' === $widget['sidebar'] ) {
continue;
}
@@ -164,7 +168,7 @@ class Jetpack_Widgets {
* @return array An array of all widget IDs.
*/
public static function get_all_widget_ids() {
- $all_widgets = array();
+ $all_widgets = array();
$sidebars_widgets = self::get_all_sidebars();
foreach ( array_values( $sidebars_widgets ) as $widgets ) {
if ( ! is_array( $widgets ) ) {
@@ -205,7 +209,6 @@ class Jetpack_Widgets {
public static function get_widgets_in_sidebar( $sidebar ) {
$sidebars = self::get_all_sidebars();
-
if ( ! $sidebars || ! is_array( $sidebars ) ) {
return null;
}
@@ -305,8 +308,11 @@ class Jetpack_Widgets {
public static function move_widget_to_sidebar( $widget, $sidebar, $position ) {
$sidebars_widgets = self::get_sidebars_widgets();
- // If a position is passed and the sidebar isn't empty,
- // splice the widget into the sidebar, update the sidebar option, and return the result
+ /*
+ * If a position is passed and the sidebar isn't empty,
+ * splice the widget into the sidebar,
+ * update the sidebar option, and return the result.
+ */
if ( isset( $widget['sidebar'] ) && isset( $widget['position'] ) ) {
array_splice( $sidebars_widgets[ $widget['sidebar'] ], $widget['position'], 1 );
}
@@ -316,9 +322,9 @@ class Jetpack_Widgets {
$sidebars_widgets[ $sidebar ] = array();
}
- // If no position is passed, set one from items in sidebar
+ // If no position is passed, set one from items in sidebar.
if ( ! isset( $position ) ) {
- $position = 0;
+ $position = 0;
$last_position = self::get_last_position_in_sidebar( $sidebar );
if ( isset( $last_position ) && is_numeric( $last_position ) ) {
$position = $last_position + 1;
@@ -329,10 +335,16 @@ class Jetpack_Widgets {
if ( empty( $sidebars_widgets[ $sidebar ] ) ) {
$sidebars_widgets[ $sidebar ][] = $widget['id'];
} else {
- array_splice( $sidebars_widgets[ $sidebar ], (int)$position, 0, $widget['id'] );
+ array_splice( $sidebars_widgets[ $sidebar ], (int) $position, 0, $widget['id'] );
}
- set_theme_mod( 'sidebars_widgets', array( 'time' => time(), 'data' => $sidebars_widgets ) );
+ set_theme_mod(
+ 'sidebars_widgets',
+ array(
+ 'time' => time(),
+ 'data' => $sidebars_widgets,
+ )
+ );
return update_option( 'sidebars_widgets', $sidebars_widgets );
}
@@ -365,21 +377,22 @@ class Jetpack_Widgets {
* any existing widget with the same `$widget_id`.
*
* @param string $widget_id The id of a widget.
- * @param array $settings An associative array of settings to merge with any existing settings on this widget.
+ * @param array $settings An associative array of settings to merge with any existing settings on this widget.
*
* @return boolean|WP_Error True if update was successful.
*/
public static function set_widget_settings( $widget_id, $settings ) {
$widget_option_name = self::get_widget_option_name( $widget_id );
- $widget_settings = get_option( $widget_option_name );
- $instance_key = self::get_widget_instance_key( $widget_id );
- $old_settings = $widget_settings[ $instance_key ];
+ $widget_settings = get_option( $widget_option_name );
+ $instance_key = self::get_widget_instance_key( $widget_id );
+ $old_settings = $widget_settings[ $instance_key ];
+ $settings = self::sanitize_widget_settings( $widget_id, $settings, $old_settings );
- if ( ! $settings = self::sanitize_widget_settings( $widget_id, $settings, $old_settings ) ) {
+ if ( ! $settings ) {
return new WP_Error( 'invalid_data', 'Update failed.', 500 );
}
if ( is_array( $old_settings ) ) {
- // array_filter prevents empty arguments from replacing existing ones
+ // array_filter prevents empty arguments from replacing existing ones.
$settings = wp_parse_args( array_filter( $settings ), $old_settings );
}
@@ -392,13 +405,15 @@ class Jetpack_Widgets {
* Sanitize an associative array for saving.
*
* @param string $widget_id The id of a widget.
- * @param array $settings A widget settings array.
- * @param array $old_settings The existing widget settings array.
+ * @param array $settings A widget settings array.
+ * @param array $old_settings The existing widget settings array.
*
* @return array|false The settings array sanitized by `WP_Widget::update` or false if sanitization failed.
*/
private static function sanitize_widget_settings( $widget_id, $settings, $old_settings ) {
- if ( ! $widget = self::get_registered_widget_object( self::get_widget_id_base( $widget_id ) ) ) {
+ $widget = self::get_registered_widget_object( self::get_widget_id_base( $widget_id ) );
+
+ if ( ! $widget ) {
return false;
}
$new_settings = $widget->update( $settings, $old_settings );
@@ -416,7 +431,7 @@ class Jetpack_Widgets {
*/
public static function remove_widget_settings( $widget ) {
$widget_option_name = self::get_widget_option_name( $widget['id'] );
- $widget_settings = get_option( $widget_option_name );
+ $widget_settings = get_option( $widget_option_name );
unset( $widget_settings[ self::get_widget_instance_key( $widget['id'] ) ] );
update_option( $widget_option_name, $widget_settings );
}
@@ -425,9 +440,9 @@ class Jetpack_Widgets {
* Update a widget's settings, sidebar, and position. Returns the (updated)
* formatted widget if successful or a WP_Error if it fails.
*
- * @param string $widget_id The id of a widget to update.
- * @param string $sidebar (Optional) A sidebar to which this widget will be moved.
- * @param string|integer (Optional) A new position to which this widget will be moved within its new or existing sidebar.
+ * @param string $widget_id The id of a widget to update.
+ * @param string $sidebar (Optional) A sidebar to which this widget will be moved.
+ * @param string|integer $position (Optional) A new position to which this widget will be moved within its new or existing sidebar.
* @param array|object|string $settings Settings to merge with the existing settings of the widget (will be passed through `decode_settings`).
*
* @return array|WP_Error The newly added widget as an associative array with all the above properties.
@@ -470,7 +485,7 @@ class Jetpack_Widgets {
* Deletes a widget entirely including all its settings. Returns a WP_Error if
* the widget could not be found. Otherwise returns an empty array.
*
- * @param string $widget_id The id of a widget to delete. (eg: 'text-2')
+ * @param string $widget_id The id of a widget to delete. (eg: 'text-2').
*
* @return array|WP_Error An empty array if successful.
*/
@@ -493,14 +508,14 @@ class Jetpack_Widgets {
* @return array Decoded associative array of settings.
*/
public static function decode_settings( $settings ) {
- // Treat as string in case JSON was passed
+ // Treat as string in case JSON was passed.
if ( is_object( $settings ) && property_exists( $settings, 'scalar' ) ) {
$settings = $settings->scalar;
}
if ( is_object( $settings ) ) {
$settings = (array) $settings;
}
- // Attempt to decode JSON string
+ // Attempt to decode JSON string.
if ( is_string( $settings ) ) {
$settings = (array) json_decode( $settings );
}
@@ -510,9 +525,9 @@ class Jetpack_Widgets {
/**
* Activate a new widget.
*
- * @param string $id_base The id_base of the new widget (eg: 'text')
- * @param string $sidebar The id of the sidebar where this widget will go. Dependent on theme. (eg: 'sidebar-1')
- * @param string|integer $position (Optional) The position of the widget in the sidebar. Defaults to the last position.
+ * @param string $id_base The id_base of the new widget (eg: 'text').
+ * @param string $sidebar The id of the sidebar where this widget will go. Dependent on theme. (eg: 'sidebar-1').
+ * @param string|integer $position (Optional) The position of the widget in the sidebar. Defaults to the last position.
* @param array|object|string $settings (Optional) An associative array of settings for this widget (will be passed through `decode_settings`). Varies by widget.
*
* @return array|WP_Error The newly added widget as an associative array with all the above properties except 'id_base' replaced with the generated 'id'.
@@ -541,7 +556,7 @@ class Jetpack_Widgets {
}
$widget_counter = 1 + self::get_last_widget_instance_key_with_id_base( $id_base );
- $widget_id = $id_base . '-' . $widget_counter;
+ $widget_id = $id_base . '-' . $widget_counter;
if ( 0 >= $widget_counter ) {
return new WP_Error( 'invalid_data', 'Error creating widget ID' . $widget_id, 500 );
}
@@ -585,7 +600,7 @@ class Jetpack_Widgets {
$added_widgets = array();
- foreach( $widgets as $widget ) {
+ foreach ( $widgets as $widget ) {
$added_widgets[] = self::activate_widget( $widget['id_base'], $widget['sidebar'], $widget['position'], $widget['settings'] );
}
@@ -597,7 +612,7 @@ class Jetpack_Widgets {
* `$id_base`. So if you pass in `text`, and there is a widget with the id
* `text-2`, this function will return `2`.
*
- * @param string $id_base The id_base of a type of widget. (eg: 'rss')
+ * @param string $id_base The id_base of a type of widget. (eg: 'rss').
*
* @return integer The last instance key of that type of widget.
*/
@@ -605,11 +620,11 @@ class Jetpack_Widgets {
$similar_widgets = self::get_widgets_with_id_base( $id_base );
if ( ! empty( $similar_widgets ) ) {
- // If the last widget with the same name is `text-3`, we want `text-4`
+ // If the last widget with the same name is `text-3`, we want `text-4`.
usort( $similar_widgets, __CLASS__ . '::sort_widgets' );
$last_widget = array_pop( $similar_widgets );
- $last_val = (int) self::get_widget_instance_key( $last_widget['id'] );
+ $last_val = (int) self::get_widget_instance_key( $last_widget['id'] );
return $last_val;
}
@@ -622,8 +637,8 @@ class Jetpack_Widgets {
*
* @since 5.4
*
- * @param array $a
- * @param array $b
+ * @param array $a A normalized array representing a widget.
+ * @param array $b A normalized array representing a widget.
*
* @return int
*/
@@ -685,36 +700,36 @@ class Jetpack_Widgets {
* Insert a new widget in a given sidebar.
*
* @param string $widget_id ID of the widget.
- * @param array $widget_options Content of the widget.
- * @param string $sidebar ID of the sidebar to which the widget will be added.
- *
- * @return WP_Error|true True when data has been saved correctly, error otherwise.
- */
- static function insert_widget_in_sidebar( $widget_id, $widget_options, $sidebar ) {
- // Retrieve sidebars, widgets and their instances
+ * @param array $widget_options Content of the widget.
+ * @param string $sidebar ID of the sidebar to which the widget will be added.
+ *
+ * @return WP_Error|true True when data has been saved correctly, error otherwise.
+ */
+ public static function insert_widget_in_sidebar( $widget_id, $widget_options, $sidebar ) {
+ // Retrieve sidebars, widgets and their instances.
$sidebars_widgets = get_option( 'sidebars_widgets', array() );
$widget_instances = get_option( 'widget_' . $widget_id, array() );
- // Retrieve the key of the next widget instance
+ // Retrieve the key of the next widget instance.
$numeric_keys = array_filter( array_keys( $widget_instances ), 'is_int' );
- $next_key = $numeric_keys ? max( $numeric_keys ) + 1 : 2;
+ $next_key = $numeric_keys ? max( $numeric_keys ) + 1 : 2;
- // Add this widget to the sidebar
+ // Add this widget to the sidebar.
if ( ! isset( $sidebars_widgets[ $sidebar ] ) ) {
$sidebars_widgets[ $sidebar ] = array();
}
$sidebars_widgets[ $sidebar ][] = $widget_id . '-' . $next_key;
- // Add the new widget instance
+ // Add the new widget instance.
$widget_instances[ $next_key ] = $widget_options;
- // Store updated sidebars, widgets and their instances
+ // Store updated sidebars, widgets and their instances.
if (
! ( update_option( 'sidebars_widgets', $sidebars_widgets ) )
|| ( ! ( update_option( 'widget_' . $widget_id, $widget_instances ) ) )
) {
return new WP_Error( 'widget_update_failed', 'Failed to update widget or sidebar.', 400 );
- };
+ }
return true;
}
@@ -723,17 +738,17 @@ class Jetpack_Widgets {
* Update the content of an existing widget in a given sidebar.
*
* @param string $widget_id ID of the widget.
- * @param array $widget_options New content for the update.
- * @param string $sidebar ID of the sidebar to which the widget will be added.
- *
- * @return WP_Error|true True when data has been updated correctly, error otherwise.
- */
- static function update_widget_in_sidebar( $widget_id, $widget_options, $sidebar ) {
- // Retrieve sidebars, widgets and their instances
+ * @param array $widget_options New content for the update.
+ * @param string $sidebar ID of the sidebar to which the widget will be added.
+ *
+ * @return WP_Error|true True when data has been updated correctly, error otherwise.
+ */
+ public static function update_widget_in_sidebar( $widget_id, $widget_options, $sidebar ) {
+ // Retrieve sidebars, widgets and their instances.
$sidebars_widgets = get_option( 'sidebars_widgets', array() );
$widget_instances = get_option( 'widget_' . $widget_id, array() );
- // Retrieve index of first widget instance in that sidebar
+ // Retrieve index of first widget instance in that sidebar.
$widget_key = false;
foreach ( $sidebars_widgets[ $sidebar ] as $widget ) {
if ( strpos( $widget, $widget_id ) !== false ) {
@@ -742,23 +757,23 @@ class Jetpack_Widgets {
}
}
- // There is no widget instance
+ // There is no widget instance.
if ( ! $widget_key ) {
return new WP_Error( 'invalid_data', 'No such widget.', 400 );
}
- // Update the widget instance and option if the data has changed
+ // Update the widget instance and option if the data has changed.
if ( $widget_instances[ $widget_key ]['title'] !== $widget_options['title']
|| $widget_instances[ $widget_key ]['address'] !== $widget_options['address']
) {
$widget_instances[ $widget_key ] = array_merge( $widget_instances[ $widget_key ], $widget_options );
- // Store updated widget instances and return Error when not successful
+ // Store updated widget instances and return Error when not successful.
if ( ! ( update_option( 'widget_' . $widget_id, $widget_instances ) ) ) {
return new WP_Error( 'widget_update_failed', 'Failed to update widget.', 400 );
- };
- };
+ }
+ }
return true;
}
@@ -766,10 +781,10 @@ class Jetpack_Widgets {
* Retrieve the first active sidebar.
*
* @return string|WP_Error First active sidebar, error if none exists.
- */
- static function get_first_sidebar() {
+ */
+ public static function get_first_sidebar() {
$active_sidebars = get_option( 'sidebars_widgets', array() );
- unset( $active_sidebars[ 'wp_inactive_widgets' ], $active_sidebars[ 'array_version' ] );
+ unset( $active_sidebars['wp_inactive_widgets'], $active_sidebars['array_version'] );
if ( empty( $active_sidebars ) ) {
return false;