updated plugin Jetpack Protect version 2.2.0

This commit is contained in:
KawaiiPunk 2024-06-27 12:10:57 +00:00 committed by Gitium
parent ec9d8a5834
commit 938cef2946
218 changed files with 7469 additions and 1864 deletions

View File

@ -5,20 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.1.0 - 2024-04-10
## 2.2.0 - 2024-05-24
### Added
- Add data to WAF logs and a toggle for users to opt-in to share more data with us if needed. [#36377]
- Trigger a red bubble notification when a bad install is detected. [#36449]
### Changed
- Update WordPress minimum version requirement to WordPress 6.4. [#37047]
- Only show installation errors on the plugins page. [#36390]
### Fixed
- Jetpack Protect Footer: ensure that "Go to cloud" links are not shown when on a platform with no firewall support. [#36794]
## 2.1.0 - 2024-03-14
### Added
- Add data to WAF logs and add toggle for users to opt-in to share more data with us if needed. [#36377]
- Added firewall standalone mode indicator. [#34840]
- Added onboarding flows. [#34649]
- Added firewall standalone mode indicator. [#34840]
### Changed
- General: indicate compatibility with the upcoming version of WordPress, 6.5. [#35820]
- Use blog ID instead of site slug in checkout links. [#35004]
- Updated package dependencies. [#36325]
- Updated package lockfile. [#35672]
- Use blog ID instead of site slug in checkout links. [#35004]
### Fixed
- Jetpack Protect footer: Ensured that links to the cloud and the promotion around it are not shown if you are on a platform where the firewall is not supported. [#36794]
- Prevent text orphans in the site scanning header. [#35935]
## 2.0.0 - 2024-01-18

View File

@ -1 +1 @@
<?php return array('dependencies' => array('moment', 'react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => 'c12994dcc943f0a86ea0');
<?php return array('dependencies' => array('moment', 'react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => 'fe97d1535658daaa9984');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,23 +5,23 @@
"license": "GPL-2.0-or-later",
"require": {
"ext-json": "*",
"automattic/jetpack-assets": "^2.1.4",
"automattic/jetpack-admin-ui": "^0.4.1",
"automattic/jetpack-autoloader": "^3.0.3",
"automattic/jetpack-assets": "^2.1.11",
"automattic/jetpack-admin-ui": "^0.4.2",
"automattic/jetpack-autoloader": "^3.0.7",
"automattic/jetpack-composer-plugin": "^2.0.1",
"automattic/jetpack-config": "^2.0.1",
"automattic/jetpack-identity-crisis": "^0.17.3",
"automattic/jetpack-my-jetpack": "^4.17.0",
"automattic/jetpack-plugins-installer": "^0.3.2",
"automattic/jetpack-sync": "^2.10.1",
"automattic/jetpack-transport-helper": "^0.2.2",
"automattic/jetpack-plans": "^0.4.3",
"automattic/jetpack-waf": "^0.16.0.1",
"automattic/jetpack-status": "^2.1.2"
"automattic/jetpack-config": "^2.0.2",
"automattic/jetpack-identity-crisis": "^0.20.0",
"automattic/jetpack-my-jetpack": "^4.24.1",
"automattic/jetpack-plugins-installer": "^0.4.0",
"automattic/jetpack-sync": "^2.16.6",
"automattic/jetpack-transport-helper": "^0.2.3",
"automattic/jetpack-plans": "^0.4.7",
"automattic/jetpack-waf": "^0.16.8",
"automattic/jetpack-status": "^3.2.0"
},
"require-dev": {
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-changelogger": "^4.2.4",
"automattic/wordbless": "0.4.2"
},
"autoload": {
@ -71,6 +71,6 @@
"automattic/jetpack-autoloader": true,
"automattic/jetpack-composer-plugin": true
},
"autoloader-suffix": "c4802e05bbcf59fd3b6350e8d3e5482c_protectⓥ2_1_0"
"autoloader-suffix": "c4802e05bbcf59fd3b6350e8d3e5482c_protectⓥ2_2_0"
}
}

View File

@ -3,7 +3,7 @@
* Plugin Name: Jetpack Protect
* Plugin URI: https://wordpress.org/plugins/jetpack-protect
* Description: Security tools that keep your site safe and sound, from posts to plugins.
* Version: 2.1.0
* Version: 2.2.0
* Author: Automattic - Jetpack Security team
* Author URI: https://jetpack.com/protect/
* License: GPLv2 or later
@ -32,7 +32,7 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'JETPACK_PROTECT_VERSION', '2.1.0' );
define( 'JETPACK_PROTECT_VERSION', '2.2.0' );
define( 'JETPACK_PROTECT_DIR', plugin_dir_path( __FILE__ ) );
define( 'JETPACK_PROTECT_ROOT_FILE', __FILE__ );
define( 'JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH', plugin_basename( __FILE__ ) );
@ -56,31 +56,48 @@ if ( is_readable( $jetpack_autoloader ) ) {
);
}
// Add a red bubble notification to My Jetpack if the installation is bad.
add_filter(
'my_jetpack_red_bubble_notification_slugs',
function ( $slugs ) {
$slugs['jetpack-protect-plugin-bad-installation'] = array(
'data' => array(
'plugin' => 'Jetpack Protect',
),
);
return $slugs;
}
);
add_action(
'admin_notices',
function () {
?>
<div class="notice notice-error is-dismissible">
<p>
<?php
printf(
wp_kses(
/* translators: Placeholder is a link to a support document. */
__( 'Your installation of Jetpack Protect is incomplete. If you installed Jetpack Protect from GitHub, please refer to <a href="%1$s" target="_blank" rel="noopener noreferrer">this document</a> to set up your development environment. Jetpack Protect must have Composer dependencies installed and built via the build command.', 'jetpack-protect' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
)
),
'https://github.com/Automattic/jetpack/blob/trunk/docs/development-environment.md#building-your-project'
);
?>
</p>
</div>
<?php
if ( get_current_screen()->id !== 'plugins' ) {
return;
}
$message = sprintf(
wp_kses(
/* translators: Placeholder is a link to a support document. */
__( 'Your installation of Jetpack Protect is incomplete. If you installed Jetpack Protect from GitHub, please refer to <a href="%1$s" target="_blank" rel="noopener noreferrer">this document</a> to set up your development environment. Jetpack Protect must have Composer dependencies installed and built via the build command.', 'jetpack-protect' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
)
),
'https://github.com/Automattic/jetpack/blob/trunk/docs/development-environment.md#building-your-project'
);
wp_admin_notice(
$message,
array(
'type' => 'error',
'dismissible' => true,
)
);
}
);
@ -98,7 +115,7 @@ add_action( 'activated_plugin', 'jetpack_protect_plugin_activation' );
function jetpack_protect_plugin_activation( $plugin ) {
if (
JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH === $plugin &&
\Automattic\Jetpack\Plugins_Installer::is_current_request_activating_plugin_from_plugins_screen( JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH )
( new \Automattic\Jetpack\Paths() )->is_current_request_activating_plugin_from_plugins_screen( JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH )
) {
wp_safe_redirect( esc_url( admin_url( 'admin.php?page=jetpack-protect' ) ) );
exit;

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.4.2] - 2024-04-22
### Changed
- Internal updates.
## [0.4.1] - 2024-03-12
### Changed
- Internal updates.
@ -144,6 +148,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixing menu visibility issues.
[0.4.2]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.1...0.4.2
[0.4.1]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/Automattic/jetpack-admin-ui/compare/0.3.2...0.4.0
[0.3.2]: https://github.com/Automattic/jetpack-admin-ui/compare/0.3.1...0.3.2

View File

@ -8,8 +8,8 @@
},
"require-dev": {
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-logo": "^2.0.1",
"automattic/jetpack-changelogger": "^4.2.2",
"automattic/jetpack-logo": "^2.0.2",
"automattic/wordbless": "dev-master"
},
"suggest": {

View File

@ -13,7 +13,7 @@ namespace Automattic\Jetpack\Admin_UI;
*/
class Admin_Menu {
const PACKAGE_VERSION = '0.4.1';
const PACKAGE_VERSION = '0.4.2';
/**
* Whether this class has been initialized

View File

@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.1.11] - 2024-05-20
### Changed
- Internal updates.
## [2.1.10] - 2024-05-16
### Added
- Assets: Adding comments to explain why we use variables within translation functions [#37397]
### Changed
- Updated package dependencies. [#37379]
## [2.1.9] - 2024-05-06
### Changed
- Updated package dependencies. [#37147]
## [2.1.8] - 2024-04-22
### Changed
- Internal updates.
## [2.1.7] - 2024-04-08
### Changed
- Updated package dependencies. [#36760]
## [2.1.6] - 2024-03-27
### Changed
- Updated package dependencies. [#36585]
## [2.1.5] - 2024-03-18
### Changed
- Internal updates.
## [2.1.4] - 2024-03-12
### Changed
- Internal updates.
@ -419,6 +450,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Statically access asset tools
[2.1.11]: https://github.com/Automattic/jetpack-assets/compare/v2.1.10...v2.1.11
[2.1.10]: https://github.com/Automattic/jetpack-assets/compare/v2.1.9...v2.1.10
[2.1.9]: https://github.com/Automattic/jetpack-assets/compare/v2.1.8...v2.1.9
[2.1.8]: https://github.com/Automattic/jetpack-assets/compare/v2.1.7...v2.1.8
[2.1.7]: https://github.com/Automattic/jetpack-assets/compare/v2.1.6...v2.1.7
[2.1.6]: https://github.com/Automattic/jetpack-assets/compare/v2.1.5...v2.1.6
[2.1.5]: https://github.com/Automattic/jetpack-assets/compare/v2.1.4...v2.1.5
[2.1.4]: https://github.com/Automattic/jetpack-assets/compare/v2.1.3...v2.1.4
[2.1.3]: https://github.com/Automattic/jetpack-assets/compare/v2.1.2...v2.1.3
[2.1.2]: https://github.com/Automattic/jetpack-assets/compare/v2.1.1...v2.1.2

View File

@ -5,12 +5,12 @@
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-constants": "^2.0.1"
"automattic/jetpack-constants": "^2.0.2"
},
"require-dev": {
"brain/monkey": "2.6.1",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-changelogger": "^4.2.4",
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0 || ^3.0"
},
"suggest": {

View File

@ -651,7 +651,7 @@ class Assets {
*/
public static function filter_gettext( $translation, $text, $domain ) {
if ( $translation === $text ) {
// phpcs:ignore WordPress.WP.I18n
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$newtext = __( $text, self::$domain_map[ $domain ][0] );
if ( $newtext !== $text ) {
return $newtext;
@ -673,7 +673,7 @@ class Assets {
*/
public static function filter_ngettext( $translation, $single, $plural, $number, $domain ) {
if ( $translation === $single || $translation === $plural ) {
// phpcs:ignore WordPress.WP.I18n
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _n( $single, $plural, $number, self::$domain_map[ $domain ][0] );
}
return $translation;
@ -691,7 +691,7 @@ class Assets {
*/
public static function filter_gettext_with_context( $translation, $text, $context, $domain ) {
if ( $translation === $text ) {
// phpcs:ignore WordPress.WP.I18n
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _x( $text, $context, self::$domain_map[ $domain ][0] );
}
return $translation;
@ -711,7 +711,7 @@ class Assets {
*/
public static function filter_ngettext_with_context( $translation, $single, $plural, $number, $context, $domain ) {
if ( $translation === $single || $translation === $plural ) {
// phpcs:ignore WordPress.WP.I18n
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _nx( $single, $plural, $number, $context, self::$domain_map[ $domain ][0] );
}
return $translation;

View File

@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.6] - 2024-04-08
### Changed
- Internal updates.
## [0.2.5] - 2024-03-25
### Fixed
- Backup: change some error messages to not trigger security scanners [#36496]
## [0.2.4] - 2024-03-18
### Changed
- Internal updates.
@ -29,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Initial release (improved helper script installer logging). [#34297]
[0.2.6]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.1...v0.2.2

View File

@ -9,7 +9,7 @@
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0003;
namespace Automattic\Jetpack\Backup\V0004;
use Exception;
use WP_Error;

View File

@ -9,7 +9,7 @@
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0003;
namespace Automattic\Jetpack\Backup\V0004;
/**
* Manage installation, deletion and cleanup of Helper Scripts to assist with backing up Jetpack Sites.

View File

@ -8,7 +8,7 @@
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0003;
namespace Automattic\Jetpack\Backup\V0004;
use Exception;
use Throwable;
@ -430,7 +430,7 @@ class Throw_On_Errors {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for file_put_contents() is unset' );
throw new Exception( 'Filename for f_p_c() is unset' );
}
if ( $data === null ) {
throw new Exception( 'Data to write is null' );
@ -438,7 +438,8 @@ class Throw_On_Errors {
$data_length = strlen( $data );
$label = "file_put_contents( '$filename', $data_length bytes of data )";
// Weird label is intentional, otherwise security scanners find this label suspicious.
$label = "f_p_c( '$filename', $data_length bytes of data )";
$number_of_bytes_written = static::throw_on_warnings(
function () use ( $filename, $data ) {
@ -474,12 +475,13 @@ class Throw_On_Errors {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for file_get_contents() is unset' );
throw new Exception( 'Filename for f_g_c() is unset' );
}
$label = "file_get_contents( '$filename' )";
// Weird label is intentional, otherwise security scanners find this label suspicious.
$label = "f_g_c( '$filename' )";
$file_get_contents_result = static::throw_on_warnings(
$fgc_result = static::throw_on_warnings(
function () use ( $filename ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
return file_get_contents( $filename );
@ -487,10 +489,10 @@ class Throw_On_Errors {
$label
);
if ( false === $file_get_contents_result ) {
if ( false === $fgc_result ) {
throw new Exception( "Unable to $label" );
}
return $file_get_contents_result;
return $fgc_result;
}
}

View File

@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.7] - 2024-05-06
### Added
- Add missing package dependencies. [#37141]
## [0.2.6] - 2024-03-25
### Changed
- Internal updates.
## [0.2.5] - 2024-03-14
### Changed
- Internal updates.
@ -49,6 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Introduce new package. [#31163]
[0.2.7]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.6...v0.2.7
[0.2.6]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.2...v0.2.3

View File

@ -4,11 +4,12 @@
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0"
"php": ">=7.0",
"automattic/jetpack-connection": "^2.7.6"
},
"require-dev": {
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-changelogger": "^4.2.3",
"automattic/wordbless": "dev-master"
},
"autoload": {

View File

@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.11] - 2024-04-22
### Changed
- Internal updates.
## [0.3.10] - 2024-04-08
### Changed
- Bump project version. [#36072]
## [0.3.9] - 2024-03-27
### Added
- Use `jetpack_boost_critical_css_environment_changed` hook instead of `handle_environment_change` [#36519]
### Changed
- Speed Score: More accurately detect which modules are active when a speed score is requested. [#36534]
### Fixed
- Updated Jetpack_Boost_Modules placeholder class to match Boost interface [#36598]
## [0.3.8] - 2024-03-25
### Changed
- Internal updates.
## [0.3.7] - 2024-03-18
### Changed
- Internal updates.
@ -62,6 +84,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add a new package for Boost Speed Score [#30914]
- Add a new argument to `Speed_Score` to identify where the request was made from (e.g. 'boost-plugin', 'jetpack-dashboard', etc). [#31012]
[0.3.11]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.10...v0.3.11
[0.3.10]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.9...v0.3.10
[0.3.9]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.8...v0.3.9
[0.3.8]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.7...v0.3.8
[0.3.7]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.4...v0.3.5

View File

@ -5,7 +5,7 @@
"license": "GPL-2.0-or-later",
"require-dev": {
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.2",
"automattic/jetpack-changelogger": "^4.2.2",
"brain/monkey": "^2.6"
},
"autoload-dev": {
@ -15,7 +15,7 @@
},
"require": {
"php": ">=7.0",
"automattic/jetpack-boost-core": "^0.2.5"
"automattic/jetpack-boost-core": "^0.2.6"
},
"autoload": {
"classmap": [

View File

@ -37,11 +37,11 @@ class Jetpack_Boost_Modules {
return self::$instance;
}
/**
* Returns status of all active boost modules
* Returns status of all active boost modules that are also ready
*
* @return array - An empty array. The user will never have active modules when using the Boost Score API
*/
public function get_status() {
public function get_ready_active_optimization_modules() {
return array();
}

View File

@ -22,14 +22,14 @@ class Speed_Score_Graph_History_Request extends Cacheable {
/**
* The timestamp start windown in ms.
*
* @var number $start timestamp start windown in ms.
* @var int|float $start timestamp start windown in ms.
*/
private $start;
/**
* The timestamp end windown in ms.
*
* @var number $end timestamp end windown in ms.
* @var int|float $end timestamp end windown in ms.
*/
private $end;
@ -57,9 +57,9 @@ class Speed_Score_Graph_History_Request extends Cacheable {
/**
* Constructor.
*
* @param number $start timestamp start windown in ms.
* @param number $end timestamp end windown in ms.
* @param array $error Speed Scores error.
* @param int|float $start timestamp start windown in ms.
* @param int|float $end timestamp end windown in ms.
* @param array $error Speed Scores error.
*/
public function __construct( $start, $end, $error ) {
$this->start = $start;

View File

@ -30,7 +30,7 @@ class Speed_Score_Request extends Cacheable {
/**
* Active Jetpack Boost modules.
*
* @var array $active_modules Active modules.
* @var string[] $active_modules Active modules.
*/
private $active_modules;
@ -105,21 +105,10 @@ class Speed_Score_Request extends Cacheable {
/**
* Get the list of active performance modules while this request was created.
*
* @return string
* @return string[]
*/
public function get_active_performance_modules() {
// List of modules that affect the speed score.
$performance_modules = array(
'cloud_css',
'critical_css',
'image_cdn',
'minify_css',
'minify_js',
'render_blocking_js',
);
return array_intersect( $this->active_modules, $performance_modules );
public function get_active_modules() {
return $this->active_modules;
}
/**
@ -130,7 +119,7 @@ class Speed_Score_Request extends Cacheable {
return array(
'id' => $this->get_cache_id(),
'url' => $this->url,
'active_modules' => $this->get_active_performance_modules(),
'active_modules' => $this->get_active_modules(),
'created' => $this->created,
'status' => $this->status,
'error' => $this->error,

View File

@ -23,12 +23,12 @@ if ( ! defined( 'JETPACK_BOOST_REST_PREFIX' ) ) {
*/
class Speed_Score {
const PACKAGE_VERSION = '0.3.7';
const PACKAGE_VERSION = '0.3.11';
/**
* An instance of Automatic\Jetpack_Boost\Modules\Modules_Setup passed to the constructor
* Array of module slugs that are currently active and can impact speed score.
*
* @var Modules_Setup
* @var string[]
*/
protected $modules;
@ -42,16 +42,35 @@ class Speed_Score {
/**
* Constructor.
*
* @param Modules_Setup $modules - An instance of Automatic\Jetpack_Boost\Modules\Modules_Setup.
* @param string $client - A string representing the client making the request.
* @param string[] $modules - Array of module slugs that are currently active and can impact speed score.
* @param string $client - A string representing the client making the request.
*/
public function __construct( $modules, $client ) {
/*
* Plugins using the old version of the package may pass an object instead of an array. Converting the
* object to an array keeps it backward compatible. We will lose the module slugs in case of an object,
* but it is better than a fatal error.
*/
if ( ! is_array( $modules ) ) {
$modules = array();
}
$this->modules = $modules;
$this->client = $client;
add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
add_action( 'jetpack_boost_deactivate', array( $this, 'clear_speed_score_request_cache' ) );
/**
* Mark the speed score history as stale when the environment changes.
*
* @since 0.3.9 - This hook replaced `handle_environment_change` action.
*/
add_action( 'jetpack_boost_critical_css_environment_changed', array( Speed_Score_History::class, 'mark_stale' ) );
/**
* The `handle_environment_change` action is replaced by `jetpack_boost_critical_css_environment_changed` in Jetpack Boost.
* Keeping the `handle_environment_change` action for backward compatibility.
*/
add_action( 'handle_environment_change', array( Speed_Score_History::class, 'mark_stale' ) );
add_action( 'jetpack_boost_deactivate', array( Speed_Score_History::class, 'mark_stale' ) );
}
@ -139,8 +158,7 @@ class Speed_Score {
}
// Create and store the Speed Score request.
$active_modules = array_keys( array_filter( $this->modules->get_status(), 'strlen' ) );
$score_request = new Speed_Score_Request( $url, $active_modules, null, 'pending', null, $this->client );
$score_request = new Speed_Score_Request( $url, $this->modules, null, 'pending', null, $this->client );
$score_request->store( 1800 ); // Keep the request for 30 minutes even if no one access the results.
// Send the request.
@ -241,7 +259,7 @@ class Speed_Score {
if (
// If there isn't already a pending request.
( empty( $score_request ) || ! $score_request->is_pending() )
&& $this->modules->have_enabled_modules()
&& ! empty( $this->modules )
&& $history->is_stale()
) {
$score_request = new Speed_Score_Request( $url_no_boost, array(), null, 'pending', null, $this->client ); // Dispatch a new speed score request to measure score without boost.
@ -320,7 +338,7 @@ class Speed_Score {
);
// Only include noBoost scores if at least one module is enabled.
if ( $score_request && ! empty( $score_request->get_active_performance_modules() ) ) {
if ( $score_request && ! empty( $score_request->get_active_modules() ) ) {
$response['scores']['noBoost'] = $history_no_boost->latest_scores();
}

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.2] - 2024-05-06
### Changed
- Internal updates.
## [2.0.1] - 2024-03-14
### Changed
- Internal updates.
@ -196,6 +200,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Trying to add deterministic initialization.
[2.0.2]: https://github.com/Automattic/jetpack-config/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-config/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-config/compare/v1.15.4...v2.0.0
[1.15.4]: https://github.com/Automattic/jetpack-config/compare/v1.15.3...v1.15.4

View File

@ -7,7 +7,21 @@
"php": ">=7.0"
},
"require-dev": {
"automattic/jetpack-changelogger": "^4.1.1"
"automattic/jetpack-changelogger": "^4.2.3",
"automattic/jetpack-connection": "@dev",
"automattic/jetpack-identity-crisis": "@dev",
"automattic/jetpack-import": "@dev",
"automattic/jetpack-jitm": "@dev",
"automattic/jetpack-post-list": "@dev",
"automattic/jetpack-publicize": "@dev",
"automattic/jetpack-search": "@dev",
"automattic/jetpack-stats": "@dev",
"automattic/jetpack-stats-admin": "@dev",
"automattic/jetpack-sync": "@dev",
"automattic/jetpack-videopress": "@dev",
"automattic/jetpack-waf": "@dev",
"automattic/jetpack-wordads": "@dev",
"automattic/jetpack-yoast-promo": "@dev"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
@ -28,6 +42,29 @@
},
"branch-alias": {
"dev-trunk": "2.0.x-dev"
},
"dependencies": {
"test-only": [
"packages/connection",
"packages/identity-crisis",
"packages/import",
"packages/jitm",
"packages/post-list",
"packages/publicize",
"packages/search",
"packages/stats",
"packages/stats-admin",
"packages/sync",
"packages/videopress",
"packages/waf",
"packages/wordads",
"packages/yoast-promo"
]
}
},
"config": {
"allow-plugins": {
"automattic/jetpack-autoloader": true
}
}
}

View File

@ -234,6 +234,7 @@ class Config {
JITMS_JITM::configure();
} else {
// Provides compatibility with jetpack-jitm <v1.6.
// @phan-suppress-next-line PhanUndeclaredClassMethod
JITM::configure();
}

View File

@ -5,6 +5,94 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.8.4] - 2024-05-22
### Deprecated
- Jetpack Connection Manager: Deprecate `request_params` arg in setup_xmlrpc_handlers method. [#37445]
### Fixed
- SSO: Ensure the dist files are generated properly, without overwriting each other. [#37489]
## [2.8.3] - 2024-05-20
### Changed
- Internal updates.
## [2.8.2] - 2024-05-16
### Added
- Connection: Ensuring direct file access is disabled in class-jetpack-ixr-client.php [#37398]
### Changed
- Updated package dependencies. [#37379]
## [2.8.1] - 2024-05-14
### Changed
- SSO: do not rely on the Jetpack class anymore. [#37153]
## [2.8.0] - 2024-05-13
### Added
- SSO: Ensuring tooltips are accessible [#37302]
### Changed
- SSO: Improve user invite error logging [#37144]
## [2.7.7] - 2024-05-09
### Fixed
- SSO: Fix tooltip display on view all users page [#37257]
## [2.7.6] - 2024-05-06
### Added
- Bring in authentication methods needed for SSO feature. [#36924]
### Changed
- SSO: rely on Connection methods instead of relying on methods from the Jetpack plugin. [#36989]
- Updated package dependencies. [#37147]
## [2.7.5] - 2024-04-30
### Changed
- Internal updates.
## [2.7.4] - 2024-04-26
### Changed
- General: use wp_admin_notice function introduced in WP 6.4 to display notices. [#37051]
## [2.7.3] - 2024-04-25
### Changed
- General: Remove code that was added to remain compatible with versions of WordPress lower than 6.4. [#37049]
### Fixed
- Disconnect connection owner on removal. [#36888]
- Improve phpdoc comments in Client class, and remove some unnecessary boolean checks. [#37056]
## [2.7.2] - 2024-04-22
### Added
- SSO: Add SSO feature to the package. [#36587]
### Fixed
- Jetpack Connection: Prevent unnecessary jetpack_connection_active_plugins option updates. [#36896]
## [2.7.1] - 2024-04-08
### Changed
- Updated package dependencies. [#36760]
## [2.7.0] - 2024-03-27
### Added
- Add 'test_connection' endpoint to check for blog token validity. [#36471]
- Add the 'get_heartbeat_data' REST endpoint. [#36553]
### Changed
- Updated package dependencies. [#36585]
## [2.6.2] - 2024-03-25
### Changed
- Internal updates.
## [2.6.1] - 2024-03-22
### Changed
- yUpdate Phan config. [#36353]
## [2.6.0] - 2024-03-20
### Added
- Add the 'remote_connect' REST endpoint. [#36329]
## [2.5.0] - 2024-03-18
### Added
- Add the 'remote_provision' REST endpoint. [#36275]
@ -992,6 +1080,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Separate the connection library into its own package.
[2.8.4]: https://github.com/Automattic/jetpack-connection/compare/v2.8.3...v2.8.4
[2.8.3]: https://github.com/Automattic/jetpack-connection/compare/v2.8.2...v2.8.3
[2.8.2]: https://github.com/Automattic/jetpack-connection/compare/v2.8.1...v2.8.2
[2.8.1]: https://github.com/Automattic/jetpack-connection/compare/v2.8.0...v2.8.1
[2.8.0]: https://github.com/Automattic/jetpack-connection/compare/v2.7.7...v2.8.0
[2.7.7]: https://github.com/Automattic/jetpack-connection/compare/v2.7.6...v2.7.7
[2.7.6]: https://github.com/Automattic/jetpack-connection/compare/v2.7.5...v2.7.6
[2.7.5]: https://github.com/Automattic/jetpack-connection/compare/v2.7.4...v2.7.5
[2.7.4]: https://github.com/Automattic/jetpack-connection/compare/v2.7.3...v2.7.4
[2.7.3]: https://github.com/Automattic/jetpack-connection/compare/v2.7.2...v2.7.3
[2.7.2]: https://github.com/Automattic/jetpack-connection/compare/v2.7.1...v2.7.2
[2.7.1]: https://github.com/Automattic/jetpack-connection/compare/v2.7.0...v2.7.1
[2.7.0]: https://github.com/Automattic/jetpack-connection/compare/v2.6.2...v2.7.0
[2.6.2]: https://github.com/Automattic/jetpack-connection/compare/v2.6.1...v2.6.2
[2.6.1]: https://github.com/Automattic/jetpack-connection/compare/v2.6.0...v2.6.1
[2.6.0]: https://github.com/Automattic/jetpack-connection/compare/v2.5.0...v2.6.0
[2.5.0]: https://github.com/Automattic/jetpack-connection/compare/v2.4.1...v2.5.0
[2.4.1]: https://github.com/Automattic/jetpack-connection/compare/v2.4.0...v2.4.1
[2.4.0]: https://github.com/Automattic/jetpack-connection/compare/v2.3.4...v2.4.0

View File

@ -6,17 +6,18 @@
"require": {
"php": ">=7.0",
"automattic/jetpack-a8c-mc-stats": "^2.0.1",
"automattic/jetpack-admin-ui": "^0.4.1",
"automattic/jetpack-constants": "^2.0.1",
"automattic/jetpack-roles": "^2.0.1",
"automattic/jetpack-status": "^2.1.2",
"automattic/jetpack-redirect": "^2.0.1"
"automattic/jetpack-admin-ui": "^0.4.2",
"automattic/jetpack-assets": "^2.1.11",
"automattic/jetpack-constants": "^2.0.2",
"automattic/jetpack-roles": "^2.0.2",
"automattic/jetpack-status": "^3.2.0",
"automattic/jetpack-redirect": "^2.0.2"
},
"require-dev": {
"automattic/wordbless": "@dev",
"yoast/phpunit-polyfills": "1.1.0",
"brain/monkey": "2.6.1",
"automattic/jetpack-changelogger": "^4.1.2"
"automattic/jetpack-changelogger": "^4.2.4"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
@ -57,7 +58,13 @@
"link-template": "https://github.com/Automattic/jetpack-connection/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "2.5.x-dev"
"dev-trunk": "2.8.x-dev"
},
"dependencies": {
"test-only": [
"packages/licensing",
"packages/sync"
]
}
},
"config": {

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => 'd0b88193b5b4008c3108');

View File

@ -0,0 +1 @@
.jetpack-sso-admin-create-user-invite-message{width:550px}.jetpack-sso-admin-create-user-invite-message-link-sso{text-decoration:none}#createuser .form-field textarea{width:25em}#createuser .form-field [type=checkbox]{width:1rem}#custom_email_message_description{color:#646970;font-size:12px;max-width:25rem}

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("send_user_notification"),d=document.getElementById("user_external_contractor"),t=document.getElementById("invite_user_wpcom"),n=document.getElementById("custom_email_message_block");t&&e&&n&&(t.addEventListener("change",(function(){e.disabled=t.checked,t.checked?(e.checked=!1,d&&(d.disabled=!1),n.style.display="table"):(d&&(d.disabled=!0,d.checked=!1),n.style.display="none")})),t.checked&&(e.disabled=!0,e.checked=!1,n.style.display="table"),t.checked||(d&&(d.disabled=!0),n.style.display="none"))}));

View File

@ -0,0 +1 @@
.jetpack-sso-admin-create-user-invite-message{width:550px}.jetpack-sso-admin-create-user-invite-message-link-sso{text-decoration:none}#createuser .form-field textarea{width:25em}#createuser .form-field [type=checkbox]{width:1rem}#custom_email_message_description{color:#646970;font-size:12px;max-width:25rem}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '049775f3b0a647a127f9');

View File

@ -0,0 +1 @@
#loginform{padding-bottom:92px;position:relative!important}.jetpack-sso-repositioned #loginform{padding-bottom:26px}#loginform #jetpack-sso-wrap,#loginform #jetpack-sso-wrap *{box-sizing:border-box}#jetpack-sso-wrap__action,#jetpack-sso-wrap__user{display:none}.jetpack-sso-form-display #jetpack-sso-wrap__action,.jetpack-sso-form-display #jetpack-sso-wrap__user{display:block}#jetpack-sso-wrap{bottom:20px;margin-left:-24px;margin-right:-24px;padding:0 24px;position:absolute;width:100%}.jetpack-sso-repositioned #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:16px;padding:0;position:relative}.jetpack-sso-form-display #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:0;padding:0;position:relative}#loginform #jetpack-sso-wrap p{color:#777;margin-bottom:16px}#jetpack-sso-wrap a{display:block;text-align:center;text-decoration:none;width:100%}#jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:none}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:block}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.default,.jetpack-sso-form-display #loginform>div,.jetpack-sso-form-display #loginform>p{display:none}.jetpack-sso-form-display #loginform #jetpack-sso-wrap{display:block}.jetpack-sso-form-display #loginform{padding:26px 24px}.jetpack-sso-or{margin-bottom:16px;position:relative;text-align:center}.jetpack-sso-or:before{background:#dcdcde;content:"";height:1px;left:0;position:absolute;top:50%;width:100%}.jetpack-sso-or span{background:#fff;color:#777;padding:0 8px;position:relative;text-transform:uppercase}#jetpack-sso-wrap .button{align-items:center;display:flex;height:36px;justify-content:center;margin-bottom:16px;width:100%}#jetpack-sso-wrap .button .genericon-wordpress{font-size:24px;margin-right:4px}#jetpack-sso-wrap__user img{border-radius:50%;display:block;margin:0 auto 16px}#jetpack-sso-wrap__user h2{font-size:21px;font-weight:300;margin-bottom:16px;text-align:center}#jetpack-sso-wrap__user h2 span{font-weight:700}.jetpack-sso-wrap__reauth{margin-bottom:16px}.jetpack-sso-form-display #nav{display:none}.jetpack-sso-form-display #backtoblog{margin:24px 0 0}.jetpack-sso-clear:after{clear:both;content:"";display:table}

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",(()=>{const e=document.querySelector("body"),t=document.querySelector(".jetpack-sso-toggle"),d=document.getElementById("user_login"),o=document.getElementById("user_pass"),s=document.getElementById("jetpack-sso-wrap"),n=document.getElementById("loginform"),c=document.createElement("div");c.className="jetpack-sso-clear",n.appendChild(c),c.appendChild(document.querySelector("p.forgetmenot")),c.appendChild(document.querySelector("p.submit")),n.appendChild(s),e.classList.add("jetpack-sso-repositioned"),t.addEventListener("click",(t=>{t.preventDefault(),e.classList.toggle("jetpack-sso-form-display"),e.classList.contains("jetpack-sso-form-display")||(d.focus(),o.disabled=!1)}))}));

View File

@ -0,0 +1 @@
#loginform{padding-bottom:92px;position:relative!important}.jetpack-sso-repositioned #loginform{padding-bottom:26px}#loginform #jetpack-sso-wrap,#loginform #jetpack-sso-wrap *{box-sizing:border-box}#jetpack-sso-wrap__action,#jetpack-sso-wrap__user{display:none}.jetpack-sso-form-display #jetpack-sso-wrap__action,.jetpack-sso-form-display #jetpack-sso-wrap__user{display:block}#jetpack-sso-wrap{bottom:20px;margin-left:-24px;margin-right:-24px;padding:0 24px;position:absolute;width:100%}.jetpack-sso-repositioned #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:16px;padding:0;position:relative}.jetpack-sso-form-display #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:0;padding:0;position:relative}#loginform #jetpack-sso-wrap p{color:#777;margin-bottom:16px}#jetpack-sso-wrap a{display:block;text-align:center;text-decoration:none;width:100%}#jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:none}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:block}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.default,.jetpack-sso-form-display #loginform>div,.jetpack-sso-form-display #loginform>p{display:none}.jetpack-sso-form-display #loginform #jetpack-sso-wrap{display:block}.jetpack-sso-form-display #loginform{padding:26px 24px}.jetpack-sso-or{margin-bottom:16px;position:relative;text-align:center}.jetpack-sso-or:before{background:#dcdcde;content:"";height:1px;position:absolute;right:0;top:50%;width:100%}.jetpack-sso-or span{background:#fff;color:#777;padding:0 8px;position:relative;text-transform:uppercase}#jetpack-sso-wrap .button{align-items:center;display:flex;height:36px;justify-content:center;margin-bottom:16px;width:100%}#jetpack-sso-wrap .button .genericon-wordpress{font-size:24px;margin-left:4px}#jetpack-sso-wrap__user img{border-radius:50%;display:block;margin:0 auto 16px}#jetpack-sso-wrap__user h2{font-size:21px;font-weight:300;margin-bottom:16px;text-align:center}#jetpack-sso-wrap__user h2 span{font-weight:700}.jetpack-sso-wrap__reauth{margin-bottom:16px}.jetpack-sso-form-display #nav{display:none}.jetpack-sso-form-display #backtoblog{margin:24px 0 0}.jetpack-sso-clear:after{clear:both;content:"";display:table}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '04d208524c748ec232f3');

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",(function(){function t(){this.querySelector(".jetpack-sso-invitation-tooltip").style.display="block"}function e(t){document.activeElement!==t.target&&(this.querySelector(".jetpack-sso-invitation-tooltip").style.display="none")}document.querySelectorAll(".jetpack-sso-invitation-tooltip-icon:not(.sso-disconnected-user)").forEach((function(t){t.innerHTML+=" [?]";const e=document.createElement("span");e.classList.add("jetpack-sso-invitation-tooltip","jetpack-sso-th-tooltip");const n=window.Jetpack_SSOTooltip.tooltipString;function o(){t.appendChild(e),e.style.display="block"}function i(){document.activeElement!==t&&t.removeChild(e)}e.innerHTML+=n,t.addEventListener("mouseenter",o),t.addEventListener("focus",o),t.addEventListener("mouseleave",i),t.addEventListener("blur",i)})),document.querySelectorAll(".jetpack-sso-invitation-tooltip-icon:not(.jetpack-sso-status-column)").forEach((function(n){n.addEventListener("mouseenter",t),n.addEventListener("focus",t),n.addEventListener("mouseleave",e),n.addEventListener("blur",e)}))}));

View File

@ -12,6 +12,13 @@
use Automattic\Jetpack\Connection\Client;
use Automattic\Jetpack\Connection\Manager;
/**
* Disable direct access.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( IXR_Client::class ) ) {
require_once ABSPATH . WPINC . '/class-IXR.php';
}
@ -146,10 +153,10 @@ class Jetpack_IXR_Client extends IXR_Client {
$code = $match[1];
$message = $match[2];
$status = $fault_code;
return new \WP_Error( $code, $message, $status );
return new WP_Error( $code, $message, $status );
}
return new \WP_Error( "IXR_{$fault_code}", $fault_string );
return new WP_Error( "IXR_{$fault_code}", $fault_string );
}
/**

View File

@ -93,9 +93,9 @@ class Jetpack_Signature {
// Convert the $_POST to the body, if the body was empty. This is how arrays are hashed
// and encoded on the Jetpack side.
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Used to generate a cryptographic signature of the post data. Not actually using any of it here.
if ( empty( $body ) && is_array( $_POST ) && $_POST !== array() ) {
$body = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$body = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- We need all of $_POST in order to generate a cryptographic signature of the post data.
}
}
} elseif ( isset( $_SERVER['REQUEST_METHOD'] ) && 'PUT' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is validating.

View File

@ -440,8 +440,8 @@ class Jetpack_XMLRPC_Server {
* Given an array containing a local user identifier and a nonce, will attempt to fetch and set
* an access token for the given user.
*
* @param array $request An array containing local_user and nonce keys at minimum.
* @param \IXR_Client $ixr_client The client object, optional.
* @param array|ArrayAccess $request An array containing local_user and nonce keys at minimum.
* @param \IXR_Client $ixr_client The client object, optional.
* @return mixed
*/
public function remote_connect( $request, $ixr_client = false ) {

View File

@ -0,0 +1,281 @@
<?php
/**
* Authorize_Json_Api handler class.
* Used to handle connections via JSON API.
* Ported from the Jetpack class.
*
* @since 2.7.6 Ported from the Jetpack class.
*
* @package automattic/jetpack-connection
*/
namespace Automattic\Jetpack\Connection;
use Automattic\Jetpack\Redirect;
use Automattic\Jetpack\Status\Host;
use Jetpack_Options;
/**
* Authorize_Json_Api handler class.
*/
class Authorize_Json_Api {
/**
* Verified data for JSON authorization request
*
* @since 2.7.6
*
* @var array
*/
public $json_api_authorization_request = array();
/**
* Verifies the request by checking the signature
*
* @since jetpack-4.6.0 Method was updated to use `$_REQUEST` instead of `$_GET` and `$_POST`. Method also updated to allow
* passing in an `$environment` argument that overrides `$_REQUEST`. This was useful for integrating with SSO.
* @since 2.7.6 Ported from Jetpack to the Connection package.
*
* @param null|array $environment Value to override $_REQUEST.
*
* @return void
*/
public function verify_json_api_authorization_request( $environment = null ) {
$environment = $environment === null
? $_REQUEST // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verification handled later in function and request data are 1) used to verify a cryptographic signature of the request data and 2) sanitized later in function.
: $environment;
if ( ! isset( $environment['token'] ) ) {
wp_die( esc_html__( 'You must connect your Jetpack plugin to WordPress.com to use this feature.', 'jetpack-connection' ) );
}
list( $env_token,, $env_user_id ) = explode( ':', $environment['token'] );
$token = ( new Tokens() )->get_access_token( (int) $env_user_id, $env_token );
if ( ! $token || empty( $token->secret ) ) {
wp_die( esc_html__( 'You must connect your Jetpack plugin to WordPress.com to use this feature.', 'jetpack-connection' ) );
}
$die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack-connection' );
// Host has encoded the request URL, probably as a result of a bad http => https redirect.
if (
preg_match( '/https?%3A%2F%2F/i', esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) ) > 0 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no site changes, we're erroring out.
) {
/**
* Jetpack authorisation request Error.
*
* @since jetpack-7.5.0
*/
do_action( 'jetpack_verify_api_authorization_request_error_double_encode' );
$die_error = sprintf(
/* translators: %s is a URL */
__( 'Your site is incorrectly double-encoding redirects from http to https. This is preventing Jetpack from authenticating your connection. Please visit our <a href="%s">support page</a> for details about how to resolve this.', 'jetpack-connection' ),
esc_url( Redirect::get_url( 'jetpack-support-double-encoding' ) )
);
}
$jetpack_signature = new \Jetpack_Signature( $token->secret, (int) Jetpack_Options::get_option( 'time_diff' ) );
if ( isset( $environment['jetpack_json_api_original_query'] ) ) {
$signature = $jetpack_signature->sign_request(
$environment['token'],
$environment['timestamp'],
$environment['nonce'],
'',
'GET',
$environment['jetpack_json_api_original_query'],
null,
true
);
} else {
$signature = $jetpack_signature->sign_current_request(
array(
'body' => null,
'method' => 'GET',
)
);
}
if ( ! $signature ) {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
} elseif ( is_wp_error( $signature ) ) {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
} elseif ( ! hash_equals( $signature, $environment['signature'] ) ) {
if ( is_ssl() ) {
// If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well.
$signature = $jetpack_signature->sign_current_request(
array(
'scheme' => 'http',
'body' => null,
'method' => 'GET',
)
);
if ( ! $signature || is_wp_error( $signature ) || ! hash_equals( $signature, $environment['signature'] ) ) {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
}
} else {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
}
}
$timestamp = (int) $environment['timestamp'];
$nonce = stripslashes( (string) $environment['nonce'] );
if ( ! ( new Nonce_Handler() )->add( $timestamp, $nonce ) ) {
// De-nonce the nonce, at least for 5 minutes.
// We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed).
$old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" );
if ( $old_nonce_time < time() - 300 ) {
wp_die( esc_html__( 'The authorization process expired. Please go back and try again.', 'jetpack-connection' ) );
}
}
$data = json_decode(
base64_decode( stripslashes( $environment['data'] ) ) // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
);
$data_filters = array(
'state' => 'opaque',
'client_id' => 'int',
'client_title' => 'string',
'client_image' => 'url',
);
foreach ( $data_filters as $key => $sanitation ) {
if ( ! isset( $data->$key ) ) {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
}
switch ( $sanitation ) {
case 'int':
$this->json_api_authorization_request[ $key ] = (int) $data->$key;
break;
case 'opaque':
$this->json_api_authorization_request[ $key ] = (string) $data->$key;
break;
case 'string':
$this->json_api_authorization_request[ $key ] = wp_kses( (string) $data->$key, array() );
break;
case 'url':
$this->json_api_authorization_request[ $key ] = esc_url_raw( (string) $data->$key );
break;
}
}
if ( empty( $this->json_api_authorization_request['client_id'] ) ) {
wp_die(
wp_kses(
$die_error,
array(
'a' => array(
'href' => array(),
),
)
)
);
}
}
/**
* Add the Access Code details to the public-api.wordpress.com redirect.
*
* @since 2.7.6 Ported from Jetpack to the Connection package.
*
* @param string $redirect_to URL.
* @param string $original_redirect_to URL.
* @param \WP_User $user WP_User for the redirect.
*
* @return string
*/
public function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return add_query_arg(
urlencode_deep(
array(
'jetpack-code' => get_user_meta(
$user->ID,
'jetpack_json_api_' . $this->json_api_authorization_request['client_id'],
true
),
'jetpack-user-id' => (int) $user->ID,
'jetpack-state' => $this->json_api_authorization_request['state'],
)
),
$redirect_to
);
}
/**
* If someone logs in to approve API access, store the Access Code in usermeta.
*
* @since 2.7.6 Ported from Jetpack to the Connection package.
*
* @param string $user_login Unused.
* @param \WP_User $user User logged in.
*
* @return void
*/
public function store_json_api_authorization_token( $user_login, $user ) {
add_filter( 'login_redirect', array( $this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 );
add_filter( 'allowed_redirect_hosts', array( Host::class, 'allow_wpcom_public_api_domain' ) );
$token = wp_generate_password( 32, false );
update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token );
}
/**
* HTML for the JSON API authorization notice.
*
* @since 2.7.6 Ported from Jetpack to the Connection package.
*
* @return string
*/
public function login_message_json_api_authorization() {
return '<p class="message">' . sprintf(
/* translators: Name/image of the client requesting authorization */
esc_html__( '%s wants to access your sites data. Log in to authorize that access.', 'jetpack-connection' ),
'<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>'
) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>';
}
}

View File

@ -8,6 +8,10 @@
namespace Automattic\Jetpack\Connection;
use Automattic\Jetpack\Constants;
use WP_Error;
// `wp_remote_request` returns an array with a particular format.
'@phan-type _WP_Remote_Response_Array = array{headers:\WpOrg\Requests\Utility\CaseInsensitiveDictionary,body:string,response:array{code:int,message:string},cookies:\WP_HTTP_Cookie[],filename:?string,http_response:WP_HTTP_Requests_Response}';
/**
* The Client class that is used to connect to WordPress.com Jetpack API.
@ -18,9 +22,10 @@ class Client {
/**
* Makes an authorized remote request using Jetpack_Signature
*
* @param array $args the arguments for the remote request.
* @param array|String $body the request body.
* @param array $args the arguments for the remote request.
* @param array|string|null $body the request body.
* @return array|WP_Error WP HTTP response on success
* @phan-return _WP_Remote_Response_Array|WP_Error
*/
public static function remote_request( $args, $body = null ) {
if ( isset( $args['url'] ) ) {
@ -35,7 +40,7 @@ class Client {
}
$result = self::build_signed_request( $args, $body );
if ( ! $result || is_wp_error( $result ) ) {
if ( is_wp_error( $result ) ) {
return $result;
}
@ -64,12 +69,12 @@ class Client {
/**
* Adds authorization signature to a remote request using Jetpack_Signature
*
* @param array $args the arguments for the remote request.
* @param array|String $body the request body.
* @return WP_Error|array {
* @param array $args the arguments for the remote request.
* @param array|string|null $body the request body.
* @return WP_Error|array{url:string,request:array,auth:array} {
* An array containing URL and request items.
*
* @type String $url The request URL.
* @type string $url The request URL.
* @type array $request Request arguments.
* @type array $auth Authorization data.
* }
@ -107,7 +112,7 @@ class Client {
$token = ( new Tokens() )->get_access_token( $args['user_id'] );
if ( ! $token ) {
return new \WP_Error( 'missing_token' );
return new WP_Error( 'missing_token' );
}
$method = strtoupper( $args['method'] );
@ -122,8 +127,8 @@ class Client {
$request = compact( 'method', 'body', 'timeout', 'redirection', 'stream', 'filename', 'sslverify' );
@list( $token_key, $secret ) = explode( '.', $token->secret ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( empty( $token ) || empty( $secret ) ) {
return new \WP_Error( 'malformed_token' );
if ( ! $secret ) {
return new WP_Error( 'malformed_token' );
}
$token_key = sprintf(
@ -141,7 +146,7 @@ class Client {
if ( function_exists( 'wp_generate_password' ) ) {
$nonce = wp_generate_password( 10, false );
} else {
$nonce = substr( sha1( wp_rand( 0, 1000000 ) ), 0, 10 );
$nonce = substr( sha1( (string) wp_rand( 0, 1000000 ) ), 0, 10 );
}
// Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing.
@ -166,7 +171,7 @@ class Client {
}
if ( ! is_string( $body_to_hash ) ) {
return new \WP_Error( 'invalid_body', 'Body is malformed.' );
return new WP_Error( 'invalid_body', 'Body is malformed.' );
}
$body_hash = base64_encode( sha1( $body_to_hash, true ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
}
@ -195,7 +200,7 @@ class Client {
$signature = $jetpack_signature->sign_request( $token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false );
if ( ! $signature || is_wp_error( $signature ) ) {
if ( is_wp_error( $signature ) ) {
return $signature;
}
@ -232,10 +237,11 @@ class Client {
*
* @internal
*
* @param String $url the request URL.
* @param string $url the request URL.
* @param array $args request arguments.
* @param Boolean $set_fallback whether to allow flagging this request to use a fallback certficate override.
* @param boolean $set_fallback whether to allow flagging this request to use a fallback certficate override.
* @return array|WP_Error WP HTTP response on success
* @phan-return _WP_Remote_Response_Array|WP_Error
*/
public static function _wp_remote_request( $url, $args, $set_fallback = false ) { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
$fallback = \Jetpack_Options::get_option( 'fallback_no_verify_ssl_certs' );
@ -315,8 +321,9 @@ class Client {
/**
* Sets the time difference for correct signature computation.
*
* @param HTTP_Response $response the response object.
* @param Boolean $force_set whether to force setting the time difference.
* @param array|WP_Error $response Response array from `wp_remote_request`, or WP_Error on error.
* @param bool $force_set whether to force setting the time difference.
* @phan-param _WP_Remote_Response_Array|WP_Error $response
*/
public static function set_time_diff( &$response, $force_set = false ) {
$code = wp_remote_retrieve_response_code( $response );
@ -356,7 +363,7 @@ class Client {
* @param array $args Arguments to {@see WP_Http}. Default is `array()`.
* @param string $base_api_path REST API root. Default is `wpcom`.
*
* @return array|WP_Error $response Response data, else {@see WP_Error} on failure.
* @return array Validated arguments.
*/
public static function validate_args_for_wpcom_json_api_request(
$path,
@ -407,13 +414,14 @@ class Client {
/**
* Queries the WordPress.com REST API with a user token.
*
* @param string $path REST API path.
* @param string $version REST API version. Default is `2`.
* @param array $args Arguments to {@see WP_Http}. Default is `array()`.
* @param string $body Body passed to {@see WP_Http}. Default is `null`.
* @param string $base_api_path REST API root. Default is `wpcom`.
* @param string $path REST API path.
* @param string $version REST API version. Default is `2`.
* @param array $args Arguments to {@see WP_Http}. Default is `array()`.
* @param null|string|array $body Body passed to {@see WP_Http}. Default is `null`.
* @param string $base_api_path REST API root. Default is `wpcom`.
*
* @return array|WP_Error $response Response data, else {@see WP_Error} on failure.
* @phan-return _WP_Remote_Response_Array|WP_Error
*/
public static function wpcom_json_api_request_as_user(
$path,
@ -439,12 +447,13 @@ class Client {
/**
* Query the WordPress.com REST API using the blog token
*
* @param String $path The API endpoint relative path.
* @param String $version The API version.
* @param array $args Request arguments.
* @param String $body Request body.
* @param String $base_api_path (optional) the API base path override, defaults to 'rest'.
* @param string $path The API endpoint relative path.
* @param string $version The API version.
* @param array $args Request arguments.
* @param array|string|null $body Request body.
* @param string $base_api_path (optional) the API base path override, defaults to 'rest'.
* @return array|WP_Error $response Data.
* @phan-return _WP_Remote_Response_Array|WP_Error
*/
public static function wpcom_json_api_request_as_blog(
$path,
@ -471,7 +480,7 @@ class Client {
* make sure that body hashes are made ith the string version, which is what will be seen after a
* server pulls up the data in the $_POST array.
*
* @param array|Mixed $data the data that needs to be stringified.
* @param mixed $data the data that needs to be stringified.
*
* @return array|string
*/

View File

@ -702,11 +702,15 @@ class Error_Handler {
return;
}
?>
<div class="notice notice-error is-dismissible jetpack-message jp-connect" style="display:block !important;">
<p><?php echo esc_html( $message ); ?></p>
</div>
<?php
wp_admin_notice(
esc_html( $message ),
array(
'type' => 'error',
'dismissible' => true,
'additional_classes' => array( 'jetpack-message', 'jp-connect' ),
'attributes' => array( 'style' => 'display:block !important;' ),
)
);
}
/**

View File

@ -7,8 +7,13 @@
namespace Automattic\Jetpack;
use Automattic\Jetpack\Connection\Rest_Authentication;
use Automattic\Jetpack\Connection\REST_Connector;
use Jetpack_Options;
use WP_CLI;
use WP_Error;
use WP_REST_Request;
use WP_REST_Server;
/**
* Heartbeat sends a batch of stats to wp.com once a day
@ -73,6 +78,8 @@ class Heartbeat {
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'jetpack-heartbeat', array( $this, 'cli_callback' ) );
}
add_action( 'rest_api_init', array( $this, 'initialize_rest_api' ) );
}
/**
@ -249,4 +256,55 @@ class Heartbeat {
WP_CLI::line( sprintf( __( 'Last heartbeat sent at: %s', 'jetpack-connection' ), $last_date ) );
}
}
/**
* Initialize the heartbeat REST API.
*
* @return void
*/
public function initialize_rest_api() {
register_rest_route(
'jetpack/v4',
'/heartbeat/data',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'rest_heartbeat_data' ),
'permission_callback' => array( $this, 'rest_heartbeat_data_permission_check' ),
'args' => array(
'prefix' => array(
'description' => __( 'Prefix to add before the stats identifiers.', 'jetpack-connection' ),
'type' => 'string',
),
),
)
);
}
/**
* Endpoint to retrieve the heartbeat data.
*
* @param WP_REST_Request $request The request data.
*
* @since 2.7.0
*
* @return array
*/
public function rest_heartbeat_data( WP_REST_Request $request ) {
return static::generate_stats_array( $request->get_param( 'prefix' ) );
}
/**
* Check permissions for the `get_heartbeat_data` endpoint.
*
* @return true|WP_Error
*/
public function rest_heartbeat_data_permission_check() {
if ( current_user_can( 'jetpack_connect' ) ) {
return true;
}
return Rest_Authentication::is_signed_with_blog_token()
? true
: new WP_Error( 'invalid_permission_heartbeat_data', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
}

View File

@ -16,8 +16,10 @@ use Automattic\Jetpack\Status;
use Automattic\Jetpack\Status\Host;
use Automattic\Jetpack\Terms_Of_Service;
use Automattic\Jetpack\Tracking;
use IXR_Error;
use Jetpack_IXR_Client;
use Jetpack_Options;
use Jetpack_XMLRPC_Server;
use WP_Error;
use WP_User;
@ -71,6 +73,13 @@ class Manager {
*/
private static $extra_register_params = array();
/**
* We store ID's of users already disconnected to prevent multiple disconnect requests.
*
* @var array
*/
private static $disconnected_users = array();
/**
* Initialize the object.
* Make sure to call the "Configure" first.
@ -102,7 +111,7 @@ class Manager {
);
$manager->setup_xmlrpc_handlers(
$_GET, // phpcs:ignore WordPress.Security.NonceVerification.Recommended
null,
$manager->has_connected_owner(),
$manager->verify_xml_rpc_signature()
);
@ -127,6 +136,10 @@ class Manager {
Webhooks::init( $manager );
// Unlink user before deleting the user from WP.com.
add_action( 'deleted_user', array( $manager, 'disconnect_user_force' ), 9, 1 );
add_action( 'remove_user_from_blog', array( $manager, 'disconnect_user_force' ), 9, 1 );
// Set up package version hook.
add_filter( 'jetpack_package_versions', __NAMESPACE__ . '\Package_Version::send_package_version_to_tracker' );
@ -148,32 +161,31 @@ class Manager {
* Sets up the XMLRPC request handlers.
*
* @since 1.25.0 Deprecate $is_active param.
* @since 2.8.4 Deprecate $request_params param.
*
* @param array $request_params incoming request parameters.
* @param bool $has_connected_owner Whether the site has a connected owner.
* @param bool $is_signed whether the signature check has been successful.
* @param \Jetpack_XMLRPC_Server $xmlrpc_server (optional) an instance of the server to use instead of instantiating a new one.
* @param array|null $deprecated Deprecated. Not used.
* @param bool $has_connected_owner Whether the site has a connected owner.
* @param bool $is_signed whether the signature check has been successful.
* @param Jetpack_XMLRPC_Server $xmlrpc_server (optional) an instance of the server to use instead of instantiating a new one.
*/
public function setup_xmlrpc_handlers(
$request_params,
$deprecated,
$has_connected_owner,
$is_signed,
\Jetpack_XMLRPC_Server $xmlrpc_server = null
Jetpack_XMLRPC_Server $xmlrpc_server = null
) {
add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ), 1000, 2 );
if (
! isset( $request_params['for'] )
|| 'jetpack' !== $request_params['for']
) {
if ( $deprecated !== null ) {
_deprecated_argument( __METHOD__, '2.8.4' );
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We are using the 'for' request param to early return unless it's 'jetpack'.
if ( ! isset( $_GET['for'] ) || 'jetpack' !== $_GET['for'] ) {
return false;
}
// Alternate XML-RPC, via ?for=jetpack&jetpack=comms.
if (
isset( $request_params['jetpack'] )
&& 'comms' === $request_params['jetpack']
) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This just determines whether to handle the request as an XML-RPC request. The actual XML-RPC endpoints do the appropriate nonce checking where applicable. Plus we make sure to clear all cookies via require_jetpack_authentication called later in method.
if ( isset( $_GET['jetpack'] ) && 'comms' === $_GET['jetpack'] ) {
if ( ! Constants::is_defined( 'XMLRPC_REQUEST' ) ) {
// Use the real constant here for WordPress' sake.
define( 'XMLRPC_REQUEST', true );
@ -193,7 +205,7 @@ class Manager {
if ( $xmlrpc_server ) {
$this->xmlrpc_server = $xmlrpc_server;
} else {
$this->xmlrpc_server = new \Jetpack_XMLRPC_Server();
$this->xmlrpc_server = new Jetpack_XMLRPC_Server();
}
$this->require_jetpack_authentication();
@ -442,9 +454,9 @@ class Manager {
}
$jetpack_signature = new \Jetpack_Signature( $token->secret, (int) \Jetpack_Options::get_option( 'time_diff' ) );
// phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Used to verify a cryptographic signature of the post data. Also a nonce is verified later in the function.
if ( isset( $_POST['_jetpack_is_multipart'] ) ) {
$post_data = $_POST;
$post_data = $_POST; // We need all of $_POST in order to verify a cryptographic signature of the post data.
$file_hashes = array();
foreach ( $post_data as $post_data_key => $post_data_value ) {
if ( ! str_starts_with( $post_data_key, '_jetpack_file_hmac_' ) ) {
@ -863,6 +875,22 @@ class Manager {
exit();
}
/**
* Force user disconnect.
*
* @param int $user_id Local (external) user ID.
*
* @return bool
*/
public function disconnect_user_force( $user_id ) {
if ( ! (int) $user_id ) {
// Missing user ID.
return false;
}
return $this->disconnect_user( $user_id, true, true );
}
/**
* Unlinks the current user from the linked WordPress.com user.
*
@ -884,6 +912,11 @@ class Manager {
return false;
}
if ( in_array( $user_id, self::$disconnected_users, true ) ) {
// The user is already disconnected.
return false;
}
// Attempt to disconnect the user from WordPress.com.
$is_disconnected_from_wpcom = $this->unlink_user_from_wpcom( $user_id );
@ -913,6 +946,8 @@ class Manager {
}
}
self::$disconnected_users[] = $user_id;
return $is_disconnected_from_wpcom && $is_disconnected_locally;
}
@ -1842,11 +1877,16 @@ class Manager {
/**
* Builds a URL to the Jetpack connection auth page.
*
* @param WP_User $user (optional) defaults to the current logged in user.
* @param String $redirect (optional) a redirect URL to use instead of the default.
* @since 2.7.6 Added optional $from and $raw parameters.
*
* @param WP_User $user (optional) defaults to the current logged in user.
* @param string $redirect (optional) a redirect URL to use instead of the default.
* @param bool|string $from If not false, adds 'from=$from' param to the connect URL.
* @param bool $raw If true, URL will not be escaped.
*
* @return string Connect URL.
*/
public function get_authorization_url( $user = null, $redirect = null ) {
public function get_authorization_url( $user = null, $redirect = null, $from = false, $raw = false ) {
if ( empty( $user ) ) {
$user = wp_get_current_user();
}
@ -1939,8 +1979,28 @@ class Manager {
$url = add_query_arg( $body, $api_url );
/** This filter is documented in plugins/jetpack/class-jetpack.php */
return apply_filters( 'jetpack_build_authorize_url', $url );
if ( is_network_admin() ) {
$url = add_query_arg( 'is_multisite', network_admin_url( 'admin.php?page=jetpack-settings' ), $url );
}
if ( $from ) {
$url = add_query_arg( 'from', $from, $url );
}
if ( $raw ) {
$url = esc_url_raw( $url );
}
/**
* Filter the URL used when connecting a user to a WordPress.com account.
*
* @since 2.0.0
* @since 2.7.6 Added $raw parameter.
*
* @param string $url Connection URL.
* @param bool $raw If true, URL will not be escaped.
*/
return apply_filters( 'jetpack_build_authorize_url', $url, $raw );
}
/**
@ -2287,7 +2347,7 @@ class Manager {
* Handles a getOptions XMLRPC method call.
*
* @param array $args method call arguments.
* @return an amended XMLRPC server options array.
* @return array|IXR_Error An amended XMLRPC server options array.
*/
public function jetpack_get_options( $args ) {
global $wp_xmlrpc_server;

View File

@ -12,7 +12,7 @@ namespace Automattic\Jetpack\Connection;
*/
class Package_Version {
const PACKAGE_VERSION = '2.5.0';
const PACKAGE_VERSION = '2.8.4';
const PACKAGE_SLUG = 'connection';

View File

@ -24,6 +24,11 @@ class Plugin_Storage {
*/
const PLUGINS_DISABLED_OPTION_NAME = 'jetpack_connection_disabled_plugins';
/**
* Transient name used as flag to indicate that the active connected plugins list needs refreshing.
*/
const ACTIVE_PLUGINS_REFRESH_FLAG = 'jetpack_connection_active_plugins_refresh';
/**
* Whether this class was configured for the first time or not.
*
@ -31,13 +36,6 @@ class Plugin_Storage {
*/
private static $configured = false;
/**
* Refresh list of connected plugins upon intialization.
*
* @var boolean
*/
private static $refresh_connected_plugins = false;
/**
* Connected plugins.
*
@ -65,11 +63,6 @@ class Plugin_Storage {
public static function upsert( $slug, array $args = array() ) {
self::$plugins[ $slug ] = $args;
// if plugin is not in the list of active plugins, refresh the list.
if ( ! array_key_exists( $slug, (array) get_option( self::ACTIVE_PLUGINS_OPTION_NAME, array() ) ) ) {
self::$refresh_connected_plugins = true;
}
return true;
}
@ -167,6 +160,44 @@ class Plugin_Storage {
return;
}
self::$configured = true;
add_action( 'update_option_active_plugins', array( __CLASS__, 'set_flag_to_refresh_active_connected_plugins' ) );
self::maybe_update_active_connected_plugins();
}
/**
* Set a flag to indicate that the active connected plugins list needs to be updated.
* This will happen when the `active_plugins` option is updated.
*
* @see configure
*/
public static function set_flag_to_refresh_active_connected_plugins() {
set_transient( self::ACTIVE_PLUGINS_REFRESH_FLAG, time() );
}
/**
* Determine if we need to update the active connected plugins list.
*/
public static function maybe_update_active_connected_plugins() {
$maybe_error = self::ensure_configured();
if ( $maybe_error instanceof WP_Error ) {
return;
}
// Only attempt to update the option if the corresponding flag is set.
if ( ! get_transient( self::ACTIVE_PLUGINS_REFRESH_FLAG ) ) {
return;
}
// Only attempt to update the option on POST requests.
// This will prevent the option from being updated multiple times due to concurrent requests.
if ( ! ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) ) {
return;
}
delete_transient( self::ACTIVE_PLUGINS_REFRESH_FLAG );
if ( is_multisite() ) {
self::$current_blog_id = get_current_blog_id();
}
@ -175,11 +206,9 @@ class Plugin_Storage {
// self::$plugins is populated in Config::ensure_options_connection().
$number_of_plugins_differ = count( self::$plugins ) !== count( (array) get_option( self::ACTIVE_PLUGINS_OPTION_NAME, array() ) );
if ( $number_of_plugins_differ || true === self::$refresh_connected_plugins ) {
if ( $number_of_plugins_differ ) {
self::update_active_plugins_option();
}
self::$configured = true;
}
/**
@ -188,7 +217,7 @@ class Plugin_Storage {
* @return void
*/
public static function update_active_plugins_option() {
// Note: Since this options is synced to wpcom, if you change its structure, you have to update the sanitizer at wpcom side.
// Note: Since this option is synced to wpcom, if you change its structure, you have to update the sanitizer at wpcom side.
update_option( self::ACTIVE_PLUGINS_OPTION_NAME, self::$plugins );
if ( ! class_exists( 'Automattic\Jetpack\Sync\Settings' ) || ! \Automattic\Jetpack\Sync\Settings::is_sync_enabled() ) {

View File

@ -7,6 +7,8 @@
namespace Automattic\Jetpack\Connection;
use WP_Error;
/**
* The Jetpack Connection Rest Authentication class.
*/
@ -118,7 +120,7 @@ class Rest_Authentication {
}
if ( ! isset( $_SERVER['REQUEST_METHOD'] ) ) {
$this->rest_authentication_status = new \WP_Error(
$this->rest_authentication_status = new WP_Error(
'rest_invalid_request',
__( 'The request method is missing.', 'jetpack-connection' ),
array( 'status' => 400 )
@ -131,7 +133,7 @@ class Rest_Authentication {
// can be passed to the WP REST API via the '?_method=' parameter if
// needed.
if ( 'GET' !== $_SERVER['REQUEST_METHOD'] && 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
$this->rest_authentication_status = new \WP_Error(
$this->rest_authentication_status = new WP_Error(
'rest_invalid_request',
__( 'This request method is not supported.', 'jetpack-connection' ),
array( 'status' => 400 )
@ -139,7 +141,7 @@ class Rest_Authentication {
return null;
}
if ( 'POST' !== $_SERVER['REQUEST_METHOD'] && ! empty( file_get_contents( 'php://input' ) ) ) {
$this->rest_authentication_status = new \WP_Error(
$this->rest_authentication_status = new WP_Error(
'rest_invalid_request',
__( 'This request method does not support body parameters.', 'jetpack-connection' ),
array( 'status' => 400 )
@ -173,7 +175,7 @@ class Rest_Authentication {
}
// Something else went wrong. Probably a signature error.
$this->rest_authentication_status = new \WP_Error(
$this->rest_authentication_status = new WP_Error(
'rest_invalid_signature',
__( 'The request is not signed correctly.', 'jetpack-connection' ),
array( 'status' => 400 )

View File

@ -7,6 +7,7 @@
namespace Automattic\Jetpack\Connection;
use Automattic\Jetpack\Connection\Webhooks\Authorize_Redirect;
use Automattic\Jetpack\Constants;
use Automattic\Jetpack\Redirect;
use Automattic\Jetpack\Status;
@ -105,6 +106,28 @@ class REST_Connector {
)
);
// Connect a remote user.
register_rest_route(
'jetpack/v4',
'/remote_connect',
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array( $this, 'remote_connect' ),
'permission_callback' => array( $this, 'remote_connect_permission_check' ),
)
);
// The endpoint verifies blog connection and blog token validity.
register_rest_route(
'jetpack/v4',
'/connection/check',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'connection_check' ),
'permission_callback' => array( $this, 'connection_check_permission_check' ),
)
);
// Get current connection status of Jetpack.
register_rest_route(
'jetpack/v4',
@ -295,7 +318,7 @@ class REST_Connector {
*
* @param WP_REST_Request $request The request sent to the WP REST API.
*
* @return array|wp-error
* @return array|WP_Error
*/
public static function remote_authorize( $request ) {
$xmlrpc_server = new Jetpack_XMLRPC_Server();
@ -328,6 +351,26 @@ class REST_Connector {
return $result;
}
/**
* Connect a remote user.
*
* @since 2.6.0
*
* @param WP_REST_Request $request The request sent to the WP REST API.
*
* @return WP_Error|array
*/
public static function remote_connect( WP_REST_Request $request ) {
$xmlrpc_server = new Jetpack_XMLRPC_Server();
$result = $xmlrpc_server->remote_connect( $request );
if ( is_a( $result, 'IXR_Error' ) ) {
$result = new WP_Error( $result->code, $result->message );
}
return $result;
}
/**
* Register the site so that a plan can be provisioned.
*
@ -359,6 +402,17 @@ class REST_Connector {
: new WP_Error( 'invalid_permission_remote_provision', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
/**
* Remote connect endpoint permission check.
*
* @return true|WP_Error
*/
public function remote_connect_permission_check() {
return Rest_Authentication::is_signed_with_blog_token()
? true
: new WP_Error( 'invalid_permission_remote_connect', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
/**
* Remote register endpoint permission check.
*
@ -761,11 +815,7 @@ class REST_Connector {
$redirect_uri = $request->get_param( 'redirect_uri' ) ? admin_url( $request->get_param( 'redirect_uri' ) ) : null;
if ( class_exists( 'Jetpack' ) ) {
$authorize_url = \Jetpack::build_authorize_url( $redirect_uri );
} else {
$authorize_url = $this->connection->get_authorization_url( null, $redirect_uri );
}
$authorize_url = ( new Authorize_Redirect( $this->connection ) )->build_authorize_url( $redirect_uri );
/**
* Filters the response of jetpack/v4/connection/register endpoint
@ -885,7 +935,7 @@ class REST_Connector {
*
* @since 1.29.0
*
* @return bool|WP_Error.
* @return bool|WP_Error
*/
public static function update_user_token_permission_check() {
return Rest_Authentication::is_signed_with_blog_token()
@ -934,4 +984,41 @@ class REST_Connector {
return new WP_Error( 'invalid_user_permission_set_connection_owner', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
/**
* The endpoint verifies blog connection and blog token validity.
*
* @since 2.7.0
*
* @return mixed|null
*/
public function connection_check() {
/**
* Filters the successful response of the REST API test_connection method
*
* @param string $response The response string.
*/
$status = apply_filters( 'jetpack_rest_connection_check_response', 'success' );
return rest_ensure_response(
array(
'status' => $status,
)
);
}
/**
* Remote connect endpoint permission check.
*
* @return true|WP_Error
*/
public function connection_check_permission_check() {
if ( current_user_can( 'jetpack_connect' ) ) {
return true;
}
return Rest_Authentication::is_signed_with_blog_token()
? true
: new WP_Error( 'invalid_permission_connection_check', self::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
}

View File

@ -158,6 +158,7 @@ class Secrets {
*/
do_action( 'jetpack_verify_secrets_begin', $action, $user );
/** Closure to run the 'fail' action and return an error. */
$return_error = function ( WP_Error $error ) use ( $action, $user ) {
/**
* Verifying of the previously generated secret has failed.

View File

@ -223,7 +223,7 @@ class Server_Sandbox {
*
* Attached to the `admin_bar_menu` action.
*
* @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
* @param \WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
*/
public function admin_bar_add_sandbox_item( $wp_admin_bar ) {
if ( ! Constants::get_constant( 'JETPACK__SANDBOX_DOMAIN' ) ) {

View File

@ -38,8 +38,8 @@ class Tracking {
/**
* Creates the Tracking object.
*
* @param String $product_name the slug of the product that we are tracking.
* @param Automattic\Jetpack\Connection\Manager $connection the connection manager object.
* @param String $product_name the slug of the product that we are tracking.
* @param \Automattic\Jetpack\Connection\Manager $connection the connection manager object.
*/
public function __construct( $product_name = 'jetpack', $connection = null ) {
$this->product_name = $product_name;
@ -159,7 +159,7 @@ class Tracking {
*
* @param string $event_type Type of the event.
* @param array $data Data to send with the event.
* @param mixed $user Username, user_id, or WP_user object.
* @param mixed $user Username, user_id, or WP_User object.
* @param bool $use_product_prefix Whether to use the object's product name as a prefix to the event type. If
* set to false, the prefix will be 'jetpack_'.
*/
@ -189,7 +189,7 @@ class Tracking {
/**
* Record an event in Tracks - this is the preferred way to record events from PHP.
*
* @param mixed $user username, user_id, or WP_user object.
* @param mixed $user username, user_id, or WP_User object.
* @param string $event_name The name of the event.
* @param array $properties Custom properties to send with the event.
* @param int $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred.
@ -221,8 +221,8 @@ class Tracking {
/**
* Determines whether tracking should be enabled.
*
* @param Automattic\Jetpack\Terms_Of_Service $terms_of_service A Terms_Of_Service object.
* @param Automattic\Jetpack\Status $status A Status object.
* @param \Automattic\Jetpack\Terms_Of_Service $terms_of_service A Terms_Of_Service object.
* @param \Automattic\Jetpack\Status $status A Status object.
*
* @return boolean True if tracking should be enabled, else false.
*/
@ -238,10 +238,10 @@ class Tracking {
* Procedurally build a Tracks Event Object.
* NOTE: Use this only when the simpler Automattic\Jetpack\Tracking->jetpack_tracks_record_event() function won't work for you.
*
* @param WP_user $user WP_user object.
* @param string $event_name The name of the event.
* @param array $properties Custom properties to send with the event.
* @param int $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred.
* @param \WP_User $user WP_User object.
* @param string $event_name The name of the event.
* @param array $properties Custom properties to send with the event.
* @param int $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred.
*
* @return \Jetpack_Tracks_Event|\WP_Error
*/

View File

@ -82,8 +82,8 @@ class Urls {
/**
* Return URL with a normalized protocol.
*
* @param callable $callable Function to retrieve URL option.
* @param string $new_value URL Protocol to set URLs to.
* @param string $callable Function name that was used to retrieve URL option.
* @param string $new_value URL Protocol to set URLs to.
* @return string Normalized URL.
*/
public static function get_protocol_normalized_url( $callable, $new_value ) {

View File

@ -83,4 +83,53 @@ class Utils {
)
);
}
/**
* Generate a new user from a SSO attempt.
*
* @param object $user_data WordPress.com user information.
*/
public static function generate_user( $user_data ) {
$username = $user_data->login;
/**
* Determines how many times the SSO module can attempt to randomly generate a user.
*
* @module sso
*
* @since jetpack-4.3.2
*
* @param int 5 By default, SSO will attempt to random generate a user up to 5 times.
*/
$num_tries = (int) apply_filters( 'jetpack_sso_allowed_username_generate_retries', 5 );
$exists = username_exists( $username );
$tries = 0;
while ( $exists && $tries++ < $num_tries ) {
$username = $user_data->login . '_' . $user_data->ID . '_' . wp_rand();
$exists = username_exists( $username );
}
if ( $exists ) {
return false;
}
$user = (object) array();
$user->user_pass = wp_generate_password( 20 );
$user->user_login = wp_slash( $username );
$user->user_email = wp_slash( $user_data->email );
$user->display_name = $user_data->display_name;
$user->first_name = $user_data->first_name;
$user->last_name = $user_data->last_name;
$user->url = $user_data->url;
$user->description = $user_data->description;
if ( isset( $user_data->role ) && $user_data->role ) {
$user->role = $user_data->role;
}
$created_user_id = wp_insert_user( $user );
update_user_meta( $created_user_id, 'wpcom_user_id', $user_data->ID );
return get_userdata( $created_user_id );
}
}

View File

@ -107,7 +107,7 @@ class Webhooks {
}
do_action( 'jetpack_client_authorize_processing' );
$data = stripslashes_deep( $_GET );
$data = stripslashes_deep( $_GET ); // We need all request data under the context of an authorization request.
$data['auth_type'] = 'client';
$roles = new Roles();
$role = $roles->translate_current_user_to_role();

View File

@ -7,6 +7,8 @@
namespace Automattic\Jetpack\Connection;
use IXR_Error;
/**
* Registers the XML-RPC methods for Connections.
*/
@ -69,10 +71,10 @@ class XMLRPC_Connector {
$code = -10520;
}
if ( ! class_exists( \IXR_Error::class ) ) {
if ( ! class_exists( IXR_Error::class ) ) {
require_once ABSPATH . WPINC . '/class-IXR.php';
}
return new \IXR_Error(
return new IXR_Error(
$code,
sprintf( 'Jetpack: [%s] %s', $data->get_error_code(), $data->get_error_message() )
);

View File

@ -0,0 +1,184 @@
<?php
/**
* Force Jetpack 2FA Functionality
*
* Ported from original repo at https://github.com/automattic/jetpack-force-2fa
*
* @package automattic/jetpack-connection
*/
namespace Automattic\Jetpack\Connection\SSO;
use Automattic\Jetpack\Connection\SSO;
use Automattic\Jetpack\Modules;
use WP_Error;
/**
* Force users to use two factor authentication.
*/
class Force_2FA {
/**
* The role to force 2FA for.
*
* Defaults to manage_options via the plugins_loaded function.
* Can be modified with the jetpack_force_2fa_cap filter.
*
* @var string
*/
private $role;
/**
* Constructor.
*/
public function __construct() {
add_action( 'after_setup_theme', array( $this, 'plugins_loaded' ) );
}
/**
* Load the plugin via the plugins_loaded hook.
*/
public function plugins_loaded() {
/**
* Filter the role to force 2FA for.
* Defaults to manage_options.
*
* @param string $role The role to force 2FA for.
* @return string
* @since jetpack-12.7
* @module SSO
*/
$this->role = apply_filters( 'jetpack_force_2fa_cap', 'manage_options' );
// Bail if Jetpack SSO is not active
if ( ! ( new Modules() )->is_active( 'sso' ) ) {
add_action( 'admin_notices', array( $this, 'admin_notice' ) );
return;
}
$this->force_2fa();
}
/**
* Display an admin notice if Jetpack SSO is not active.
*/
public function admin_notice() {
/**
* Filter if an admin notice is deplayed when Force 2FA is required, but SSO is not enabled.
* Defaults to true.
*
* @param bool $display_notice Whether to display the notice.
* @return bool
* @since jetpack-12.7
* @module SSO
*/
if ( apply_filters( 'jetpack_force_2fa_dependency_notice', true ) && current_user_can( $this->role ) ) {
wp_admin_notice(
esc_html__( 'Jetpack Force 2FA requires Jetpacks SSO feature.', 'jetpack-connection' ),
array(
'type' => 'warning',
)
);
}
}
/**
* Force 2FA when using Jetpack SSO and force Jetpack SSO.
*
* @return void
*/
private function force_2fa() {
// Allows WP.com login to a local account if it matches the local account.
add_filter( 'jetpack_sso_match_by_email', '__return_true', 9999 );
// multisite
if ( is_multisite() ) {
// Hide the login form
add_filter( 'jetpack_remove_login_form', '__return_true', 9999 );
add_filter( 'jetpack_sso_bypass_login_forward_wpcom', '__return_true', 9999 );
add_filter( 'jetpack_sso_display_disclaimer', '__return_false', 9999 );
add_filter(
'wp_authenticate_user',
function () {
return new WP_Error( 'wpcom-required', $this->get_login_error_message() ); },
9999
);
add_filter( 'jetpack_sso_require_two_step', '__return_true' );
add_filter( 'allow_password_reset', '__return_false' );
} else {
// Not multisite.
// Completely disable the standard login form for admins.
add_filter(
'wp_authenticate_user',
function ( $user ) {
if ( is_wp_error( $user ) ) {
return $user;
}
if ( $user->has_cap( $this->role ) ) {
return new WP_Error( 'wpcom-required', $this->get_login_error_message(), $user->user_login );
}
return $user;
},
9999
);
add_filter(
'allow_password_reset',
function ( $allow, $user_id ) {
if ( user_can( $user_id, $this->role ) ) {
return false;
}
return $allow; },
9999,
2
);
add_action( 'jetpack_sso_pre_handle_login', array( $this, 'jetpack_set_two_step' ) );
}
}
/**
* Specifically set the two step filter for Jetpack SSO.
*
* @param Object $user_data The user data from WordPress.com.
*
* @return void
*/
public function jetpack_set_two_step( $user_data ) {
$user = SSO::get_user_by_wpcom_id( $user_data->ID );
// Borrowed from Jetpack. Ignores the match_by_email setting.
if ( empty( $user ) ) {
$user = get_user_by( 'email', $user_data->email );
}
if ( $user && $user->has_cap( $this->role ) ) {
add_filter( 'jetpack_sso_require_two_step', '__return_true' );
}
}
/**
* Get the login error message.
*
* @return string
*/
private function get_login_error_message() {
/**
* Filter the login error message.
* Defaults to a message that explains the user must use a WordPress.com account with 2FA enabled.
*
* @param string $message The login error message.
* @return string
* @since jetpack-12.7
* @module SSO
*/
return apply_filters(
'jetpack_force_2fa_login_error_message',
sprintf( 'For added security, please log in using your WordPress.com account.<br /><br />Note: Your account must have <a href="%1$s" target="_blank">Two Step Authentication</a> enabled, which can be configured from <a href="%2$s" target="_blank">Security Settings</a>.', 'https://support.wordpress.com/security/two-step-authentication/', 'https://wordpress.com/me/security/two-step' )
);
}
}

View File

@ -0,0 +1,387 @@
<?php
/**
* A collection of helper functions used in the SSO module.
*
* @package automattic/jetpack-connection
*/
namespace Automattic\Jetpack\Connection\SSO;
use Automattic\Jetpack\Constants;
use Jetpack_IXR_Client;
/**
* A collection of helper functions used in the SSO module.
*
* @since jetpack-4.1.0
*/
class Helpers {
/**
* Determine if the login form should be hidden or not
*
* @return bool
**/
public static function should_hide_login_form() {
/**
* Remove the default log in form, only leave the WordPress.com log in button.
*
* @module sso
*
* @since jetpack-3.1.0
*
* @param bool get_option( 'jetpack_sso_remove_login_form', false ) Should the default log in form be removed. Default to false.
*/
return (bool) apply_filters( 'jetpack_remove_login_form', get_option( 'jetpack_sso_remove_login_form', false ) );
}
/**
* Returns a boolean value for whether logging in by matching the WordPress.com user email to a
* Jetpack site user's email is allowed.
*
* @return bool
*/
public static function match_by_email() {
$match_by_email = defined( 'WPCC_MATCH_BY_EMAIL' ) ? \WPCC_MATCH_BY_EMAIL : (bool) get_option( 'jetpack_sso_match_by_email', true );
/**
* Link the local account to an account on WordPress.com using the same email address.
*
* @module sso
*
* @since jetpack-2.6.0
*
* @param bool $match_by_email Should we link the local account to an account on WordPress.com using the same email address. Default to false.
*/
return (bool) apply_filters( 'jetpack_sso_match_by_email', $match_by_email );
}
/**
* Returns a boolean for whether users are allowed to register on the Jetpack site with SSO,
* even though the site disallows normal registrations.
*
* @param object|null $user_data WordPress.com user information.
* @return bool|string
*/
public static function new_user_override( $user_data = null ) {
$new_user_override = defined( 'WPCC_NEW_USER_OVERRIDE' ) ? \WPCC_NEW_USER_OVERRIDE : false;
/**
* Allow users to register on your site with a WordPress.com account, even though you disallow normal registrations.
* If you return a string that corresponds to a user role, the user will be given that role.
*
* @module sso
*
* @since jetpack-2.6.0
* @since jetpack-4.6 $user_data object is now passed to the jetpack_sso_new_user_override filter
*
* @param bool|string $new_user_override Allow users to register on your site with a WordPress.com account. Default to false.
* @param object|null $user_data An object containing the user data returned from WordPress.com.
*/
$role = apply_filters( 'jetpack_sso_new_user_override', $new_user_override, $user_data );
if ( $role ) {
if ( is_string( $role ) && get_role( $role ) ) {
return $role;
} else {
return get_option( 'default_role' );
}
}
return false;
}
/**
* Returns a boolean value for whether two-step authentication is required for SSO.
*
* @since jetpack-4.1.0
*
* @return bool
*/
public static function is_two_step_required() {
/**
* Is it required to have 2-step authentication enabled on WordPress.com to use SSO?
*
* @module sso
*
* @since jetpack-2.8.0
*
* @param bool get_option( 'jetpack_sso_require_two_step' ) Does SSO require 2-step authentication?
*/
return (bool) apply_filters( 'jetpack_sso_require_two_step', get_option( 'jetpack_sso_require_two_step', false ) );
}
/**
* Returns a boolean for whether a user that is attempting to log in will be automatically
* redirected to WordPress.com to begin the SSO flow.
*
* @return bool
*/
public static function bypass_login_forward_wpcom() {
/**
* Redirect the site's log in form to WordPress.com's log in form.
*
* @module sso
*
* @since jetpack-3.1.0
*
* @param bool false Should the site's log in form be automatically forwarded to WordPress.com's log in form.
*/
return (bool) apply_filters( 'jetpack_sso_bypass_login_forward_wpcom', false );
}
/**
* Returns a boolean for whether the SSO login form should be displayed as the default
* when both the default and SSO login form allowed.
*
* @since jetpack-4.1.0
*
* @return bool
*/
public static function show_sso_login() {
if ( self::should_hide_login_form() ) {
return true;
}
/**
* Display the SSO login form as the default when both the default and SSO login forms are enabled.
*
* @module sso
*
* @since jetpack-4.1.0
*
* @param bool true Should the SSO login form be displayed by default when the default login form is also enabled?
*/
return (bool) apply_filters( 'jetpack_sso_default_to_sso_login', true );
}
/**
* Returns a boolean for whether the two step required checkbox, displayed on the Jetpack admin page, should be disabled.
*
* @since jetpack-4.1.0
*
* @return bool
*/
public static function is_require_two_step_checkbox_disabled() {
return (bool) has_filter( 'jetpack_sso_require_two_step' );
}
/**
* Returns a boolean for whether the match by email checkbox, displayed on the Jetpack admin page, should be disabled.
*
* @since jetpack-4.1.0
*
* @return bool
*/
public static function is_match_by_email_checkbox_disabled() {
return defined( 'WPCC_MATCH_BY_EMAIL' ) || has_filter( 'jetpack_sso_match_by_email' );
}
/**
* Returns an array of hosts that SSO will redirect to.
*
* Instead of accessing JETPACK__API_BASE within the method directly, we set it as the
* default for $api_base due to restrictions with testing constants in our tests.
*
* @since jetpack-4.3.0
* @since jetpack-4.6.0 Added public-api.wordpress.com as an allowed redirect
*
* @param array $hosts Allowed redirect hosts.
* @param string $api_base Base API URL.
*
* @return array
*/
public static function allowed_redirect_hosts( $hosts, $api_base = '' ) {
if ( empty( $api_base ) ) {
$api_base = Constants::get_constant( 'JETPACK__API_BASE' );
}
if ( empty( $hosts ) ) {
$hosts = array();
}
$hosts[] = 'wordpress.com';
$hosts[] = 'jetpack.wordpress.com';
$hosts[] = 'public-api.wordpress.com';
$hosts[] = 'jetpack.com';
if ( ! str_contains( $api_base, 'jetpack.wordpress.com/jetpack' ) ) {
$base_url_parts = wp_parse_url( esc_url_raw( $api_base ) );
if ( $base_url_parts && ! empty( $base_url_parts['host'] ) ) {
$hosts[] = $base_url_parts['host'];
}
}
return array_unique( $hosts );
}
/**
* Determines how long the auth cookie is valid for when a user logs in with SSO.
*
* @return int result of the jetpack_sso_auth_cookie_expiration filter.
*/
public static function extend_auth_cookie_expiration_for_sso() {
/**
* Determines how long the auth cookie is valid for when a user logs in with SSO.
*
* @module sso
*
* @since jetpack-4.4.0
* @since jetpack-6.1.0 Fixed a typo. Filter was previously jetpack_sso_auth_cookie_expirtation.
*
* @param int YEAR_IN_SECONDS
*/
return (int) apply_filters( 'jetpack_sso_auth_cookie_expiration', YEAR_IN_SECONDS );
}
/**
* Determines if the SSO form should be displayed for the current action.
*
* @since jetpack-4.6.0
*
* @param string $action SSO action being performed.
*
* @return bool Is SSO allowed for the current action?
*/
public static function display_sso_form_for_action( $action ) {
/**
* Allows plugins the ability to overwrite actions where the SSO form is allowed to be used.
*
* @module sso
*
* @since jetpack-4.6.0
*
* @param array $allowed_actions_for_sso
*/
$allowed_actions_for_sso = (array) apply_filters(
'jetpack_sso_allowed_actions',
array(
'login',
'jetpack-sso',
'jetpack_json_api_authorization',
)
);
return in_array( $action, $allowed_actions_for_sso, true );
}
/**
* This method returns an environment array that is meant to simulate `$_REQUEST` when the initial
* JSON API auth request was made.
*
* @since jetpack-4.6.0
*
* @return array|bool
*/
public static function get_json_api_auth_environment() {
if ( empty( $_COOKIE['jetpack_sso_original_request'] ) ) {
return false;
}
$original_request = esc_url_raw( wp_unslash( $_COOKIE['jetpack_sso_original_request'] ) );
$parsed_url = wp_parse_url( $original_request );
if ( empty( $parsed_url ) || empty( $parsed_url['query'] ) ) {
return false;
}
$args = array();
wp_parse_str( $parsed_url['query'], $args );
if ( empty( $args ) || empty( $args['action'] ) ) {
return false;
}
if ( 'jetpack_json_api_authorization' !== $args['action'] ) {
return false;
}
return array_merge(
$args,
array( 'jetpack_json_api_original_query' => $original_request )
);
}
/**
* Check if the site has a custom login page URL, and return it.
* If default login page URL is used (`wp-login.php`), `null` will be returned.
*
* @return string|null
*/
public static function get_custom_login_url() {
$login_url = wp_login_url();
if ( str_ends_with( $login_url, 'wp-login.php' ) ) {
// No custom URL found.
return null;
}
$site_url = trailingslashit( site_url() );
if ( ! str_starts_with( $login_url, $site_url ) ) {
// Something went wrong, we can't properly extract the custom URL.
return null;
}
// Extracting the "path" part of the URL, because we don't need the `site_url` part.
return str_ireplace( $site_url, '', $login_url );
}
/**
* Clear the cookies that store the profile information for the last
* WPCOM user to connect.
*/
public static function clear_wpcom_profile_cookies() {
if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_name_' . COOKIEHASH ] ) ) {
setcookie(
'jetpack_sso_wpcom_name_' . COOKIEHASH,
' ',
time() - YEAR_IN_SECONDS,
COOKIEPATH,
COOKIE_DOMAIN,
is_ssl(),
true
);
}
if ( isset( $_COOKIE[ 'jetpack_sso_wpcom_gravatar_' . COOKIEHASH ] ) ) {
setcookie(
'jetpack_sso_wpcom_gravatar_' . COOKIEHASH,
' ',
time() - YEAR_IN_SECONDS,
COOKIEPATH,
COOKIE_DOMAIN,
is_ssl(),
true
);
}
}
/**
* Remove an SSO connection for a user.
*
* @param int $user_id The local user id.
*/
public static function delete_connection_for_user( $user_id ) {
$wpcom_user_id = get_user_meta( $user_id, 'wpcom_user_id', true );
if ( ! $wpcom_user_id ) {
return;
}
$xml = new Jetpack_IXR_Client(
array(
'wpcom_user_id' => $user_id,
)
);
$xml->query( 'jetpack.sso.removeUser', $wpcom_user_id );
if ( $xml->isError() ) {
return false;
}
// Clean up local data stored for SSO.
delete_user_meta( $user_id, 'wpcom_user_id' );
delete_user_meta( $user_id, 'wpcom_user_data' );
self::clear_wpcom_profile_cookies();
return $xml->getResponse();
}
}

View File

@ -0,0 +1,241 @@
<?php
/**
* A collection of helper functions used in the SSO module.
*
* @package automattic/jetpack-connection
*/
namespace Automattic\Jetpack\Connection\SSO;
use Automattic\Jetpack\Redirect;
use WP_Error;
use WP_User;
/**
* A collection of helper functions used in the SSO module.
*
* @since jetpack-4.4.0
*/
class Notices {
/**
* Error message displayed on the login form when two step is required and
* the user's account on WordPress.com does not have two step enabled.
*
* @since jetpack-2.7
* @param string $message Error message.
* @return string
**/
public static function error_msg_enable_two_step( $message ) {
$error = sprintf(
wp_kses(
/* translators: URL to settings page */
__(
'Two-Step Authentication is required to access this site. Please visit your <a href="%1$s" rel="noopener noreferrer" target="_blank">Security Settings</a> to configure <a href="%2$s" rel="noopener noreferrer" target="_blank">Two-step Authentication</a> for your account.',
'jetpack-connection'
),
array( 'a' => array( 'href' => array() ) )
),
Redirect::get_url( 'calypso-me-security-two-step' ),
Redirect::get_url( 'wpcom-support-security-two-step-authentication' )
);
$message .= sprintf( '<p class="message" id="login_error">%s</p>', $error );
return $message;
}
/**
* Error message displayed when the user tries to SSO, but match by email
* is off and they already have an account with their email address on
* this site.
*
* @param string $message Error message.
* @return string
*/
public static function error_msg_email_already_exists( $message ) {
$error = sprintf(
wp_kses(
/* translators: login URL */
__(
'You already have an account on this site. Please <a href="%1$s">sign in</a> with your username and password and then connect to WordPress.com.',
'jetpack-connection'
),
array( 'a' => array( 'href' => array() ) )
),
esc_url_raw( add_query_arg( 'jetpack-sso-show-default-form', '1', wp_login_url() ) )
);
$message .= sprintf( '<p class="message" id="login_error">%s</p>', $error );
return $message;
}
/**
* Error message that is displayed when the current site is in an identity crisis and SSO can not be used.
*
* @since jetpack-4.3.2
*
* @param string $message Error Message.
*
* @return string
*/
public static function error_msg_identity_crisis( $message ) {
$error = esc_html__( 'Logging in with WordPress.com is not currently available because this site is experiencing connection problems.', 'jetpack-connection' );
$message .= sprintf( '<p class="message" id="login_error">%s</p>', $error );
return $message;
}
/**
* Error message that is displayed when we are not able to verify the SSO nonce due to an XML error or
* failed validation. In either case, we prompt the user to try again or log in with username and password.
*
* @since jetpack-4.3.2
*
* @param string $message Error message.
*
* @return string
*/
public static function error_invalid_response_data( $message ) {
$error = esc_html__(
'There was an error logging you in via WordPress.com, please try again or try logging in with your username and password.',
'jetpack-connection'
);
$message .= sprintf( '<p class="message" id="login_error">%s</p>', $error );
return $message;
}
/**
* Error message that is displayed when we were not able to automatically create an account for a user
* after a user has logged in via SSO. By default, this message is triggered after trying to create an account 5 times.
*
* @since jetpack-4.3.2
*
* @param string $message Error message.
*
* @return string
*/
public static function error_unable_to_create_user( $message ) {
$error = esc_html__(
'There was an error creating a user for you. Please contact the administrator of your site.',
'jetpack-connection'
);
$message .= sprintf( '<p class="message" id="login_error">%s</p>', $error );
return $message;
}
/**
* When the default login form is hidden, this method is called on the 'authenticate' filter with a priority of 30.
* This method disables the ability to submit the default login form.
*
* @param WP_User|WP_Error $user Either the user attempting to login or an existing authentication failure.
*
* @return WP_Error
*/
public static function disable_default_login_form( $user ) {
if ( is_wp_error( $user ) ) {
return $user;
}
/**
* Since we're returning an error that will be shown as a red notice, let's remove the
* informational "blue" notice.
*/
remove_filter( 'login_message', array( static::class, 'msg_login_by_jetpack' ) );
return new WP_Error( 'jetpack_sso_required', self::get_sso_required_message() );
}
/**
* Message displayed when the site admin has disabled the default WordPress
* login form in Settings > General > Secure Sign On
*
* @since jetpack-2.7
* @param string $message Error message.
*
* @return string
**/
public static function msg_login_by_jetpack( $message ) {
$message .= sprintf( '<p class="message">%s</p>', self::get_sso_required_message() );
return $message;
}
/**
* Get the message for SSO required.
*
* @return string
*/
public static function get_sso_required_message() {
$msg = esc_html__(
'A WordPress.com account is required to access this site. Click the button below to sign in or create a free WordPress.com account.',
'jetpack-connection'
);
/**
* Filter the message displayed when the default WordPress login form is disabled.
*
* @module sso
*
* @since jetpack-2.8.0
*
* @param string $msg Disclaimer when default WordPress login form is disabled.
*/
return apply_filters( 'jetpack_sso_disclaimer_message', $msg );
}
/**
* Message displayed when the user can not be found after approving the SSO process on WordPress.com
*
* @param string $message Error message.
*
* @return string
*/
public static function cant_find_user( $message ) {
$error = __(
"We couldn't find your account. If you already have an account, make sure you have connected to WordPress.com.",
'jetpack-connection'
);
/**
* Filters the "couldn't find your account" notice after an attempted SSO.
*
* @module sso
*
* @since jetpack-10.5.0
*
* @param string $error Error text.
*/
$error = apply_filters( 'jetpack_sso_unknown_user_notice', $error );
$message .= sprintf( '<p class="message" id="login_error">%s</p>', esc_html( $error ) );
return $message;
}
/**
* Error message that is displayed when the current site is in an identity crisis and SSO can not be used.
*
* @since jetpack-4.4.0
*
* @param string $message Error message.
*
* @return string
*/
public static function sso_not_allowed_in_staging( $message ) {
$error = __(
'Logging in with WordPress.com is disabled for sites that are in staging mode.',
'jetpack-connection'
);
/**
* Filters the disallowed notice for staging sites attempting SSO.
*
* @module sso
*
* @since jetpack-10.5.0
*
* @param string $error Error text.
*/
$error = apply_filters( 'jetpack_sso_disallowed_staging_notice', $error );
$message .= sprintf( '<p class="message">%s</p>', esc_html( $error ) );
return $message;
}
}

View File

@ -0,0 +1,21 @@
.jetpack-sso-admin-create-user-invite-message {
width: 550px;
}
.jetpack-sso-admin-create-user-invite-message-link-sso {
text-decoration: none;
}
#createuser .form-field textarea {
width: 25em;
}
#createuser .form-field [type=checkbox] {
width: 1rem;
}
#custom_email_message_description {
max-width: 25rem;
color: #646970;
font-size: 12px;
}

View File

@ -0,0 +1,45 @@
document.addEventListener( 'DOMContentLoaded', function () {
const sendUserNotificationCheckbox = document.getElementById( 'send_user_notification' );
const userExternalContractorCheckbox = document.getElementById( 'user_external_contractor' );
const inviteUserWpcomCheckbox = document.getElementById( 'invite_user_wpcom' );
const customEmailMessageBlock = document.getElementById( 'custom_email_message_block' );
if ( inviteUserWpcomCheckbox && sendUserNotificationCheckbox && customEmailMessageBlock ) {
// Toggle Send User Notification checkbox enabled/disabled based on Invite User checkbox
// Enable External Contractor checkbox if Invite User checkbox is checked
// Show/hide the external email message field.
inviteUserWpcomCheckbox.addEventListener( 'change', function () {
sendUserNotificationCheckbox.disabled = inviteUserWpcomCheckbox.checked;
if ( inviteUserWpcomCheckbox.checked ) {
sendUserNotificationCheckbox.checked = false;
if ( userExternalContractorCheckbox ) {
userExternalContractorCheckbox.disabled = false;
}
customEmailMessageBlock.style.display = 'table';
} else {
if ( userExternalContractorCheckbox ) {
userExternalContractorCheckbox.disabled = true;
userExternalContractorCheckbox.checked = false;
}
customEmailMessageBlock.style.display = 'none';
}
} );
// On load, disable Send User Notification checkbox
// and show the custom email message if Invite User checkbox is checked
if ( inviteUserWpcomCheckbox.checked ) {
sendUserNotificationCheckbox.disabled = true;
sendUserNotificationCheckbox.checked = false;
customEmailMessageBlock.style.display = 'table';
}
// On load, disable External Contractor checkbox
// and hide the custom email message if Invite User checkbox is unchecked
if ( ! inviteUserWpcomCheckbox.checked ) {
if ( userExternalContractorCheckbox ) {
userExternalContractorCheckbox.disabled = true;
}
customEmailMessageBlock.style.display = 'none';
}
}
} );

View File

@ -0,0 +1,164 @@
#loginform {
/* We set !important because sometimes static is added inline */
position: relative !important;
padding-bottom: 92px;
}
.jetpack-sso-repositioned #loginform {
padding-bottom: 26px;
}
#loginform #jetpack-sso-wrap,
#loginform #jetpack-sso-wrap * {
box-sizing: border-box;
}
#jetpack-sso-wrap__action,
#jetpack-sso-wrap__user {
display: none;
}
.jetpack-sso-form-display #jetpack-sso-wrap__action,
.jetpack-sso-form-display #jetpack-sso-wrap__user {
display: block;
}
#jetpack-sso-wrap {
position: absolute;
bottom: 20px;
padding: 0 24px;
margin-left: -24px;
margin-right: -24px;
width: 100%;
}
.jetpack-sso-repositioned #jetpack-sso-wrap {
position: relative;
bottom: auto;
padding: 0;
margin-top: 16px;
margin-left: 0;
margin-right: 0;
}
.jetpack-sso-form-display #jetpack-sso-wrap {
position: relative;
bottom: auto;
padding: 0;
margin-top: 0;
margin-left: 0;
margin-right: 0;
}
#loginform #jetpack-sso-wrap p {
color: #777777;
margin-bottom: 16px;
}
#jetpack-sso-wrap a {
display: block;
width: 100%;
text-align: center;
text-decoration: none;
}
#jetpack-sso-wrap .jetpack-sso-toggle.wpcom {
display: none;
}
.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.wpcom {
display: block;
}
.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.default {
display: none;
}
.jetpack-sso-form-display #loginform>p,
.jetpack-sso-form-display #loginform>div {
display: none;
}
.jetpack-sso-form-display #loginform #jetpack-sso-wrap {
display: block;
}
.jetpack-sso-form-display #loginform {
padding: 26px 24px;
}
.jetpack-sso-or {
margin-bottom: 16px;
position: relative;
text-align: center;
}
.jetpack-sso-or:before {
background: #dcdcde;
content: '';
height: 1px;
position: absolute;
left: 0;
top: 50%;
width: 100%;
}
.jetpack-sso-or span {
background: #fff;
color: #777;
position: relative;
padding: 0 8px;
text-transform: uppercase
}
#jetpack-sso-wrap .button {
display: flex;
justify-content: center;
align-items: center;
height: 36px;
margin-bottom: 16px;
width: 100%;
}
#jetpack-sso-wrap .button .genericon-wordpress {
font-size: 24px;
margin-right: 4px;
}
#jetpack-sso-wrap__user img {
border-radius: 50%;
display: block;
margin: 0 auto 16px;
}
#jetpack-sso-wrap__user h2 {
font-size: 21px;
font-weight: 300;
margin-bottom: 16px;
text-align: center;
}
#jetpack-sso-wrap__user h2 span {
font-weight: bold;
}
.jetpack-sso-wrap__reauth {
margin-bottom: 16px;
}
.jetpack-sso-form-display #nav {
display: none;
}
.jetpack-sso-form-display #backtoblog {
margin: 24px 0 0;
}
.jetpack-sso-clear:after {
content: "";
display: table;
clear: both;
}

View File

@ -0,0 +1,27 @@
document.addEventListener( 'DOMContentLoaded', () => {
const body = document.querySelector( 'body' ),
toggleSSO = document.querySelector( '.jetpack-sso-toggle' ),
userLogin = document.getElementById( 'user_login' ),
userPassword = document.getElementById( 'user_pass' ),
ssoWrap = document.getElementById( 'jetpack-sso-wrap' ),
loginForm = document.getElementById( 'loginform' ),
overflow = document.createElement( 'div' );
overflow.className = 'jetpack-sso-clear';
loginForm.appendChild( overflow );
overflow.appendChild( document.querySelector( 'p.forgetmenot' ) );
overflow.appendChild( document.querySelector( 'p.submit' ) );
loginForm.appendChild( ssoWrap );
body.classList.add( 'jetpack-sso-repositioned' );
toggleSSO.addEventListener( 'click', e => {
e.preventDefault();
body.classList.toggle( 'jetpack-sso-form-display' );
if ( ! body.classList.contains( 'jetpack-sso-form-display' ) ) {
userLogin.focus();
userPassword.disabled = false;
}
} );
} );

View File

@ -0,0 +1,64 @@
document.addEventListener( 'DOMContentLoaded', function () {
document
.querySelectorAll( '.jetpack-sso-invitation-tooltip-icon:not(.sso-disconnected-user)' )
.forEach( function ( tooltip ) {
tooltip.innerHTML += ' [?]';
const tooltipTextbox = document.createElement( 'span' );
tooltipTextbox.classList.add( 'jetpack-sso-invitation-tooltip', 'jetpack-sso-th-tooltip' );
const tooltipString = window.Jetpack_SSOTooltip.tooltipString;
tooltipTextbox.innerHTML += tooltipString;
tooltip.addEventListener( 'mouseenter', appendTooltip );
tooltip.addEventListener( 'focus', appendTooltip );
tooltip.addEventListener( 'mouseleave', removeTooltip );
tooltip.addEventListener( 'blur', removeTooltip );
/**
* Display the tooltip textbox.
*/
function appendTooltip() {
tooltip.appendChild( tooltipTextbox );
tooltipTextbox.style.display = 'block';
}
/**
* Remove the tooltip textbox.
*/
function removeTooltip() {
// Only remove tooltip if the element isn't currently active.
if ( document.activeElement === tooltip ) {
return;
}
tooltip.removeChild( tooltipTextbox );
}
} );
document
.querySelectorAll( '.jetpack-sso-invitation-tooltip-icon:not(.jetpack-sso-status-column)' )
.forEach( function ( tooltip ) {
tooltip.addEventListener( 'mouseenter', appendSSOInvitationTooltip );
tooltip.addEventListener( 'focus', appendSSOInvitationTooltip );
tooltip.addEventListener( 'mouseleave', removeSSOInvitationTooltip );
tooltip.addEventListener( 'blur', removeSSOInvitationTooltip );
} );
/**
* Display the SSO invitation tooltip textbox.
*/
function appendSSOInvitationTooltip() {
this.querySelector( '.jetpack-sso-invitation-tooltip' ).style.display = 'block';
}
/**
* Remove the SSO invitation tooltip textbox.
*
* @param {Event} event - Triggering event.
*/
function removeSSOInvitationTooltip( event ) {
if ( document.activeElement === event.target ) {
return;
}
this.querySelector( '.jetpack-sso-invitation-tooltip' ).style.display = 'none';
}
} );

View File

@ -10,6 +10,7 @@ namespace Automattic\Jetpack\Connection\Webhooks;
use Automattic\Jetpack\Admin_UI\Admin_Menu;
use Automattic\Jetpack\Constants;
use Automattic\Jetpack\Licensing;
use Automattic\Jetpack\Status\Host;
use Automattic\Jetpack\Tracking;
use GP_Locales;
use Jetpack_Network;
@ -21,14 +22,14 @@ class Authorize_Redirect {
/**
* The Connection Manager object.
*
* @var Manager
* @var \Automattic\Jetpack\Connection\Manager
*/
private $connection;
/**
* Constructs the object
*
* @param Automattic\Jetpack\Connection\Manager $connection The Connection Manager object.
* @param \Automattic\Jetpack\Connection\Manager $connection The Connection Manager object.
*/
public function __construct( $connection ) {
$this->connection = $connection;
@ -97,44 +98,57 @@ class Authorize_Redirect {
}
/**
* Create the Jetpack authorization URL. Copied from Jetpack class.
* Create the Jetpack authorization URL.
*
* @since 2.7.6 Added optional $from and $raw parameters.
*
* @param bool|string $redirect URL to redirect to.
* @param bool|string $from If not false, adds 'from=$from' param to the connect URL.
* @param bool $raw If true, URL will not be escaped.
*
* @todo Update default value for redirect since the called function expects a string.
*
* @return mixed|void
*/
public function build_authorize_url( $redirect = false ) {
public function build_authorize_url( $redirect = false, $from = false, $raw = false ) {
add_filter( 'jetpack_connect_request_body', array( __CLASS__, 'filter_connect_request_body' ) );
add_filter( 'jetpack_connect_redirect_url', array( __CLASS__, 'filter_connect_redirect_url' ) );
$url = $this->connection->get_authorization_url( wp_get_current_user(), $redirect );
$url = $this->connection->get_authorization_url( wp_get_current_user(), $redirect, $from, $raw );
remove_filter( 'jetpack_connect_request_body', array( __CLASS__, 'filter_connect_request_body' ) );
remove_filter( 'jetpack_connect_redirect_url', array( __CLASS__, 'filter_connect_redirect_url' ) );
/** This filter is documented in plugins/jetpack/class-jetpack.php */
return apply_filters( 'jetpack_build_authorize_url', $url );
/**
* Filter the URL used when authorizing a user to a WordPress.com account.
*
* @since jetpack-8.9.0
* @since 2.7.6 Added $raw parameter.
*
* @param string $url Connection URL.
* @param bool $raw If true, URL will not be escaped.
*/
return apply_filters( 'jetpack_build_authorize_url', $url, $raw );
}
/**
* Filters the redirection URL that is used for connect requests. The redirect
* URL should return the user back to the Jetpack console.
* Copied from Jetpack class.
* URL should return the user back to the My Jetpack page.
*
* @param String $redirect the default redirect URL used by the package.
* @return String the modified URL.
* @param string $redirect the default redirect URL used by the package.
* @return string the modified URL.
*/
public static function filter_connect_redirect_url( $redirect ) {
$jetpack_admin_page = esc_url_raw( admin_url( 'admin.php?page=jetpack' ) );
$jetpack_admin_page = esc_url_raw( admin_url( 'admin.php?page=my-jetpack' ) );
$redirect = $redirect
? wp_validate_redirect( esc_url_raw( $redirect ), $jetpack_admin_page )
: $jetpack_admin_page;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( isset( $_REQUEST['is_multisite'] ) ) {
if (
class_exists( 'Jetpack_Network' )
&& isset( $_REQUEST['is_multisite'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
) {
$redirect = Jetpack_Network::init()->get_url( 'network_admin_page' );
}
@ -143,7 +157,6 @@ class Authorize_Redirect {
/**
* Filters the connection URL parameter array.
* Copied from Jetpack class.
*
* @param array $args default URL parameters used by the package.
* @return array the modified URL arguments array.
@ -170,7 +183,7 @@ class Authorize_Redirect {
)
);
$calypso_env = self::get_calypso_env();
$calypso_env = ( new Host() )->get_calypso_env();
if ( ! empty( $calypso_env ) ) {
$args['calypso_env'] = $calypso_env;
@ -184,25 +197,15 @@ class Authorize_Redirect {
* it with different Calypso enrionments, such as localhost.
* Copied from Jetpack class.
*
* @deprecated 2.7.6
*
* @since 1.37.1
*
* @return string Calypso environment
*/
public static function get_calypso_env() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['calypso_env'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
return sanitize_key( $_GET['calypso_env'] );
}
_deprecated_function( __METHOD__, '2.7.6', 'Automattic\\Jetpack\\Status\\Host::get_calypso_env' );
if ( getenv( 'CALYPSO_ENV' ) ) {
return sanitize_key( getenv( 'CALYPSO_ENV' ) );
}
if ( defined( 'CALYPSO_ENV' ) && CALYPSO_ENV ) {
return sanitize_key( CALYPSO_ENV );
}
return '';
return ( new Host() )->get_calypso_env();
}
}

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.2] - 2024-04-30
### Changed
- Internal updates.
## [2.0.1] - 2024-03-12
### Changed
- Internal updates.
@ -162,6 +166,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Packages: Finish the constants package
[2.0.2]: https://github.com/Automattic/jetpack-constants/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-constants/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-constants/compare/v1.6.23...v2.0.0
[1.6.23]: https://github.com/Automattic/jetpack-constants/compare/v1.6.22...v1.6.23

View File

@ -9,7 +9,7 @@
"require-dev": {
"brain/monkey": "2.6.1",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1"
"automattic/jetpack-changelogger": "^4.2.2"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."

View File

@ -29,7 +29,7 @@ class Constants {
* @access public
* @static
*
* @var array.
* @var array
*/
public static $set_constants = array();

View File

@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.1.3] - 2024-04-08
### Added
- Added functionality for extracting the browser and desktop platform from a user agent. [#36568]
### Changed
- Add new bots. [#36477]
## [2.1.2] - 2024-03-18
### Changed
- Internal updates.
@ -189,6 +196,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Moving jetpack_is_mobile into a package
[2.1.3]: https://github.com/Automattic/jetpack-device-detection/compare/v2.1.2...v2.1.3
[2.1.2]: https://github.com/Automattic/jetpack-device-detection/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/Automattic/jetpack-device-detection/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/Automattic/jetpack-device-detection/compare/v2.0.1...v2.1.0

View File

@ -49,6 +49,8 @@ class Device_Detection {
'is_smartphone' => self::is_mobile( 'smart', false, $ua_info ),
'is_tablet' => $ua_info->is_tablet(),
'platform' => $ua_info->get_platform(),
'desktop_platform' => $ua_info->get_desktop_platform(),
'browser' => $ua_info->get_browser(),
);
$info['is_handheld'] = $info['is_phone'] || $info['is_tablet'];

View File

@ -64,19 +64,30 @@ class User_Agent_Info {
*
* @var null|string
*/
private $platform = null;
const PLATFORM_WINDOWS = 'windows';
const PLATFORM_IPHONE = 'iphone';
const PLATFORM_IPOD = 'ipod';
const PLATFORM_IPAD = 'ipad';
const PLATFORM_BLACKBERRY = 'blackberry';
const PLATFORM_BLACKBERRY_10 = 'blackberry_10';
const PLATFORM_SYMBIAN = 'symbian_series60';
const PLATFORM_SYMBIAN_S40 = 'symbian_series40';
const PLATFORM_J2ME_MIDP = 'j2me_midp';
const PLATFORM_ANDROID = 'android';
const PLATFORM_ANDROID_TABLET = 'android_tablet';
const PLATFORM_FIREFOX_OS = 'firefoxOS';
private $platform = null;
const PLATFORM_WINDOWS = 'windows';
const PLATFORM_IPHONE = 'iphone';
const PLATFORM_IPOD = 'ipod';
const PLATFORM_IPAD = 'ipad';
const PLATFORM_BLACKBERRY = 'blackberry';
const PLATFORM_BLACKBERRY_10 = 'blackberry_10';
const PLATFORM_SYMBIAN = 'symbian_series60';
const PLATFORM_SYMBIAN_S40 = 'symbian_series40';
const PLATFORM_J2ME_MIDP = 'j2me_midp';
const PLATFORM_ANDROID = 'android';
const PLATFORM_ANDROID_TABLET = 'android_tablet';
const PLATFORM_FIREFOX_OS = 'firefoxOS';
const PLATFORM_DESKTOP_LINUX = 'linux';
const PLATFORM_DESKTOP_MAC = 'mac';
const PLATFORM_DESKTOP_WINDOWS = 'windows';
const PLATFORM_DESKTOP_CHROME = 'chrome';
const BROWSER_CHROME = 'chrome';
const BROWSER_FIREFOX = 'firefox';
const BROWSER_SAFARI = 'safari';
const BROWSER_EDGE = 'edge';
const BROWSER_OPERA = 'opera';
const BROWSER_IE = 'ie';
const OTHER = 'other';
/**
* A list of dumb-phone user agent parts.
@ -277,6 +288,57 @@ class User_Agent_Info {
return $this->platform;
}
/**
* Returns the platform for desktops
*
* @return string
*/
public function get_desktop_platform() {
$ua = $this->useragent;
if ( empty( $ua ) ) {
return false;
}
$platform = self::OTHER;
if ( static::is_linux_desktop() ) {
$platform = self::PLATFORM_DESKTOP_LINUX;
} elseif ( static::is_mac_desktop() ) {
$platform = self::PLATFORM_DESKTOP_MAC;
} elseif ( static::is_windows_desktop() ) {
$platform = self::PLATFORM_DESKTOP_WINDOWS;
} elseif ( static::is_chrome_desktop() ) {
$platform = self::PLATFORM_DESKTOP_CHROME;
}
return $platform;
}
/**
* A simple pattern matching method for extracting the browser from the user agent.
*
* @return string
*/
public function get_browser() {
$ua = $this->useragent;
if ( empty( $ua ) ) {
return self::OTHER;
}
if ( static::is_opera_mini() || static::is_opera_mobile() || static::is_opera_desktop() || static::is_opera_mini_dumb() ) {
return self::BROWSER_OPERA;
} elseif ( static::is_edge_browser() ) {
return self::BROWSER_EDGE;
} elseif ( static::is_chrome_desktop() || self::is_chrome_for_iOS() ) {
return self::BROWSER_CHROME;
} elseif ( static::is_safari_browser() ) {
return self::BROWSER_SAFARI;
} elseif ( static::is_firefox_mobile() || static::is_firefox_desktop() ) {
return self::BROWSER_FIREFOX;
} elseif ( static::is_ie_browser() ) {
return self::BROWSER_IE;
}
return self::OTHER;
}
/**
* This method detects for UA which can display iPhone-optimized web content.
* Includes iPhone, iPod Touch, Android, WebOS, Fennec (Firefox mobile), etc.
@ -714,6 +776,46 @@ class User_Agent_Info {
}
}
/**
* Detect Safari browser
*/
public static function is_safari_browser() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( false === strpos( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ), 'Safari' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Detect Edge browser
*/
public static function is_edge_browser() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( false === strpos( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ), 'Edge' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Detect Edge browser
*/
public static function is_ie_browser() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
$ua = wp_unslash( $_SERVER['HTTP_USER_AGENT'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
if ( false === ( strpos( $ua, 'MSIE' ) || strpos( $ua, 'Trident/7' ) ) ) {
return false;
}
return true;
}
/**
* Detect modern Opera desktop
*
@ -1271,6 +1373,66 @@ class User_Agent_Info {
return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
}
/**
* Determines whether a desktop platform is Linux OS
*
* @return bool
*/
public static function is_linux_desktop() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( ! preg_match( '/linux/i', wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Determines whether a desktop platform is Mac OS
*
* @return bool
*/
public static function is_mac_desktop() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( ! preg_match( '/macintosh|mac os x/i', wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Determines whether a desktop platform is Windows OS
*
* @return bool
*/
public static function is_windows_desktop() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( ! preg_match( '/windows|win32/i', wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Determines whether a desktop platform is Chrome OS
*
* @return bool
*/
public static function is_chrome_desktop() {
if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
return false;
}
if ( ! preg_match( '/chrome/i', wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- This is validating.
return false;
}
return true;
}
/**
* Retrieve the blackberry OS version.
*
@ -1579,6 +1741,7 @@ class User_Agent_Info {
'bne.es_bot', // https://www.bne.es/es/colecciones/archivo-web-espanola/aviso-webmasters
'google-safety;', // https://www.google.com/bot.html
'mojeekbot', // https://www.mojeek.com/bot.html
'linkwalker', // https://www.linkwalker.com/
);
foreach ( $bot_agents as $bot_agent ) {

View File

@ -5,6 +5,62 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.20.0] - 2024-05-20
### Removed
- IDC: Remove deprecated code. [#37421]
## [0.19.0] - 2024-05-16
### Added
- IDC: Add escapes to echo statements. [#37395]
### Changed
- Updated package dependencies. [#37379]
- Updated package dependencies. [#37380]
## [0.18.6] - 2024-05-06
### Changed
- Updated package dependencies. [#37147]
### Fixed
- Fix class references in `URL_Secret::create_secret()` exception handler. [#37201]
## [0.18.5] - 2024-04-29
### Changed
- Internal updates.
## [0.18.4] - 2024-04-25
### Changed
- Update dependencies.
## [0.18.3] - 2024-04-08
### Changed
- Updated package dependencies. [#36760]
## [0.18.2] - 2024-04-02
### Changed
- Internal updates.
## [0.18.1] - 2024-04-01
### Changed
- Tests: moved tests from a separate files to the main tests file. [#36656]
## [0.18.0] - 2024-03-29
### Added
- Packages: added version tracking for identity-crisis. [#36635]
- REST: added endpoint for IDC validation. [#36537]
## [0.17.6] - 2024-03-27
### Changed
- Updated package dependencies. [#36585]
## [0.17.5] - 2024-03-25
### Changed
- Internal updates.
## [0.17.4] - 2024-03-18
### Changed
- Internal updates.
## [0.17.3] - 2024-03-14
### Changed
- Internal updates.
@ -503,6 +559,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated package dependencies.
- Use Connection/Urls for home_url and site_url functions migrated from Sync.
[0.20.0]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.19.0...v0.20.0
[0.19.0]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.6...v0.19.0
[0.18.6]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.5...v0.18.6
[0.18.5]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.4...v0.18.5
[0.18.4]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.3...v0.18.4
[0.18.3]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.2...v0.18.3
[0.18.2]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.1...v0.18.2
[0.18.1]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.18.0...v0.18.1
[0.18.0]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.6...v0.18.0
[0.17.6]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.5...v0.17.6
[0.17.5]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.4...v0.17.5
[0.17.4]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.3...v0.17.4
[0.17.3]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.2...v0.17.3
[0.17.2]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.1...v0.17.2
[0.17.1]: https://github.com/Automattic/jetpack-identity-crisis/compare/v0.17.0...v0.17.1

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => '607b018606bd0a465d3b');
<?php return array('dependencies' => array('react', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => '4b5c20bc6fc08deb6c73');

View File

@ -5,14 +5,14 @@
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-connection": "^2.4.1",
"automattic/jetpack-constants": "^2.0.1",
"automattic/jetpack-status": "^2.1.2",
"automattic/jetpack-logo": "^2.0.1",
"automattic/jetpack-assets": "^2.1.4"
"automattic/jetpack-connection": "^2.8.3",
"automattic/jetpack-constants": "^2.0.2",
"automattic/jetpack-status": "^3.1.0",
"automattic/jetpack-logo": "^2.0.3",
"automattic/jetpack-assets": "^2.1.11"
},
"require-dev": {
"automattic/jetpack-changelogger": "^4.1.1",
"automattic/jetpack-changelogger": "^4.2.4",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/wordbless": "@dev"
},
@ -57,7 +57,7 @@
"link-template": "https://github.com/Automattic/jetpack-identity-crisis/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "0.17.x-dev"
"dev-trunk": "0.20.x-dev"
}
},
"config": {

View File

@ -26,7 +26,12 @@ class Identity_Crisis {
/**
* Package Version
*/
const PACKAGE_VERSION = '0.17.3';
const PACKAGE_VERSION = '0.20.0';
/**
* Package Slug
*/
const PACKAGE_SLUG = 'identity-crisis';
/**
* Persistent WPCOM blog ID that stays in the options after disconnect.
@ -58,7 +63,7 @@ class Identity_Crisis {
/**
* The current screen, which is set if the current user is a non-admin and this is an admin page.
*
* @var WP_Screen
* @var \WP_Screen
*/
public static $current_screen;
@ -98,6 +103,9 @@ class Identity_Crisis {
add_filter( 'jetpack_register_request_body', array( static::class, 'register_request_body' ) );
add_action( 'jetpack_site_registered', array( static::class, 'site_registered' ) );
// Set up package version hook.
add_filter( 'jetpack_package_versions', array( static::class, 'send_package_version_to_tracker' ) );
$urls_in_crisis = self::check_identity_crisis();
if ( false === $urls_in_crisis ) {
return;
@ -107,6 +115,19 @@ class Identity_Crisis {
add_action( 'init', array( $this, 'wordpress_init' ) );
}
/**
* Adds the package slug and version to the package version tracker's data.
*
* @param array $package_versions The package version array.
*
* @return array The package version array.
*/
public static function send_package_version_to_tracker( $package_versions ) {
$package_versions[ self::PACKAGE_SLUG ] = self::PACKAGE_VERSION;
return $package_versions;
}
/**
* Disconnect current connection and clear IDC options.
*/
@ -138,17 +159,6 @@ class Identity_Crisis {
return ! self::validate_sync_error_idc_option();
}
/**
* Gets the link to the support document used to explain Safe Mode to users.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public static function get_safe_mod_doc_url() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
return Redirect::get_url( 'jetpack-support-safe-mode' );
}
/**
* This method loops through the array of processed items from sync and checks if one of the items was the
* home_url or site_url callable. If so, then we delete the jetpack_migrate_for_idc option.
@ -354,19 +364,6 @@ class Identity_Crisis {
return false;
}
/**
* Prepare URL for display.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @param string $url URL to display.
*
* @return string
*/
public static function prepare_url_for_display( $url ) {
_deprecated_function( __METHOD__, 'package-0.17.0' );
return untrailingslashit( self::normalize_url_protocol_agnostic( $url ) );
}
/**
* Clears all IDC specific options. This method is used on disconnect and reconnect.
*
@ -571,447 +568,6 @@ class Identity_Crisis {
return (bool) apply_filters( 'jetpack_should_handle_idc', $default );
}
/**
* Is a container for the error notices.
* Will be shown/controlled by jQuery in idc-notice.js.
*
* @deprecated 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return void
*/
public function render_error_notice() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
?>
<div class="jp-idc-error__notice dops-notice is-error">
<svg class="gridicon gridicons-notice dops-notice__icon" height="24" width="24" viewBox="0 0 24 24">
<g>
<path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 15h-2v-2h2v2zm0-4h-2l-.5-6h3l-.5 6z"></path>
</g>
</svg>
<div class="dops-notice__content">
<span class="dops-notice__text">
<?php esc_html_e( 'Something went wrong:', 'jetpack-idc' ); ?>
<span class="jp-idc-error__desc"></span>
</span>
<a class="dops-notice__action" href="javascript:void(0);">
<span id="jp-idc-error__action">
<?php esc_html_e( 'Try Again', 'jetpack-idc' ); ?>
</span>
</a>
</div>
</div>
<?php
}
/**
* Renders the first step notice.
*
* @deprecated 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return void
*/
public function render_notice_first_step() {
_deprecated_function( __METHOD__, ' 0.17.0' );
?>
<div class="jp-idc-notice__first-step">
<div class="jp-idc-notice__content-header">
<h3 class="jp-idc-notice__content-header__lead">
<?php echo $this->get_first_step_header_lead(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</h3>
<p class="jp-idc-notice__content-header__explanation">
<?php echo $this->get_first_step_header_explanation(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
</div>
<?php $this->render_error_notice(); ?>
<div class="jp-idc-notice__actions">
<div class="jp-idc-notice__action">
<p class="jp-idc-notice__action__explanation">
<?php echo $this->get_confirm_safe_mode_action_explanation(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
<button id="jp-idc-confirm-safe-mode-action" class="dops-button">
<?php echo $this->get_confirm_safe_mode_button_text(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</button>
</div>
<div class="jp-idc-notice__action">
<p class="jp-idc-notice__action__explanation">
<?php echo $this->get_first_step_fix_connection_action_explanation(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
<button id="jp-idc-fix-connection-action" class="dops-button">
<?php echo $this->get_first_step_fix_connection_button_text(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</button>
</div>
</div>
</div>
<?php
}
/**
* Renders the second step notice.
*
* @deprecated 0.17.0 Use `@automattic/jetpack-idc` instead.
*
* @return void
*/
public function render_notice_second_step() {
_deprecated_function( __METHOD__, ' 0.17.0' );
?>
<div class="jp-idc-notice__second-step">
<div class="jp-idc-notice__content-header">
<h3 class="jp-idc-notice__content-header__lead">
<?php echo $this->get_second_step_header_lead(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</h3>
</div>
<?php $this->render_error_notice(); ?>
<div class="jp-idc-notice__actions">
<div class="jp-idc-notice__action">
<p class="jp-idc-notice__action__explanation">
<?php echo $this->get_migrate_site_action_explanation(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
<button id="jp-idc-migrate-action" class="dops-button">
<?php echo $this->get_migrate_site_button_text(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</button>
</div>
<div class="jp-idc-notice__action">
<p class="jp-idc-notice__action__explanation">
<?php echo $this->get_start_fresh_action_explanation(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
<button id="jp-idc-reconnect-site-action" class="dops-button">
<?php echo $this->get_start_fresh_button_text(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</button>
</div>
</div>
<p class="jp-idc-notice__unsure-prompt">
<?php echo $this->get_unsure_prompt(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
</div>
<?php
}
/**
* Returns the first step header lead.
*
* @deprecated 0.17.0 Use `@automattic/jetpack-idc` instead.
*
* @return string
*/
public function get_first_step_header_lead() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Safe mode docs URL and site URL. */
__( 'Jetpack has been placed into <a href="%1$s">Safe mode</a> because we noticed this is an exact copy of <a href="%2$s">%3$s</a>.', 'jetpack-idc' ),
esc_url( self::get_safe_mod_doc_url() ),
esc_url( self::$wpcom_home_url ),
self::prepare_url_for_display( esc_url_raw( self::$wpcom_home_url ) )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default header text in the first step of the Safe Mode notice.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_first_step_header_lead', $html );
}
/**
* Returns the first step header explanation.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
*
* @return string
*/
public function get_first_step_header_explanation() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Safe mode docs URL. */
__( 'Please confirm Safe Mode or fix the Jetpack connection. Select one of the options below or <a href="%1$s">learn more about Safe Mode</a>.', 'jetpack-idc' ),
esc_url( self::get_safe_mod_doc_url() )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default header explanation text in the first step of the Safe Mode notice.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_first_step_header_explanation', $html );
}
/**
* Returns the confirm safe mode explanation.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_confirm_safe_mode_action_explanation() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Site URL. */
__( 'Is this website a temporary duplicate of <a href="%1$s">%2$s</a> for the purposes of testing, staging or development? If so, we recommend keeping it in Safe Mode.', 'jetpack-idc' ),
esc_url( untrailingslashit( self::$wpcom_home_url ) ),
self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default text used to explain the confirm safe mode action.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_confirm_safe_mode_explanation', $html );
}
/**
* Returns the confirm safe mode button text.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_confirm_safe_mode_button_text() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$string = esc_html__( 'Confirm Safe Mode', 'jetpack-idc' );
/**
* Allows overriding of the default text used for the confirm safe mode action button.
*
* @param string $string The string to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_confirm_safe_mode_button_text', $string );
}
/**
* Returns the first step fix connection action explanation.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_first_step_fix_connection_action_explanation() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Site URL. */
__( 'If this is a separate and new website, or the new home of <a href="%1$s">%2$s</a>, we recommend turning Safe Mode off, and re-establishing your connection to WordPress.com.', 'jetpack-idc' ),
esc_url( untrailingslashit( self::$wpcom_home_url ) ),
self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default text used to explain the fix Jetpack connection action.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_first_fix_connection_explanation', $html );
}
/**
* Returns the first step fix connection button text.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_first_step_fix_connection_button_text() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$string = esc_html__( "Fix Jetpack's Connection", 'jetpack-idc' );
/**
* Allows overriding of the default text used for the fix Jetpack connection action button.
*
* @param string $string The string to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_first_step_fix_connection_button_text', $string );
}
/**
* Returns the second step header lead.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_second_step_header_lead() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$string = sprintf(
/* translators: %s: Site URL. */
esc_html__( 'Is %1$s the new home of %2$s?', 'jetpack-idc' ),
untrailingslashit( self::normalize_url_protocol_agnostic( get_home_url() ) ),
untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
);
/**
* Allows overriding of the default header text in the second step of the Safe Mode notice.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_second_step_header_lead', $string );
}
/**
* Returns the site action explanation.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_migrate_site_action_explanation() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Site URL. */
__( 'Yes. <a href="%1$s">%2$s</a> is replacing <a href="%3$s">%4$s</a>. I would like to migrate my stats and subscribers from <a href="%3$s">%4$s</a> to <a href="%1$s">%2$s</a>.', 'jetpack-idc' ),
esc_url( get_home_url() ),
self::prepare_url_for_display( get_home_url() ),
esc_url( self::$wpcom_home_url ),
untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default text for explaining the migrate site action.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_migrate_site_explanation', $html );
}
/**
* Returns the migrate site button text.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_migrate_site_button_text() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$string = esc_html__( 'Migrate Stats &amp; Subscribers', 'jetpack-idc' );
/**
* Allows overriding of the default text used for the migrate site action button.
*
* @param string $string The string to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_migrate_site_button_text', $string );
}
/**
* Returns the start fresh explanation.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_start_fresh_action_explanation() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Site URL. */
__( 'No. <a href="%1$s">%2$s</a> is a new and different website that\'s separate from <a href="%3$s">%4$s</a>. It requires a new connection to WordPress.com for new stats and subscribers.', 'jetpack-idc' ),
esc_url( get_home_url() ),
self::prepare_url_for_display( get_home_url() ),
esc_url( self::$wpcom_home_url ),
untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default text for explaining the start fresh action.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_start_fresh_explanation', $html );
}
/**
* Returns the start fresh button text.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_start_fresh_button_text() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$string = esc_html__( 'Start Fresh &amp; Create New Connection', 'jetpack-idc' );
/**
* Allows overriding of the default text used for the start fresh action button.
*
* @param string $string The string to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_start_fresh_button_text', $string );
}
/**
* Returns the unsure prompt text.
*
* @deprecated since 0.17.0 Use `@automattic/jetpack-idc` instead.
* @return string
*/
public function get_unsure_prompt() {
_deprecated_function( __METHOD__, 'package-0.17.0' );
$html = wp_kses(
sprintf(
/* translators: %s: Safe mode docs URL. */
__( 'Unsure what to do? <a href="%1$s">Read more about Jetpack Safe Mode</a>', 'jetpack-idc' ),
esc_url( self::get_safe_mod_doc_url() )
),
array( 'a' => array( 'href' => array() ) )
);
/**
* Allows overriding of the default text using in the "Unsure what to do?" prompt.
*
* @param string $html The HTML to be displayed.
*
* @since 0.2.0
* @since-jetpack 4.4.0
*/
return apply_filters( 'jetpack_idc_unsure_prompt', $html );
}
/**
* Whether the site is undergoing identity crisis.
*
@ -1138,6 +694,7 @@ class Identity_Crisis {
* @param array $response The endpoint response that we're modifying.
*
* @return array
*
* phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag -- The exception is being caught, false positive.
*/
public static function add_secret_to_url_validation_response( array $response ) {

View File

@ -10,6 +10,7 @@ namespace Automattic\Jetpack\IdentityCrisis;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Connection\Rest_Authentication;
use Jetpack_Options;
use Jetpack_XMLRPC_Server;
use WP_Error;
use WP_REST_Server;
@ -64,6 +65,17 @@ class REST_Endpoints {
)
);
// Fetch URL and secret for IDC check.
register_rest_route(
'jetpack/v4',
'/identity-crisis/idc-url-validation',
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( static::class, 'validate_urls_and_set_secret' ),
'permission_callback' => array( static::class, 'url_secret_permission_check' ),
)
);
// Fetch URL verification secret.
register_rest_route(
'jetpack/v4',
@ -214,6 +226,20 @@ class REST_Endpoints {
return new WP_Error( 'invalid_user_permission_identity_crisis', $error_msg, array( 'status' => rest_authorization_required_code() ) );
}
/**
* Endpoint for URL validation and creating a secret.
*
* @since 0.18.0
*
* @return array
*/
public static function validate_urls_and_set_secret() {
$xmlrpc_server = new Jetpack_XMLRPC_Server();
$result = $xmlrpc_server->validate_urls_for_idc_mitigation();
return $result;
}
/**
* Endpoint for fetching the existing secret.
*

View File

@ -7,6 +7,8 @@
namespace Automattic\Jetpack\IdentityCrisis;
use Automattic\Jetpack\Connection\Urls;
use Automattic\Jetpack\Tracking;
use Jetpack_Options;
/**

View File

@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.1.11] - 2024-05-16
### Changed
- Updated package dependencies. [#37379]
## [3.1.10] - 2024-05-06
### Changed
- Updated package dependencies. [#37147]
## [3.1.9] - 2024-04-26
### Changed
- Internal updates.
## [3.1.8] - 2024-04-25
### Changed
- Internal updates.
## [3.1.7] - 2024-04-22
### Changed
- Internal updates.
## [3.1.6] - 2024-04-15
### Changed
- Internal updates.
## [3.1.5] - 2024-04-11
### Changed
- Internal updates.
## [3.1.4] - 2024-04-08
### Changed
- Updated package dependencies. [#36760]
## [3.1.3] - 2024-03-27
### Changed
- Updated package dependencies. [#36585]
## [3.1.2] - 2024-03-25
### Changed
- Update Phan baselines [#36441]
## [3.1.1] - 2024-03-14
### Changed
- Internal updates.
@ -683,6 +723,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update Jetpack to use new JITM package
[3.1.11]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.10...v3.1.11
[3.1.10]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.9...v3.1.10
[3.1.9]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.8...v3.1.9
[3.1.8]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.7...v3.1.8
[3.1.7]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.6...v3.1.7
[3.1.6]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.5...v3.1.6
[3.1.5]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.4...v3.1.5
[3.1.4]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.3...v3.1.4
[3.1.3]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.2...v3.1.3
[3.1.2]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.1...v3.1.2
[3.1.1]: https://github.com/Automattic/jetpack-jitm/compare/v3.1.0...v3.1.1
[3.1.0]: https://github.com/Automattic/jetpack-jitm/compare/v3.0.5...v3.1.0
[3.0.5]: https://github.com/Automattic/jetpack-jitm/compare/v3.0.4...v3.0.5

View File

@ -6,17 +6,17 @@
"require": {
"php": ">=7.0",
"automattic/jetpack-a8c-mc-stats": "^2.0.1",
"automattic/jetpack-assets": "^2.1.4",
"automattic/jetpack-connection": "^2.4.1",
"automattic/jetpack-device-detection": "^2.1.1",
"automattic/jetpack-logo": "^2.0.1",
"automattic/jetpack-redirect": "^2.0.1",
"automattic/jetpack-status": "^2.1.2"
"automattic/jetpack-assets": "^2.1.10",
"automattic/jetpack-connection": "^2.8.2",
"automattic/jetpack-device-detection": "^2.1.3",
"automattic/jetpack-logo": "^2.0.2",
"automattic/jetpack-redirect": "^2.0.2",
"automattic/jetpack-status": "^3.0.3"
},
"require-dev": {
"brain/monkey": "2.6.1",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1"
"automattic/jetpack-changelogger": "^4.2.3"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."

View File

@ -20,7 +20,7 @@ use Automattic\Jetpack\Status;
*/
class JITM {
const PACKAGE_VERSION = '3.1.1';
const PACKAGE_VERSION = '3.1.11';
/**
* The configuration method that is called from the jetpack-config package.

View File

@ -27,7 +27,7 @@ class Post_Connection_JITM extends JITM {
/**
* Tracking object.
*
* @var Automattic\Jetpack\Tracking
* @var \Automattic\Jetpack\Tracking
*
* @access private
*/
@ -43,9 +43,9 @@ class Post_Connection_JITM extends JITM {
/**
* A special filter for WooCommerce, to set a message based on local state.
*
* @param string $content The current message.
* @param object $content The current message.
*
* @return array The new message.
* @return object The new message.
*/
public static function jitm_woocommerce_services_msg( $content ) {
if ( ! function_exists( 'wc_get_base_location' ) ) {

View File

@ -8,6 +8,8 @@
namespace Automattic\Jetpack\JITMS;
use Automattic\Jetpack\Connection\REST_Connector;
use WP_Error;
use WP_REST_Request;
use WP_REST_Server;
/**
@ -61,7 +63,7 @@ class Rest_Api_Endpoints {
$query['s'] = $request['s'];
}
return $jitm->get_messages( $request['message_path'], urldecode_deep( $query ), 'true' === $request['full_jp_logo_exists'] ? true : false );
return $jitm->get_messages( $request['message_path'], urldecode_deep( $query ), 'true' === $request['full_jp_logo_exists'] );
}
/**
@ -91,6 +93,6 @@ class Rest_Api_Endpoints {
return true;
}
return new \WP_Error( 'invalid_user_permission_jetpack_delete_jitm_message', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
return new WP_Error( 'invalid_user_permission_jetpack_delete_jitm_message', REST_Connector::get_user_permissions_error_msg(), array( 'status' => rest_authorization_required_code() ) );
}
}

View File

@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.5] - 2024-04-22
### Changed
- Internal updates.
## [2.0.4] - 2024-04-08
### Changed
- Internal updates.
## [2.0.3] - 2024-03-25
### Changed
- Internal updates.
## [2.0.2] - 2024-03-14
### Changed
- Internal updates.
@ -260,6 +272,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Licensing: Add support for Jetpack licenses
[2.0.5]: https://github.com/Automattic/jetpack-licensing/compare/v2.0.4...v2.0.5
[2.0.4]: https://github.com/Automattic/jetpack-licensing/compare/v2.0.3...v2.0.4
[2.0.3]: https://github.com/Automattic/jetpack-licensing/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/Automattic/jetpack-licensing/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-licensing/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-licensing/compare/v1.8.4...v2.0.0

View File

@ -5,12 +5,12 @@
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-connection": "^2.4.1"
"automattic/jetpack-connection": "^2.7.2"
},
"require-dev": {
"automattic/wordbless": "@dev",
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.1"
"automattic/jetpack-changelogger": "^4.2.2"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."

View File

@ -13,6 +13,8 @@ use Automattic\Jetpack\Licensing;
use Automattic\Jetpack\Status\Visitor;
use Jetpack_Options;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
/**
* Class Endpoints.

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.3] - 2024-05-20
### Changed
- Replaced heredoc syntax with strings. [#37396]
## [2.0.2] - 2024-03-18
### Changed
- Internal updates.
@ -174,6 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Packages: Add a basic Jetpack Logo package
[2.0.3]: https://github.com/Automattic/jetpack-logo/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/Automattic/jetpack-logo/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-logo/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-logo/compare/v1.6.3...v2.0.0

View File

@ -8,7 +8,7 @@
},
"require-dev": {
"yoast/phpunit-polyfills": "1.1.0",
"automattic/jetpack-changelogger": "^4.1.2"
"automattic/jetpack-changelogger": "^4.2.4"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."

View File

@ -19,14 +19,14 @@ namespace Automattic\Jetpack\Assets;
*
* @var string
*/
const JETPACK_LOGO_SVG = <<<'EOSVG'
const JETPACK_LOGO_SVG = '
<svg xmlns="http://www.w3.org/2000/svg" height="32" class="jetpack-logo" viewBox="0 0 118 32">
<path class="jetpack-logo__icon-circle" d="M16,0C7.2,0,0,7.2,0,16s7.2,16,16,16s16-7.2,16-16S24.8,0,16,0z" fill="#069e08" />
<polygon class="jetpack-logo__icon-triangle" points="15,19 7,19 15,3" fill="#fff" />
<polygon class="jetpack-logo__icon-triangle" points="17,29 17,13 25,13" fill="#fff" />
<path class="jetpack-logo__text" d="M41.3 26.6c-.5-.7-.9-1.4-1.3-2.1 2.3-1.4 3-2.5 3-4.6V8h-3V6h6v13.4C46 22.8 45 24.8 41.3 26.6zM58.5 21.3c-1.5.5-2.7.6-4.2.6-3.6 0-5.8-1.8-5.8-6 0-3.1 1.9-5.9 5.5-5.9s4.9 2.5 4.9 4.9c0 .8 0 1.5-.1 2h-7.3c.1 2.5 1.5 2.8 3.6 2.8 1.1 0 2.2-.3 3.4-.7C58.5 19 58.5 21.3 58.5 21.3zM56 15c0-1.4-.5-2.9-2-2.9-1.4 0-2.3 1.3-2.4 2.9C51.6 15 56 15 56 15zM65 18.4c0 1.1.8 1.3 1.4 1.3.5 0 2-.2 2.6-.4v2.1c-.9.3-2.5.5-3.7.5-1.5 0-3.2-.5-3.2-3.1V12H60v-2h2.1V7.1H65V10h4v2h-4V18.4zM71 10h3v1.3c1.1-.8 1.9-1.3 3.3-1.3 2.5 0 4.5 1.8 4.5 5.6s-2.2 6.3-5.8 6.3c-.9 0-1.3-.1-2-.3V28h-3V10zM76.5 12.3c-.8 0-1.6.4-2.5 1.2v5.9c.6.1.9.2 1.8.2 2 0 3.2-1.3 3.2-3.9C79 13.4 78.1 12.3 76.5 12.3zM93 22h-3v-1.5c-.9.7-1.9 1.5-3.5 1.5-1.5 0-3.1-1.1-3.1-3.2 0-2.9 2.5-3.4 4.2-3.7l2.4-.3v-.3c0-1.5-.5-2.3-2-2.3-.7 0-2.3.5-3.7 1.1L84 11c1.2-.4 3-1 4.4-1 2.7 0 4.6 1.4 4.6 4.7L93 22zM90 16.4l-2.2.4c-.7.1-1.4.5-1.4 1.6 0 .9.5 1.4 1.3 1.4s1.5-.5 2.3-1V16.4zM104.5 21.3c-1.1.4-2.2.6-3.5.6-4.2 0-5.9-2.4-5.9-5.9 0-3.7 2.3-6 6.1-6 1.4 0 2.3.2 3.2.5V13c-.8-.3-2-.6-3.2-.6-1.7 0-3.2.9-3.2 3.6 0 2.9 1.5 3.8 3.3 3.8.9 0 1.9-.2 3.2-.7V21.3zM110 15.2c.2-.3.2-.8 3.8-5.2h3.7l-4.6 5.7 5 6.3h-3.7l-4.2-5.8V22h-3V6h3V15.2z" />
</svg>
EOSVG;
';
/**
* Create and render a Jetpack logo.

View File

@ -5,6 +5,145 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.24.1] - 2024-05-24
### Changed
- Update Search to require user connection. [#37496]
## [4.24.0] - 2024-05-23
### Changed
- Improve the active/inactive statuses on My Jetpack. [#37217]
## [4.23.3] - 2024-05-20
### Added
- Add tracks events for dropdown on action buttons. [#37292]
### Changed
- Updated package dependencies. [#37379] [#37380] [#37382]
## [4.23.2] - 2024-05-09
### Changed
- My Jetpack Agency banner copy change. [#37248]
### Fixed
- Fix typo [#37303]
## [4.23.1] - 2024-05-08
### Changed
- Update dependencies.
## [4.23.0] - 2024-05-06
### Added
- Add a has_free_offering boolean on My Jetpack products. [#36710]
- Add copy for AI features on connection screen. [#37218]
- Define `$module_name` static property on `Hybrid_Product` (defaulting to null). [#37201]
- Jetpack AI: Add new badge to Featured Image video on the product page. [#37197]
- My Jetpack: Add errors from the connection package to the new notice component. [#36840]
### Changed
- Change "go back" in My Jetpack interstitials to always return to the My Jetpack page. [#36685]
- Fix z-index issue and close action button dropdown when clicked outside. [#37169]
- Jetpack AI: Add featured image generation as a feature on the product interstitial. [#37199]
- Jetpack AI: Include video about featured image generation on the product page. [#37192]
- Updated package dependencies. [#37147] [#37148] [#37160]
## [4.22.3] - 2024-04-29
### Changed
- Internal updates.
## [4.22.2] - 2024-04-25
### Fixed
- My Jetpack: Fix issue where the TOS component was being called inside of a <p>, throwing a warning that <p> can't be a descendant of <p>. This also fixes the font size of the TOS text. [#37034]
## [4.22.1] - 2024-04-22
### Changed
- Internal updates.
## [4.22.0] - 2024-04-11
### Added
- Add new tracking event for product activations made through My Jetpack [#36745]
- My Jetpack: add a way to connect a Jetpack site to WordPress.com asynchronously and update the message in the notice to reflect that. [#36771]
### Fixed
- Ensure page_view gets loaded before product_card_loaded [#36790]
## [4.21.0] - 2024-04-08
### Added
- Add 'from' property to connection call to WP.com. [#36741]
- My Jetpack: Update Notice component to allow adding a loading text when an action is in a loading state. Add a new resetNotice action to NoticeContext. [#36614]
### Changed
- My Jetpack: Show Boost score increase in Boost product card. [#36072]
- Updated package dependencies. [#36756] [#36760] [#36761]
- Update My Jetpack to use the Notice component from @automattic/jetpack-components and be more consistent with the other notices in Jetpack. [#36711]
### Removed
- My Jetpack: Removed custom Notice component from My Jetpack. [#36772]
- My Jetpack: Remove red bubble from connection notice in favor of using the status of the Notice component. [#36773]
### Fixed
- Fix cache on front end request for boost speed scores [#36700]
- fix tier upgrades in my Jetpack [#36705]
## [4.20.2] - 2024-04-02
### Fixed
- Fix Boost score inconsistency [#36679]
## [4.20.1] - 2024-04-01
### Added
- Change Phan baselines. [#36627]
## [4.20.0] - 2024-03-29
### Added
- Track active red bubble slugs on My Jetpack page view [#36611]
### Fixed
- Better handling on product interstitial pages if the site already has a paid product [#36570]
- Shows Jetpack CRM card as active on My Jetpack if the plugin is installed and active [#36594]
## [4.19.0] - 2024-03-27
### Added
- Add red bubble to notices tied to red bubble notifications [#36543]
- My Jetpack: add a version of WordPress' Notice component to My Jetpack considering the context of how we use notices on that screen [#36551]
### Changed
- Updated package dependencies. [#36539, #36585]
### Fixed
- Fixed Jetpack Creator going to the wrong screen when the free version is selected" [#36547]
- Fixes some pricing showing twice by connecting sites that select a free option [#36533]
## [4.18.0] - 2024-03-25
### Added
- Hook into red bubble notification when bad installation is detected [#36449]
- Jetpack AI: add notices on product page for exhausted requests [#35910]
- Jetpack AI: add plans/tier information on product page and corresponding CTAs [#35910]
- Jetpack AI: add support and create post links on product page [#35910]
- My Jetpack: add AI product page view event [#36488]
- My Jetpack: add feedback link on Jetpack AI product page [#35910]
- My Jetpack: AI pricing table is skipped once the user has opted for the free version [#35910]
- My Jetpack: change AI product for tiered pricing table display [#35910]
### Changed
- Add notice priorities to My Jetpack [#36438]
- Jetpack AI: address responsive issues on the styles [#35910]
- My Jetpack: AI product page styles update and responsive fixes [#35910]
- My Jetpack: change AI card action button target for upgraded users, point to product page [#35910]
### Removed
- My Jetpack: remove Jetpack AI code added throughout the new product page project [#35910]
- Removed reference to Creator Network, which is being deprecated. [#36168]
### Fixed
- Boost tooltips: fix typo in string. [#36520]
- My Jetpack: fix AI interstitial "remain free" flow [#35910]
- My Jetpack: fix interstitial event property malformed name productSlug -> product_slug [#36486]
- My Jetpack: fix spacing issues on the new product page [#35910]
- My Jetpack: new AI interstitial margin on admin page was messing with correct top spacing [#35910]
## [4.17.1] - 2024-03-18
### Added
- Add a loaded event for My Jetpack product cards [#36397]
## [4.17.0] - 2024-03-14
### Changed
- Rewrite My Jetpack hooks to Typescript [#36288]
@ -1347,6 +1486,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Created package
[4.24.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.24.0...4.24.1
[4.24.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.23.3...4.24.0
[4.23.3]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.23.2...4.23.3
[4.23.2]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.23.1...4.23.2
[4.23.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.23.0...4.23.1
[4.23.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.22.3...4.23.0
[4.22.3]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.22.2...4.22.3
[4.22.2]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.22.1...4.22.2
[4.22.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.22.0...4.22.1
[4.22.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.21.0...4.22.0
[4.21.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.20.2...4.21.0
[4.20.2]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.20.1...4.20.2
[4.20.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.20.0...4.20.1
[4.20.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.19.0...4.20.0
[4.19.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.18.0...4.19.0
[4.18.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.17.1...4.18.0
[4.17.1]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.17.0...4.17.1
[4.17.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.16.0...4.17.0
[4.16.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.15.0...4.16.0
[4.15.0]: https://github.com/Automattic/jetpack-my-jetpack/compare/4.14.0...4.15.0

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => '5782f9bf704638c25046');
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => 'cc72b3b90919a178b53e');

Some files were not shown because too many files have changed in this diff Show More