This commit is contained in:
emmymayo
2025-02-05 23:15:46 +01:00
commit 7269c99357
16995 changed files with 3389680 additions and 0 deletions
@@ -0,0 +1,98 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* WPCOM_JSON_API_Date class.
*
* @package automattic/jetpack
*/
/**
* Base class for WPCOM_JSON_API_Date.
*/
class WPCOM_JSON_API_Date {
/**
* Returns ISO 8601 formatted datetime: 2011-12-08T01:15:36-08:00
*
* @param string $date_gmt GMT datetime string.
* @param string $date Optional. Used to calculate the offset from GMT.
*
* @return string
*/
public static function format_date( $date_gmt, $date = null ) {
$offset = null;
$timestamp_gmt = strtotime( "$date_gmt+0000" );
if ( null === $date ) {
$timestamp = $timestamp_gmt;
$west = 0;
$minutes = 0;
$hours = 0;
} else {
$date_time = date_create( "$date+0000" );
if ( $date_time ) {
$timestamp = date_format( $date_time, 'U' );
} else {
$timestamp = 0;
}
// "0000-00-00 00:00:00" == -62169984000
if ( -62169984000 === $timestamp_gmt ) {
// WordPress sets post_date=now, post_date_gmt="0000-00-00 00:00:00" for all drafts
// WordPress sets post_modified=now, post_modified_gmt="0000-00-00 00:00:00" for new drafts.
// Try to guess the correct offset from the blog's options.
$timezone_string = get_option( 'timezone_string' );
if ( $timezone_string && $date_time ) {
$timezone = timezone_open( $timezone_string );
if ( $timezone ) {
$offset = $timezone->getOffset( $date_time );
}
} else {
$offset = 3600 * get_option( 'gmt_offset' );
}
} else {
$offset = $timestamp - $timestamp_gmt;
}
$west = $offset < 0;
$offset = abs( $offset );
$hours = (int) floor( $offset / 3600 );
$offset -= $hours * 3600;
$minutes = (int) floor( $offset / 60 );
}
return (string) gmdate( 'Y-m-d\\TH:i:s', $timestamp ) . sprintf( '%s%02d:%02d', $west ? '-' : '+', $hours, $minutes );
}
/**
* Returns ISO 8601 formatted duration interval: P0DT1H10M0S
*
* @param string $time Duration in minutes or hours.
*
* @return null|string
*/
public static function format_duration( $time ) {
$timestamp = strtotime( $time, 0 );
// Bail early if we don't recognize a date.
if ( empty( $timestamp ) ) {
return;
}
$days = floor( $timestamp / 86400 );
$timestamp = $timestamp % 86400;
$hours = floor( $timestamp / 3600 );
$timestamp = $timestamp % 3600;
$minutes = floor( $timestamp / 60 );
$timestamp = $timestamp % 60;
return (string) sprintf(
'P%dDT%dH%dM%dS',
$days,
$hours,
$minutes,
$timestamp
);
}
}
@@ -0,0 +1,446 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* WPCOM_JSON_API_Links class.
*
* @package automattic/jetpack
*/
require_once __DIR__ . '/../class.json-api.php';
/**
* Base class for WPCOM_JSON_API_Links.
*/
class WPCOM_JSON_API_Links {
/**
* An instance of the WPCOM_JSON_API.
*
* @var WPCOM_JSON_API
*/
private $api;
/**
* A WPCOM_JSON_API_Links instance.
*
* @var WPCOM_JSON_API_Links
*/
private static $instance;
/**
* An array of the closest supported version of an endpoint to the current endpoint.
*
* @var array
*/
private $closest_endpoint_cache_by_version = array();
/**
* An array including the current api endpoint as well as the max versions found if that endpoint doesn't exist.
*
* @var array
*/
private $matches_by_version = array();
/**
* An array including the cached endpoint path versions.
*
* @var array
*/
private $cache_result = null;
/**
* Creates a new instance of the WPCOM_JSON_API_Links class.
*
* @return WPCOM_JSON_API_Links
*/
public static function getInstance() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* WPCOM_JSON_API_Links constructor.
*
* Method protected for singleton.
*/
protected function __construct() {
$this->api = WPCOM_JSON_API::init();
}
/**
* An empty, private __clone method to prohibit cloning of this instance.
*/
private function __clone() { }
/**
* Overriding PHP's default __wakeup method to prvent unserializing of the instance, and return an error message.
*
* @return never
*/
public function __wakeup() {
die( "Please don't __wakeup WPCOM_JSON_API_Links" );
}
/**
* Generate a URL to an endpoint
*
* Used to construct meta links in API responses
*
* @param mixed ...$args Optional arguments to be appended to URL.
* @return string Endpoint URL
**/
public function get_link( ...$args ) {
$format = array_shift( $args );
$base = WPCOM_JSON_API__BASE;
$path = array_pop( $args );
if ( $path ) {
$path = '/' . ltrim( $path, '/' );
// tack the path onto the end of the format string.
// have to escape %'s in the path as %% because
// we're about to pass it through sprintf and we don't
// want it to see the % as a placeholder.
$format .= str_replace( '%', '%%', $path );
}
// Escape any % in args before using sprintf.
$escaped_args = array();
foreach ( $args as $arg_key => $arg_value ) {
$escaped_args[ $arg_key ] = str_replace( '%', '%%', $arg_value );
}
$relative_path = vsprintf( $format, $escaped_args );
if ( ! wp_startswith( $relative_path, '.' ) ) {
// Generic version. Match the requested version as best we can.
$api_version = $this->get_closest_version_of_endpoint( $format, $relative_path );
$base = substr( $base, 0, - 1 ) . $api_version;
}
// escape any % in the relative path before running it through sprintf again.
$relative_path = str_replace( '%', '%%', $relative_path );
// http, WPCOM_JSON_API__BASE, ... , path.
// %s , %s , $format, %s.
return esc_url_raw( sprintf( "https://%s$relative_path", $base ) );
}
/**
* Generate the /me prefixed endpoint URL
*
* Used to construct meta links in API responses, specific to WordPress.com user account pages.
*
* @param string $path Optional path to be appended to the URL.
* @return string /me endpoint URL
**/
public function get_me_link( $path = '' ) {
return $this->get_link( '/me', $path );
}
/**
* Generate the endpoint URL for taxonomies
*
* Used to construct meta links in API responses, specific to taxonomies.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param int $taxonomy_id The taxonomy ID (for example of the category, tag).
* @param string $taxonomy_type The taxonomy type (for example category, tag).
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including taxonomy information.
**/
public function get_taxonomy_link( $blog_id, $taxonomy_id, $taxonomy_type, $path = '' ) {
switch ( $taxonomy_type ) {
case 'category':
return $this->get_link( '/sites/%d/categories/slug:%s', $blog_id, $taxonomy_id, $path );
case 'post_tag':
return $this->get_link( '/sites/%d/tags/slug:%s', $blog_id, $taxonomy_id, $path );
default:
return $this->get_link( '/sites/%d/taxonomies/%s/terms/slug:%s', $blog_id, $taxonomy_type, $taxonomy_id, $path );
}
}
/**
* Generate the endpoint URL for media links
*
* Used to construct meta links in API responses, specific to media links.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param int $media_id The media item ID.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including media information.
**/
public function get_media_link( $blog_id, $media_id, $path = '' ) {
return $this->get_link( '/sites/%d/media/%d', $blog_id, $media_id, $path );
}
/**
* Generate the site link endpoint URL
*
* Used to construct meta links in API responses, specific to /site links.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including site information.
**/
public function get_site_link( $blog_id, $path = '' ) {
return $this->get_link( '/sites/%d', $blog_id, $path );
}
/**
* Generate the posts endpoint URL
*
* Used to construct meta links in API responses, specific to posts links.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param int $post_id The post ID.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including post information.
**/
public function get_post_link( $blog_id, $post_id, $path = '' ) {
return $this->get_link( '/sites/%d/posts/%d', $blog_id, $post_id, $path );
}
/**
* Generate the comments endpoint URL
*
* Used to construct meta links in API responses, specific to comments links.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param int $comment_id The comment ID.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including comment information.
**/
public function get_comment_link( $blog_id, $comment_id, $path = '' ) {
return $this->get_link( '/sites/%d/comments/%d', $blog_id, $comment_id, $path );
}
/**
* Generate the endpoint URL for Publicize connections
*
* Used to construct meta links in API responses, specific to Publicize connections.
*
* @param int $blog_id The site's Jetpack blog ID.
* @param int $publicize_connection_id The ID of the Publicize connection.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including Publicize connection information.
**/
public function get_publicize_connection_link( $blog_id, $publicize_connection_id, $path = '' ) {
return $this->get_link( '.1/sites/%d/publicize-connections/%d', $blog_id, $publicize_connection_id, $path );
}
/**
* Generate the endpoint URL for a single Publicize connection including a Keyring connection
*
* Used to construct meta links in API responses, specific to a single Publicize and Keyring connection.
*
* @param int $keyring_token_id The ID of the Keyring connection.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including specific Keyring connection information for a specific Publicize connection.
**/
public function get_publicize_connections_link( $keyring_token_id, $path = '' ) {
return $this->get_link( '.1/me/publicize-connections/?keyring_connection_ID=%d', $keyring_token_id, $path );
}
/**
* Generate the endpoint URL for a single Keyring connection
*
* Used to construct meta links in API responses, specific to a Keyring connections.
*
* @param int $keyring_token_id The ID of the Keyring connection.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including specific Keyring connection.
**/
public function get_keyring_connection_link( $keyring_token_id, $path = '' ) {
return $this->get_link( '.1/me/keyring-connections/%d', $keyring_token_id, $path );
}
/**
* Generate the endpoint URL for an external service that can be integrated with via Keyring
*
* Used to construct meta links in API responses, specific to an external service.
*
* @param int $external_service The ID of the external service.
* @param string $path Optional path to be appended to the URL.
* @return string Endpoint URL including information about an external service that WordPress.com or Jetpack sites can integrate with via keyring.
**/
public function get_external_service_link( $external_service, $path = '' ) {
return $this->get_link( '.1/meta/external-services/%s', $external_service, $path );
}
/**
* Try to find the closest supported version of an endpoint to the current endpoint
*
* For example, if we were looking at the path /animals/panda:
* - if the current endpoint is v1.3 and there is a v1.3 of /animals/%s available, we return 1.3
* - if the current endpoint is v1.3 and there is no v1.3 of /animals/%s known, we fall back to the
* maximum available version of /animals/%s, e.g. 1.1
*
* This method is used in get_link() to construct meta links for API responses.
*
* @param string $template_path The generic endpoint path, e.g. /sites/%s .
* @param string $path The current endpoint path, relative to the version, e.g. /sites/12345 .
* @param string $request_method Request method used to access the endpoint path .
* @return string The current version, or otherwise the maximum version available
*/
public function get_closest_version_of_endpoint( $template_path, $path, $request_method = 'GET' ) {
$closest_endpoint_cache_by_version = & $this->closest_endpoint_cache_by_version;
$closest_endpoint_cache = & $closest_endpoint_cache_by_version[ $this->api->version ];
if ( ! $closest_endpoint_cache ) {
$closest_endpoint_cache_by_version[ $this->api->version ] = array();
$closest_endpoint_cache = & $closest_endpoint_cache_by_version[ $this->api->version ];
}
if ( ! isset( $closest_endpoint_cache[ $template_path ] ) ) {
$closest_endpoint_cache[ $template_path ] = array();
} elseif ( isset( $closest_endpoint_cache[ $template_path ][ $request_method ] ) ) {
return $closest_endpoint_cache[ $template_path ][ $request_method ];
}
$path = untrailingslashit( $path );
// /help is a special case - always use the current request version
if ( wp_endswith( $path, '/help' ) ) {
$closest_endpoint_cache[ $template_path ][ $request_method ] = $this->api->version;
return $this->api->version;
}
$matches_by_version = & $this->matches_by_version;
// try to match out of saved matches.
if ( ! isset( $matches_by_version[ $this->api->version ] ) ) {
$matches_by_version[ $this->api->version ] = array();
}
foreach ( $matches_by_version[ $this->api->version ] as $match ) {
$regex = $match->regex;
if ( preg_match( "#^$regex\$#", $path ) ) {
$closest_endpoint_cache[ $template_path ][ $request_method ] = $match->version;
return $match->version;
}
}
$endpoint_path_versions = $this->get_endpoint_path_versions();
$last_path_segment = $this->get_last_segment_of_relative_path( $path );
$max_version_found = null;
foreach ( $endpoint_path_versions as $endpoint_last_path_segment => $endpoints ) {
// Does the last part of the path match the path key? (e.g. 'posts')
// If the last part contains a placeholder (e.g. %s), we want to carry on.
// phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual
if ( $last_path_segment != $endpoint_last_path_segment && ! strstr( $endpoint_last_path_segment, '%' ) ) {
continue;
}
foreach ( $endpoints as $endpoint ) {
// Does the request method match?
if ( ! in_array( $request_method, $endpoint['request_methods'], true ) ) {
continue;
}
$endpoint_path = untrailingslashit( $endpoint['path'] );
$endpoint_path_regex = str_replace( array( '%s', '%d' ), array( '([^/?&]+)', '(\d+)' ), $endpoint_path );
if ( ! preg_match( "#^$endpoint_path_regex\$#", $path ) ) {
continue;
}
// Make sure the endpoint exists at the same version.
if ( null !== $this->api->version &&
version_compare( $this->api->version, $endpoint['min_version'], '>=' ) &&
version_compare( $this->api->version, $endpoint['max_version'], '<=' )
) {
array_push(
$matches_by_version[ $this->api->version ],
(object) array(
'version' => $this->api->version,
'regex' => $endpoint_path_regex,
)
);
$closest_endpoint_cache[ $template_path ][ $request_method ] = $this->api->version;
return $this->api->version;
}
// If the endpoint doesn't exist at the same version, record the max version we found.
if ( empty( $max_version_found ) || version_compare( $max_version_found['version'], $endpoint['max_version'], '<' ) ) {
$max_version_found = array(
'version' => $endpoint['max_version'],
'regex' => $endpoint_path_regex,
);
}
}
}
// If the endpoint version is less than the requested endpoint version, return the max version found.
if ( ! empty( $max_version_found ) ) {
array_push(
$matches_by_version[ $this->api->version ],
(object) $max_version_found
);
$closest_endpoint_cache[ $template_path ][ $request_method ] = $max_version_found['version'];
return $max_version_found['version'];
}
// Otherwise, use the API version of the current request.
return $this->api->version;
}
/**
* Get an array of endpoint paths with their associated versions
*
* @return array Array of endpoint paths, min_versions and max_versions, keyed by last segment of path
**/
protected function get_endpoint_path_versions() {
if ( ! empty( $this->cache_result ) ) {
return $this->cache_result;
}
/*
* Create a map of endpoints and their min/max versions keyed by the last segment of the path (e.g. 'posts')
* This reduces the search space when finding endpoint matches in get_closest_version_of_endpoint()
*/
$endpoint_path_versions = array();
foreach ( $this->api->endpoints as $key => $endpoint_objects ) {
// @todo As with the todo in class.json-api.php, we need to determine if anything depends on this being serialized and hence unserialized, rather than e.g. JSON.
// The key contains a serialized path, min_version and max_version.
list( $path, $min_version, $max_version ) = unserialize( $key ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize -- Legacy, see serialization at class.json-api.php.
// Grab the last component of the relative path to use as the top-level key.
$last_path_segment = $this->get_last_segment_of_relative_path( $path );
$endpoint_path_versions[ $last_path_segment ][] = array(
'path' => $path,
'min_version' => $min_version,
'max_version' => $max_version,
'request_methods' => array_keys( $endpoint_objects ),
);
}
$this->cache_result = $endpoint_path_versions;
return $endpoint_path_versions;
}
/**
* Grab the last segment of a relative path
*
* @param string $path Path.
* @return string Last path segment
*/
protected function get_last_segment_of_relative_path( $path ) {
$path_parts = array_filter( explode( '/', $path ) );
if ( empty( $path_parts ) ) {
return null;
}
return end( $path_parts );
}
}
@@ -0,0 +1,79 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* WPCOM_JSON_API_Metadata class - Utility classes that don't necessarily have a home yet.
*
* @package automattic/jetpack
*/
/**
* Base class for WPCOM_JSON_API_Metadata
*/
class WPCOM_JSON_API_Metadata {
/**
* Checks to see if a meta key is in the array of allowed public (and whitelisted) meta data.
*
* Additionally, if the key begins with 'geo_' or '_wpas_', true will also be returned.
*
* @param string $key A post metadata key value to check.
* @return bool True or false depending on whether the key meets the defined criteria.
**/
public static function is_public( $key ) {
if ( empty( $key ) ) {
return false;
}
// Default whitelisted meta keys.
$whitelisted_meta = array( '_thumbnail_id' );
// whitelist of metadata that can be accessed.
/** This filter is documented in json-endpoints/class.wpcom-json-api-post-endpoint.php */
if ( in_array( $key, apply_filters( 'rest_api_allowed_public_metadata', $whitelisted_meta ), true ) ) {
return true;
}
if ( str_starts_with( $key, 'geo_' ) ) {
return true;
}
if ( str_starts_with( $key, '_wpas_' ) ) {
return true;
}
return false;
}
/**
* Checks to see if a meta key should be used internally only.
*
* @param string $key A post metadata key value to check.
* @return bool True or false depending on whether the key meets the defined criteria.
**/
public static function is_internal_only( $key ) {
// We want to always return the `_jetpack_blogging_prompt_key` key in post responses if it is available.
if ( $key === '_jetpack_blogging_prompt_key' ) {
return false;
}
// We want to always return the `_jetpack_newsletter_access` key to
// display the correct newsletter access in Calypso.
$whitelist = array(
'_jetpack_newsletter_access',
'_jetpack_newsletter_tier_id',
'_jetpack_dont_email_post_to_subs',
);
if ( in_array( $key, $whitelist, true ) ) {
return false;
}
if ( str_starts_with( $key, '_jetpack_' ) ) {
return true;
}
if ( str_starts_with( $key, '_elasticsearch_' ) ) {
return true;
}
return false;
}
}
@@ -0,0 +1,38 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* WPORG_Platform class that extends SAL_Platform, returning a Jetpack_Site with a $blog_id and $token
*
* @package automattic/jetpack
*/
require_once __DIR__ . '/class.json-api-platform.php';
/**
* Base class for WPORG_Platform, which extends SAL_Platform
*/
class WPORG_Platform extends SAL_Platform {
/**
* Given a Jetpack blog ID, this function returns a Jetpack_Site instance
*
* @param int $blog_id A Jetpack blog ID.
* @return Jetpack_Site A Jetpack_Site instance including all relevant details needed to define a Jetpack site.
**/
public function get_site( $blog_id ) {
require_once __DIR__ . '/class.json-api-site-jetpack.php';
return new Jetpack_Site( $blog_id, $this );
}
}
// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
/**
* Given a token instance (with blog and user id related information), this function returns a new WPORG_Platform instance
*
* @param SAL_Token $token A token instance.
* @see class.json-api-token.php
* @return WPORG_Platform A WPORG_Platform instance including all relevant details needed to define a Jetpack site, as well as a token instance.
**/
function wpcom_get_sal_platform( $token ) {
return new WPORG_Platform( $token );
}
@@ -0,0 +1,49 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* SAL_Platform class which defines a token to later be associated with a Jetpack site
*
* @package automattic/jetpack
*/
require_once __DIR__ . '/class.json-api-token.php';
/**
* Base class for SAL_Platform
*/
abstract class SAL_Platform {
/**
* A token that will represent a SAL_Token instance, default is empty.
*
* @var SAL_Token
*/
public $token;
/**
* Contructs the SAL_Platform instance
*
* @param SAL_Token $token The variable which will store the SAL_Token instance.
*/
public function __construct( $token ) {
if ( is_array( $token ) ) {
$token = SAL_Token::from_rest_token( $token );
} else {
$token = SAL_Token::for_anonymous_user();
}
$this->token = $token;
}
/**
* This is the get_site function declaration, initially not implemented.
*
* @param int $blog_id The sites Jetpack blog ID.
* @see class.json-api-platform-jetpack.php for the implementation of this function.
*/
abstract public function get_site( $blog_id );
}
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
require_once dirname( WP_CONTENT_DIR ) . '/public.api/rest/sal/class.json-api-platform-wpcom.php';
} else {
require_once __DIR__ . '/class.json-api-platform-jetpack.php';
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,90 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* This class extends the SAL_Post class, providing the implementation for
* functions that were declared in that SAL_Post class.
*
* @see WPCOM_JSON_API_Post_v1_1_Endpoint in class.wpcom-json-api-post-v1-1-endpoint.php for more context on
* the functions implemented here.
*
* @package automattic/jetpack
*/
/**
* Base class for Jetpack_Post.
*/
class Jetpack_Post extends SAL_Post {
/**
* Defines a default value for the like counts on a post, if this hasn't been defined yet.
*
* @return int Returns 0.
**/
public function get_like_count() {
return 0;
}
/**
* Defines a default value for whether or not the current user likes this post, if this hasn't been defined yet.
*
* @return bool Returns false
**/
public function is_liked() {
return false;
}
/**
* Defines a default value for whether or not the current user reblogged this post, if this hasn't been defined yet.
*
* @return bool Returns false
**/
public function is_reblogged() {
return false;
}
/**
* Defines a default value for whether or not the current user is following this blog, if this hasn't been defined yet.
*
* @return bool Returns false
**/
public function is_following() {
return false;
}
/**
* Defines the unique WordPress.com-wide representation of a post, if this hasn't been defined yet.
*
* @return string Returns an empty string
**/
public function get_global_id() {
return '';
}
/**
* Defines a default value for whether or not there is gelocation data for this post, if this hasn't been defined yet.
*
* @return bool Returns false
**/
public function get_geo() {
return false;
}
/**
* Returns the avatar URL for a user, or an empty string if there isn't a valid avatar.
*
* @param string $email The user's email.
* @param int $avatar_size The size of the avatar in pixels.
*
* @return string
*/
protected function get_avatar_url( $email, $avatar_size = 96 ) {
$avatar_url = get_avatar_url(
$email,
array(
'size' => $avatar_size,
)
);
if ( ! $avatar_url || is_wp_error( $avatar_url ) ) {
return '';
}
return $avatar_url;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,343 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* This class extends the SAL_Site class, providing the implementation for
* functions that were declared in that SAL_Site class as well as defining
* base functions to be implemented in class Jetpack_Site.
*
* @see class.json-api-site-jetpack.php for more context on
* the functions extended here.
*
* @package automattic/jetpack
*/
require_once __DIR__ . '/class.json-api-site-base.php';
/**
* Base class for Abstract_Jetpack_Site.
*/
abstract class Abstract_Jetpack_Site extends SAL_Site {
/**
* Defining a base get_constant() function to be extended in the Jetpack_Site class.
*
* If a Jetpack constant name has been defined, this will return the value of the constant.
*
* @param string $name the name of the Jetpack constant to check.
*/
abstract protected function get_constant( $name );
/**
* Defining a base current_theme_supports() function to be extended in the Jetpack_Site class.
*
* Returns true if the current theme supports the $feature_name, false otherwise.
*
* @param string $feature_name the name of the Jetpack feature.
*/
abstract protected function current_theme_supports( $feature_name );
/**
* Defining a base get_theme_support() function to be extended in the Jetpack_Site class.
*
* Gets theme support arguments to be checked against the specific Jetpack feature.
*
* @param string $feature_name the name of the Jetpack feature to check against.
*/
abstract protected function get_theme_support( $feature_name );
/**
* Defining a base get_mock_option() function to be extended in the Jetpack_Site class.
*
* Retrieves a Jetpack option's value, given the option name.
*
* @param string $name the name of the Jetpack option, without the 'jetpack' prefix (eg. 'log' for 'jetpack_log').
*/
abstract protected function get_mock_option( $name );
/**
* Defining a base get_jetpack_version() function to be extended in the Jetpack_Site class.
*
* Returns the current Jetpack version number.
*/
abstract public function get_jetpack_version();
/**
* Defining a base get_updates() function to be extended in the Jetpack_Site class.
*
* Gets updates and then stores them in the jetpack_updates option, returning an array with the option schema.
*/
abstract public function get_updates();
/**
* Defining a base main_network_site() function to be extended in the Jetpack_Site class.
*
* Returns the site URL for the current network.
*/
abstract protected function main_network_site();
/**
* Defining a base wp_version() function to be extended in the Jetpack_Site class.
*
* Returns the WordPress version for the current site.
*/
abstract protected function wp_version();
/**
* Defining a base max_upload_size() function to be extended in the Jetpack_Site class.
*
* Returns the maximum upload size allowed in php.ini.
*/
abstract protected function max_upload_size();
/**
* Defining a base is_main_network() function to be extended in the Jetpack_Site class.
*
* Returns true if the site is within a system with a multiple networks, false otherwise.
*
* @see /projects/packages/status/src/class-status.php.
*/
abstract protected function is_main_network();
/**
* Defining a base is_version_controlled() function to be extended in the Jetpack_Site class.
*
* Returns true if is_vcs_checkout discovers a version control checkout, false otherwise.
*
* @see projects/packages/sync/src/class-functions.php.
*/
abstract protected function is_version_controlled();
/**
* Defining a base file_system_write_access() function to be extended in the Jetpack_Site class.
*
* Returns true if the site has file write access false otherwise.
*
* @see projects/packages/sync/src/class-functions.php.
*/
abstract protected function file_system_write_access();
/**
* Fetch a list of active plugins that are using Jetpack Connection.
*/
abstract protected function get_connection_active_plugins();
/**
* This function is implemented on WPCom sites, where a filter is removed which forces the URL to http.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-jetpack-shadow.php.
*/
public function before_render() {
}
/**
* This function returns the value of the 'WP_MEMORY_LIMIT' constant.
*
* @return int|string
*/
protected function wp_memory_limit() {
return $this->get_constant( 'WP_MEMORY_LIMIT' );
}
/**
* This function returns the value of the 'WP_MAX_MEMORY_LIMIT' constant.
*
* @return int|string
*/
protected function wp_max_memory_limit() {
return $this->get_constant( 'WP_MAX_MEMORY_LIMIT' );
}
/**
* If a user has manage options permissions and the site is the main site of the network, make updates visible.
*
* Called after response_keys have been rendered, which itself is used to return all the necessary information for a sites response.
*
* @param array $response an array of the response keys.
*/
public function after_render( &$response ) {
if ( current_user_can( 'manage_options' ) && $this->is_main_site( $response ) ) {
$jetpack_update = $this->get_updates();
if ( ! empty( $jetpack_update ) ) {
// In previous version of Jetpack 3.4, 3.5, 3.6 we synced the wp_version into to jetpack_updates.
unset( $jetpack_update['wp_version'] );
// In previous version of Jetpack 3.4, 3.5, 3.6 we synced the site_is_version_controlled into to jetpack_updates.
unset( $jetpack_update['site_is_version_controlled'] );
$response['updates'] = $jetpack_update;
}
}
}
/**
* Extends the Jetpack options array with details including site constraints, WordPress and Jetpack versions, and plugins using the Jetpack connection.
*
* @param array $options an array of the Jetpack options.
*/
public function after_render_options( &$options ) {
$options['jetpack_version'] = $this->get_jetpack_version();
$main_network_site = $this->main_network_site();
if ( $main_network_site ) {
$options['main_network_site'] = (string) rtrim( $main_network_site, '/' );
}
$active_modules = Jetpack_Options::get_option( 'active_modules' );
if ( is_array( $active_modules ) ) {
$options['active_modules'] = (array) array_values( $active_modules );
}
$options['software_version'] = (string) $this->wp_version();
$options['max_upload_size'] = $this->max_upload_size();
$options['wp_memory_limit'] = $this->wp_memory_limit();
$options['wp_max_memory_limit'] = $this->wp_max_memory_limit();
// Sites have to prove that they are not main_network site.
// If the sync happends right then we should be able to see that we are not dealing with a network site.
$options['is_multi_network'] = (bool) $this->is_main_network();
$options['is_multi_site'] = (bool) $this->is_multisite();
$file_mod_disabled_reasons = array_keys(
array_filter(
array(
'automatic_updater_disabled' => (bool) $this->get_constant( 'AUTOMATIC_UPDATER_DISABLED' ),
// WP AUTO UPDATE CORE defaults to minor, '1' if true and '0' if set to false.
'wp_auto_update_core_disabled' => ! ( (bool) $this->get_constant( 'WP_AUTO_UPDATE_CORE' ) ),
'is_version_controlled' => (bool) $this->is_version_controlled(),
// By default we assume that site does have system write access if the value is not set yet.
'has_no_file_system_write_access' => ! (bool) $this->file_system_write_access(),
'disallow_file_mods' => (bool) $this->get_constant( 'DISALLOW_FILE_MODS' ),
)
)
);
$options['file_mod_disabled'] = empty( $file_mod_disabled_reasons ) ? false : $file_mod_disabled_reasons;
$options['jetpack_connection_active_plugins'] = $this->get_connection_active_plugins();
}
/**
* This function returns the values of any active Jetpack modules.
*
* @return array
*/
public function get_jetpack_modules() {
return array_values( Jetpack_Options::get_option( 'active_modules', array() ) );
}
/**
* This function returns true if a specified Jetpack module is active, false otherwise.
*
* @param string $module The Jetpack module name to check.
*
* @return bool
*/
public function is_module_active( $module ) {
return in_array( $module, Jetpack_Options::get_option( 'active_modules', array() ), true );
}
/**
* This function returns false for a check as to whether a site is a VIP site or not.
*
* @return bool Always returns false.
*/
public function is_vip() {
return false; // this may change for VIP Go sites, which sync using Jetpack.
}
/**
* If the site's current theme supports post thumbnails, return true (otherwise return false).
*
* @return bool
*/
public function featured_images_enabled() {
return $this->current_theme_supports( 'post-thumbnails' );
}
/**
* Returns an array of supported post formats.
*
* @return array
*/
public function get_post_formats() {
// deprecated - see separate endpoint. get a list of supported post formats.
$all_formats = get_post_format_strings();
$supported = $this->get_theme_support( 'post-formats' );
$supported_formats = array();
if ( isset( $supported[0] ) ) {
foreach ( $supported[0] as $format ) {
$supported_formats[ $format ] = $all_formats[ $format ];
}
}
return $supported_formats;
}
/**
* Returns an array with site icon details.
*
* @return array
*/
public function get_icon() {
$icon_id = get_option( 'site_icon' );
if ( empty( $icon_id ) ) {
$icon_id = Jetpack_Options::get_option( 'site_icon_id' );
}
if ( empty( $icon_id ) ) {
return null;
}
$icon = array_filter(
array(
'img' => wp_get_attachment_image_url( $icon_id, 'full' ),
'ico' => wp_get_attachment_image_url( $icon_id, array( 16, 16 ) ),
)
);
if ( empty( $icon ) ) {
return null;
}
if ( current_user_can( 'edit_posts', $icon_id ) ) {
$icon['media_id'] = (int) $icon_id;
}
return $icon;
}
/**
* Private methods
**/
/**
* This function returns true if the current site is the main network site, false otherwise.
*
* @param array $response The array of Jetpack response keys.
*
* @return bool
*/
private function is_main_site( $response ) {
if ( isset( $response['options']->main_network_site ) && isset( $response['options']->unmapped_url ) ) {
$main_network_site_url = set_url_scheme( $response['options']->main_network_site, 'http' );
$unmapped_url = set_url_scheme( $response['options']->unmapped_url, 'http' );
if ( $unmapped_url === $main_network_site_url ) {
return true;
}
}
return false;
}
/**
* For Jetpack sites this will always return false.
*
* This is extended for WordPress.com sites in wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @param int $post_id The post id.
*
* @return bool
*/
protected function is_a8c_publication( $post_id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Extended and used in WordPress.com.
return false;
}
}
@@ -0,0 +1,734 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* This class extends the Abstract_Jetpack_Site class, which includes providing
* the implementation for functions that were declared in that class.
*
* @see class.json-api-site-jetpack-base.php for more context on some of
* the functions extended here.
*
* @package automattic/jetpack
*/
use Automattic\Jetpack\Status\Host;
use Automattic\Jetpack\Sync\Functions;
require_once __DIR__ . '/class.json-api-site-jetpack-base.php';
require_once __DIR__ . '/class.json-api-post-jetpack.php';
/**
* Base class for Jetpack_Site. This code runs on Jetpack (.org) sites.
*/
class Jetpack_Site extends Abstract_Jetpack_Site {
/**
* Retrieves a Jetpack option's value, given the option name.
*
* @param string $name the name of the Jetpack option, without the 'jetpack' prefix (eg. 'log' for 'jetpack_log').
*
* @return mixed
*/
protected function get_mock_option( $name ) {
return get_option( 'jetpack_' . $name );
}
/**
* If a Jetpack constant name has been defined, this will return the value of the constant.
*
* @param string $name the name of the Jetpack constant to check.
*
* @return mixed
*/
protected function get_constant( $name ) {
if ( defined( $name ) ) {
return constant( $name );
}
return null;
}
/**
* Returns the site URL for the current network.
*
* @return string
*/
protected function main_network_site() {
return network_site_url();
}
/**
* Returns the WordPress version for the current site.
*
* @return string
*/
protected function wp_version() {
global $wp_version;
return $wp_version;
}
/**
* Returns the maximum upload size allowed in php.ini.
*
* @return int
*/
protected function max_upload_size() {
return wp_max_upload_size();
}
/**
* This function returns the value of the 'WP_MEMORY_LIMIT' constant converted to an integer byte value.
*
* @return int
*/
protected function wp_memory_limit() {
return wp_convert_hr_to_bytes( WP_MEMORY_LIMIT );
}
/**
* This function returns the value of the 'WP_MAX_MEMORY_LIMIT' constant converted to an integer byte value.
*
* @return int
*/
protected function wp_max_memory_limit() {
return wp_convert_hr_to_bytes( WP_MAX_MEMORY_LIMIT );
}
/**
* Returns true if the site is within a system with a multiple networks, false otherwise.
*
* @see /projects/packages/status/src/class-status.php
*
* @return bool
*/
protected function is_main_network() {
return Jetpack::is_multi_network();
}
/**
* Returns true if Multisite is enabled, false otherwise.
*
* @return bool
*/
public function is_multisite() {
return (bool) is_multisite();
}
/**
* Returns true if the current site is a single user site, false otherwise.
*
* @return bool
*/
public function is_single_user_site() {
return (bool) Jetpack::is_single_user_site();
}
/**
* Returns true if is_vcs_checkout discovers a version control checkout, false otherwise.
*
* @see projects/packages/sync/src/class-functions.php.
*
* @return bool
*/
protected function is_version_controlled() {
return Functions::is_version_controlled();
}
/**
* Returns true if the site has file write access, false otherwise.
*
* @see projects/packages/sync/src/class-functions.php.
*
* @return bool
*/
protected function file_system_write_access() {
return Functions::file_system_write_access();
}
/**
* Returns true if the current theme supports the $feature_name, false otherwise.
*
* @param string $feature_name the name of the Jetpack feature.
*
* @return bool
*/
protected function current_theme_supports( $feature_name ) {
return current_theme_supports( $feature_name );
}
/**
* Gets theme support arguments to be checked against the specific Jetpack feature.
*
* @param string $feature_name the name of the Jetpack feature to check against.
*
* @return array
*/
protected function get_theme_support( $feature_name ) {
return get_theme_support( $feature_name );
}
/**
* Fetch a list of active plugins that are using Jetpack Connection.
*
* @return array An array of active plugins (by slug) that are using Jetpack Connection.
*/
protected function get_connection_active_plugins() {
$plugins = $this->get_mock_option( 'connection_active_plugins' );
return is_array( $plugins ) ? array_keys( $plugins ) : array();
}
/**
* Gets updates and then stores them in the jetpack_updates option, returning an array with the option schema.
*
* @return array
*/
public function get_updates() {
return (array) Jetpack::get_updates();
}
/**
* Returns the Jetpack blog ID for a site.
*
* @return int
*/
public function get_id() {
return $this->platform->token->blog_id;
}
/**
* Returns true if a site has the 'videopress' option enabled, false otherwise.
*
* @return bool
*/
public function has_videopress() {
// TODO - this only works on wporg site - need to detect videopress option for remote Jetpack site on WPCOM.
$videopress = Jetpack_Options::get_option( 'videopress', array() );
if ( isset( $videopress['blog_id'] ) && $videopress['blog_id'] > 0 ) {
return true;
}
return false;
}
/**
* Returns VideoPress storage used, in MB.
*
* @see class.json-api-site-jetpack-shadow.php on WordPress.com for implementation. Only applicable on WordPress.com.
*
* @return float
*/
public function get_videopress_storage_used() {
return 0;
}
/**
* Sets the upgraded_filetypes_enabled Jetpack option to true as a default.
*
* Only relevant for WordPress.com sites:
* See wpcom_site_has_upgraded_upload_filetypes at /wpcom/wp-content/mu-plugins/misc.php.
*
* @return bool
*/
public function upgraded_filetypes_enabled() {
return true;
}
/**
* Sets the is_mapped_domain Jetpack option to true as a default.
*
* Primarily used in WordPress.com to confirm the current blog's domain does or doesn't match the primary redirect.
*
* @see /wpcom/wp-content/mu-plugins/insecure-content-helpers.php within WordPress.com.
*
* @return bool
*/
public function is_mapped_domain() {
return true;
}
/**
* Fallback to the home URL since all Jetpack sites don't have an unmapped *.wordpress.com domain.
*
* @return string
*/
public function get_unmapped_url() {
// Fallback to the home URL since all Jetpack sites don't have an unmapped *.wordpress.com domain.
return $this->get_url();
}
/**
* Whether the domain is a site redirect or not. Defaults to false on a Jetpack site.
*
* Primarily used in WordPress.com where it is determined if a HTTP status check is a redirect or not and whether an exception should be thrown.
*
* @see /wpcom/wp-includes/Requests/Response.php within WordPress.com.
*
* @return bool
*/
public function is_redirect() {
return false;
}
/**
* Whether or not the current user is following this blog. Defaults to false.
*
* @return bool
*/
public function is_following() {
return false;
}
/**
* Points to the user ID of the site owner
*
* @return null for Jetpack sites
*/
public function get_site_owner() {
return null;
}
/**
* Whether or not the Jetpack 'wordads' module is active on the site.
*
* @return bool
*/
public function has_wordads() {
return Jetpack::is_module_active( 'wordads' );
}
/**
* Defaults to false on Jetpack sites, however is used on WordPress.com sites. This nonce is used for previews on Jetpack sites.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-jetpack-shadow.php.
*
* @return bool
*/
public function get_frame_nonce() {
return false;
}
/**
* Defaults to false on Jetpack sites, however is used on WordPress.com sites,
* where it creates a nonce to be used with iframed block editor requests to a Jetpack site.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-jetpack-shadow.php.
*
* @return bool
*/
public function get_jetpack_frame_nonce() {
return false;
}
/**
* Defaults to false on Jetpack sites, however is used on WordPress.com sites, where it returns true if the headstart-fresh blog sticker is present.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return bool
*/
public function is_headstart_fresh() {
return false;
}
/**
* Returns the allowed mime types and file extensions for a site.
*
* @return array
*/
public function allowed_file_types() {
$allowed_file_types = array();
// https://codex.wordpress.org/Uploading_Files.
$mime_types = get_allowed_mime_types();
foreach ( $mime_types as $type => $mime_type ) {
$extras = explode( '|', $type );
foreach ( $extras as $extra ) {
$allowed_file_types[] = $extra;
}
}
return $allowed_file_types;
}
/**
* Return site's privacy status.
*
* @return bool Is site private?
*/
public function is_private() {
return (int) $this->get_atomic_cloud_site_option( 'blog_public' ) === -1;
}
/**
* Return site's coming soon status.
*
* @return bool Is site "Coming soon"?
*/
public function is_coming_soon() {
return $this->is_private() && (int) $this->get_atomic_cloud_site_option( 'wpcom_coming_soon' ) === 1;
}
/**
* Return site's launch status.
*
* @return string|bool Launch status ('launched', 'unlaunched', or false).
*/
public function get_launch_status() {
return $this->get_atomic_cloud_site_option( 'launch-status' );
}
/**
* Given an option name, returns false if the site isn't WoA or doesn't have the ability to retrieve cloud site options.
* Otherwise, if the option name exists amongst Jetpack options, the option value is returned.
*
* @param string $option The option name to check.
*
* @return string|bool
*/
public function get_atomic_cloud_site_option( $option ) {
if ( ! ( new Host() )->is_woa_site() ) {
return false;
}
$jetpack = Jetpack::init();
if ( ! method_exists( $jetpack, 'get_cloud_site_options' ) ) {
return false;
}
$result = $jetpack->get_cloud_site_options( array( $option ) );
if ( ! array_key_exists( $option, $result ) ) {
return false;
}
return $result[ $option ];
}
/**
* Defaults to false instead of returning the current site plan.
*
* @return bool
*/
public function get_plan() {
return false;
}
/**
* Defaults to 0 for the number of WordPress.com subscribers - this is filled in on the WordPress.com side.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return int
*/
public function get_subscribers_count() {
return 0;
}
/**
* Defaults to false - this is filled on the WordPress.com side in multiple locations.
*
* @see WPCOM_JSON_API_GET_Site_Endpoint::decorate_jetpack_response.
* @return bool
*/
public function get_capabilities() {
return false;
}
/**
* Returns the language code for the current site.
*
* @return string
*/
public function get_locale() {
return get_bloginfo( 'language' );
}
/**
* The flag indicates that the site has Jetpack installed.
*
* @return bool
*/
public function is_jetpack() {
return true;
}
/**
* The flag indicates that the site is connected to WP.com via Jetpack Connection.
*
* @return bool
*/
public function is_jetpack_connection() {
return true;
}
/**
* Returns the current site's Jetpack version.
*
* @return string
*/
public function get_jetpack_version() {
return JETPACK__VERSION;
}
/**
* Empty function declaration - this function is filled out on the WordPress.com side, returning true if the site has an AK / VP bundle.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-jetpack-shadow.php.
*/
public function get_ak_vp_bundle_enabled() {}
/**
* Returns the front page meta description for current site.
*
* @see /modules/seo-tools/class-jetpack-seo-utils.php.
*
* @return string
*/
public function get_jetpack_seo_front_page_description() {
return Jetpack_SEO_Utils::get_front_page_meta_description();
}
/**
* Returns custom title formats from site option.
*
* @see /modules/seo-tools/class-jetpack-seo-titles.php.
*
* @return array
*/
public function get_jetpack_seo_title_formats() {
return Jetpack_SEO_Titles::get_custom_title_formats();
}
/**
* Returns website verification codes. Allowed keys include: google, pinterest, bing, yandex, facebook.
*
* @see /modules/verification-tools/blog-verification-tools.php.
*
* @return array
*/
public function get_verification_services_codes() {
return get_option( 'verification_services_codes', null );
}
/**
* Returns null for Jetpack sites. For WordPress.com sites this returns the value of the 'podcasting_archive' option.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-wpcom.php.
*
* @return null
*/
public function get_podcasting_archive() {
return null;
}
/**
* Defaulting to true, this function is expanded out on the WordPress.com side, returning an error if the site is not connected or not communicating to us.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-jetpack-shadow.php.
*
* @return bool
*/
public function is_connected_site() {
return true;
}
/**
* Defaulting to false and not relevant for Jetpack sites, this is expanded on the WordPress.com side for a specific wp.com/start 'WP for teams' flow.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-wpcom.php.
*
* @return bool
*/
public function is_wpforteams_site() {
return false;
}
/**
* Returns true if a user has got the capability that is being checked, false otherwise.
*
* @param string $role The capability to check.
*
* @return bool
*/
public function current_user_can( $role ) {
return current_user_can( $role );
}
/**
* Check if full site editing should be considered as currently active. Full site editing
* requires the FSE plugin to be installed and activated, as well the current
* theme to be FSE compatible. The plugin can also be explicitly disabled via the
* a8c_disable_full_site_editing filter.
*
* @since 7.7.0
*
* @return bool true if full site editing is currently active.
*/
public function is_fse_active() {
if ( ! Jetpack::is_plugin_active( 'full-site-editing/full-site-editing-plugin.php' ) ) {
return false;
}
if ( function_exists( '\Automattic\Jetpack\Jetpack_Mu_Wpcom\Wpcom_Legacy_FSE\is_full_site_editing_active' ) ) {
// @phan-suppress-next-line PhanUndeclaredFunction
return \Automattic\Jetpack\Jetpack_Mu_Wpcom\Wpcom_Legacy_FSE\is_full_site_editing_active();
}
return function_exists( '\A8C\FSE\is_full_site_editing_active' ) && \A8C\FSE\is_full_site_editing_active();
}
/**
* Check if site should be considered as eligible for full site editing. Full site editing
* requires the FSE plugin to be installed and activated. For this method to return true
* the current theme does not need to be FSE compatible. The plugin can also be explicitly
* disabled via the a8c_disable_full_site_editing filter.
*
* @since 8.1.0
*
* @return bool true if site is eligible for full site editing
*/
public function is_fse_eligible() {
if ( ! Jetpack::is_plugin_active( 'full-site-editing/full-site-editing-plugin.php' ) ) {
return false;
}
if ( function_exists( '\Automattic\Jetpack\Jetpack_Mu_Wpcom\Wpcom_Legacy_FSE\is_site_eligible_for_full_site_editing' ) ) {
// @phan-suppress-next-line PhanUndeclaredFunction
return \Automattic\Jetpack\Jetpack_Mu_Wpcom\Wpcom_Legacy_FSE\is_site_eligible_for_full_site_editing();
}
return function_exists( '\A8C\FSE\is_site_eligible_for_full_site_editing' ) && \A8C\FSE\is_site_eligible_for_full_site_editing();
}
/**
* Check if site should be considered as eligible for use of the core Site Editor.
* The Site Editor requires a block based theme to be active.
*
* @since 12.2 Uses wp_is_block_theme() to determine if site is eligible instead of gutenberg_is_fse_theme().
* @return bool true if site is eligible for the Site Editor
*/
public function is_core_site_editor_enabled() {
return wp_is_block_theme();
}
/**
* Return the last engine used for an import on the site. Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/class.json-api-site-wpcom.php.
*
* @return null
*/
public function get_import_engine() {
return null;
}
/**
* Post functions
*/
/**
* Wrap a WP_Post object with SAL methods, returning a Jetpack_Post object.
*
* @param WP_Post $post A WP_Post object.
* @param string $context The post request context (for example 'edit' or 'display').
*
* @return Jetpack_Post
*/
public function wrap_post( $post, $context ) {
return new Jetpack_Post( $this, $post, $context );
}
/**
* Get the option storing the Anchor podcast ID that identifies a site as a podcasting site.
*
* @return string
*/
public function get_anchor_podcast() {
return $this->get_atomic_cloud_site_option( 'anchor_podcast' );
}
/**
* Get user interactions with a site. Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return null
*/
public function get_user_interactions() {
return null;
}
/**
* Get site deleted status. Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return bool
*/
public function is_deleted() {
return false;
}
/**
* Indicates that a site is an A4A client. Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return bool
*/
public function is_a4a_client() {
return false;
}
/**
* Detect whether a site is WordPress.com Staging Site. Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return false
*/
public function is_wpcom_staging_site() {
return false;
}
/**
* Get site option for the production blog id (if is a WP.com Staging Site). Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return null
*/
public function get_wpcom_production_blog_id() {
return null;
}
/**
* Get site option for the staging blog ids (if it has them). Not used in Jetpack.
*
* @see /wpcom/public.api/rest/sal/trait.json-api-site-wpcom.php.
*
* @return null
*/
public function get_wpcom_staging_blog_ids() {
return null;
}
/**
* Get site option for the admin interface on WordPress.com Atomic sites. Not used in Jetpack.
*
* @return null
*/
public function get_wpcom_admin_interface() {
return null;
}
/**
* Get Zendesk site meta. Not used in Jetpack.
*
* @return null
*/
public function get_zendesk_site_meta() {
return null;
}
/**
* Detect whether there's a pending plan for this site. Not used in Jetpack.
*
* @return false
*/
public function is_pending_plan() {
return false;
}
}
@@ -0,0 +1,135 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* SAL_Token class
*
* @package automattic/jetpack
*/
/**
* Base class for Jetpack_Site, so that we have a real class instead of just passing around an array.
*/
class SAL_Token {
/**
* The Jetpack blog ID for the site.
*
* @var int
*/
public $blog_id;
/**
* The Jetpack user's user ID.
*
* @var int
*/
public $user_id;
/**
* The scope for the token, for example global or auth.
*
* @var string
*/
public $scope;
/**
* The Client ID (or WordPress.com Blog ID of this site.
*
* @var int
*/
public $client_id;
/**
* The user ID on the local site.
*
* @var int
*/
public $external_user_id;
/**
* Used for tokens created by Oauth clients.
*
* @var string
*/
public $external_user_code;
/**
* The type of authorization based on where the Jetpack connection is made - eg 'calypso', 'jetpack', 'client'.
*
* @var string
*/
public $auth_type;
/**
* Contructs the SAL_Token instance.
*
* @param int $blog_id The Jetpack blog ID for the site.
* @param int $user_id The Jetpack user's user ID.
* @param string $scope The scope for the token, for example global or auth.
* @param int $client_id The Client ID (or WordPress.com Blog ID of this site.
* @param int $external_user_id The user ID on the local site.
* @param string $external_user_code Used for tokens created by Oauth clients.
* @param string $auth_type The type of authorization based on where the Jetpack connection is made (eg. calypso).
*/
public function __construct( $blog_id, $user_id, $scope, $client_id, $external_user_id, $external_user_code, $auth_type ) {
$this->blog_id = $blog_id; // if blog_id is set and scope is not global, limit to that blog.
$this->user_id = $user_id;
$this->client_id = $client_id;
$this->scope = $scope;
$this->external_user_id = $external_user_id;
$this->external_user_code = $external_user_code;
$this->auth_type = $auth_type;
}
/**
* Checks if the scope is 'global'.
*
* @return bool
*/
public function is_global() {
return $this->scope === 'global';
}
/**
* This function is used to create a SAL_Token instance with only a user id, if a token doesn't already exist.
*
* @return SAL_Token
*/
public static function for_anonymous_user() {
return new SAL_Token(
null,
get_current_user_id(),
null, // there's only ever one scope in our current API implementation, auth or global.
null,
null,
null,
null
);
}
/**
* If a user token exists, the information is used to construct a SAL_Token with the correct parameters.
*
* @param array $token An array of details relevant to the connected user (may be empty).
*
* @return SAL_Token
*/
public static function from_rest_token( $token ) {
$user_id = isset( $token['user_id'] ) ? $token['user_id'] : get_current_user_id();
$scope = isset( $token['scope'][0] ) ? $token['scope'][0] : null;
$client_id = isset( $token['client_id'] ) ? $token['client_id'] : null;
$external_user_id = isset( $token['external_user_id'] ) ? $token['external_user_id'] : null;
$external_user_code = isset( $token['external_user_code'] ) ? $token['external_user_code'] : null;
$auth = isset( $token['auth'] ) ? $token['auth'] : null;
$blog_id = isset( $token['blog_id'] ) ? $token['blog_id'] : null;
return new SAL_Token(
$blog_id,
$user_id,
$scope, // there's only ever one scope in our current API implementation, auth or global.
$client_id,
$external_user_id,
$external_user_code,
$auth
);
}
}