initial
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('jetpack-script-data', 'jetpack-shared-stores', 'react', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => 'b907ec4aa61463228272');
|
||||
@@ -0,0 +1 @@
|
||||
.block-editor-block-list__layout .block-editor-block-list__block.has-warning.is-interactive>*{pointer-events:auto;user-select:auto}.block-editor-block-list__layout .block-editor-block-list__block.has-warning.is-interactive:after{content:none}.blaze-panel .blaze-panel-outbound-link__external_icon{fill:currentColor;height:1.4em;margin-left:.1em;vertical-align:middle;width:1.4em}.blaze-panel .components-panel__body-toggle svg{margin:0 0 0 .5em}.blaze-panel .post-publish-panel__postpublish-buttons .components-button{padding-bottom:.4em;padding-top:.5em}.blaze-panel p{margin-top:0}
|
||||
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
.block-editor-block-list__layout .block-editor-block-list__block.has-warning.is-interactive>*{pointer-events:auto;user-select:auto}.block-editor-block-list__layout .block-editor-block-list__block.has-warning.is-interactive:after{content:none}.blaze-panel .blaze-panel-outbound-link__external_icon{fill:currentColor;height:1.4em;margin-right:.1em;vertical-align:middle;width:1.4em}.blaze-panel .components-panel__body-toggle svg{margin:0 .5em 0 0}.blaze-panel .post-publish-panel__postpublish-buttons .components-button{padding-bottom:.4em;padding-top:.5em}.blaze-panel p{margin-top:0}
|
||||
+558
@@ -0,0 +1,558 @@
|
||||
<?php
|
||||
/**
|
||||
* Attract high-quality traffic to your site.
|
||||
*
|
||||
* @package automattic/jetpack-blaze
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack;
|
||||
|
||||
use Automattic\Jetpack\Blaze\Dashboard as Blaze_Dashboard;
|
||||
use Automattic\Jetpack\Blaze\Dashboard_REST_Controller as Blaze_Dashboard_REST_Controller;
|
||||
use Automattic\Jetpack\Blaze\REST_Controller;
|
||||
use Automattic\Jetpack\Connection\Client;
|
||||
use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
|
||||
use Automattic\Jetpack\Connection\Manager as Jetpack_Connection;
|
||||
use Automattic\Jetpack\Status as Jetpack_Status;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
use Automattic\Jetpack\Sync\Settings as Sync_Settings;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Class for promoting posts.
|
||||
*/
|
||||
class Blaze {
|
||||
/**
|
||||
* Script handle for the JS file we enqueue in the post editor.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SCRIPT_HANDLE = 'jetpack-promote-editor';
|
||||
|
||||
/**
|
||||
* Transient prefix for active campaign status checks.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_PREFIX = 'jetpack_blaze_active_campaigns_status_';
|
||||
|
||||
/**
|
||||
* Transient TTL for active campaign status checks that find campaigns.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_TTL = HOUR_IN_SECONDS;
|
||||
|
||||
/**
|
||||
* Transient TTL for active campaign status checks that cannot determine campaign status.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const UNKNOWN_ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_TTL = 5 * MINUTE_IN_SECONDS;
|
||||
|
||||
/**
|
||||
* Minimum campaign statuses that should trigger a warning.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
const ACTIVE_CAMPAIGN_STATUSES = array( 'active' );
|
||||
|
||||
/**
|
||||
* Path of the JS file we enqueue in the post editor.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $script_path = '../build/editor.js';
|
||||
|
||||
/**
|
||||
* Initializer.
|
||||
* Used to configure the blaze package, eg when called via the Config package.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init() {
|
||||
// On the edit screen, add a row action to promote the post.
|
||||
add_action( 'load-edit.php', array( __CLASS__, 'add_post_links_actions' ) );
|
||||
// After the quick-edit screen is processed, ensure the blaze row action is still present
|
||||
if ( 'edit.php' === $GLOBALS['pagenow'] ||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is not needed here, we're not saving anything.
|
||||
( 'admin-ajax.php' === $GLOBALS['pagenow'] && ! empty( $_POST['post_view'] ) && 'list' === $_POST['post_view'] && ! empty( $_POST['action'] ) && 'inline-save' === $_POST['action'] ) ) {
|
||||
self::add_post_links_actions();
|
||||
}
|
||||
// In the post editor, add a post-publish panel to allow promoting the post.
|
||||
add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'enqueue_block_editor_assets' ) );
|
||||
// Add a Blaze Menu.
|
||||
add_action( 'admin_menu', array( __CLASS__, 'enable_blaze_menu' ), 999 );
|
||||
// Add Blaze dashboard app REST API endpoints.
|
||||
add_action( 'rest_api_init', array( Blaze_Dashboard_REST_Controller::class, 'register' ) );
|
||||
// Add general Blaze REST API endpoints.
|
||||
add_action( 'rest_api_init', array( REST_Controller::class, 'register' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add links under each published post in the wp-admin post list.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_post_links_actions() {
|
||||
if ( self::should_initialize()['can_init'] ) {
|
||||
add_filter( 'post_row_actions', array( __CLASS__, 'jetpack_blaze_row_action' ), 10, 2 );
|
||||
add_filter( 'page_row_actions', array( __CLASS__, 'jetpack_blaze_row_action' ), 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the wp-admin Dashboard enabled?
|
||||
* That dashboard is not available or necessary on WordPress.com sites when the nav redesign is disabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_dashboard_enabled() {
|
||||
$is_dashboard_enabled = true;
|
||||
|
||||
// On WordPress.com sites, the dashboard is not needed if the nav redesign is not enabled.
|
||||
if ( get_option( 'wpcom_admin_interface' ) !== 'wp-admin' && ( new Host() )->is_wpcom_platform() ) {
|
||||
$is_dashboard_enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a wp-admin dashboard for Blaze campaign management.
|
||||
*
|
||||
* @since 0.7.0
|
||||
*
|
||||
* @param bool $should_enable Should the dashboard be enabled?
|
||||
*/
|
||||
return apply_filters( 'jetpack_blaze_dashboard_enable', $is_dashboard_enabled );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the Blaze menu.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function enable_blaze_menu() {
|
||||
if ( ! self::should_initialize()['can_init'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$blaze_dashboard = new Blaze_Dashboard();
|
||||
|
||||
if ( self::is_dashboard_enabled() ) {
|
||||
$page_suffix = add_submenu_page(
|
||||
'tools.php',
|
||||
esc_attr__( 'Advertising', 'jetpack-blaze' ),
|
||||
__( 'Advertising', 'jetpack-blaze' ),
|
||||
'manage_options',
|
||||
'advertising',
|
||||
array( $blaze_dashboard, 'render' ),
|
||||
1
|
||||
);
|
||||
add_action( 'load-' . $page_suffix, array( $blaze_dashboard, 'admin_init' ) );
|
||||
} elseif ( ( new Host() )->is_wpcom_platform() ) {
|
||||
$domain = ( new Jetpack_Status() )->get_site_suffix();
|
||||
$page_suffix = add_submenu_page(
|
||||
'tools.php',
|
||||
esc_attr__( 'Advertising', 'jetpack-blaze' ),
|
||||
__( 'Advertising', 'jetpack-blaze' ),
|
||||
'manage_options',
|
||||
'https://wordpress.com/advertising/' . $domain,
|
||||
null, // @phan-suppress-current-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539
|
||||
1
|
||||
);
|
||||
add_action( 'load-' . $page_suffix, array( $blaze_dashboard, 'admin_init' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the WordPress.com REST API
|
||||
* to ensure that the site supports the Blaze feature.
|
||||
*
|
||||
* - If the site is on WordPress.com Simple, we do not query the API.
|
||||
* - Results are cached for a day after getting response from API.
|
||||
* - If the API returns an error, we cache the result for an hour.
|
||||
*
|
||||
* @param int $blog_id The blog ID to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function site_supports_blaze( $blog_id ) {
|
||||
$transient_name = 'jetpack_blaze_site_supports_blaze_' . $blog_id;
|
||||
|
||||
/*
|
||||
* On WordPress.com, we don't need to make an API request,
|
||||
* we can query directly.
|
||||
*/
|
||||
if ( defined( 'IS_WPCOM' ) && IS_WPCOM && function_exists( 'blaze_is_site_eligible' ) ) {
|
||||
return blaze_is_site_eligible( $blog_id );
|
||||
}
|
||||
|
||||
$cached_result = get_transient( $transient_name );
|
||||
if ( false !== $cached_result ) {
|
||||
if ( is_array( $cached_result ) ) {
|
||||
return $cached_result['approved'];
|
||||
}
|
||||
|
||||
return (bool) $cached_result;
|
||||
}
|
||||
|
||||
// Make the API request.
|
||||
$url = sprintf( '/sites/%d/blaze/status', $blog_id );
|
||||
$response = Client::wpcom_json_api_request_as_blog(
|
||||
$url,
|
||||
'2',
|
||||
array( 'method' => 'GET' ),
|
||||
null,
|
||||
'wpcom'
|
||||
);
|
||||
|
||||
// If there was an error or malformed response, bail and save response for an hour.
|
||||
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
set_transient( $transient_name, array( 'approved' => false ), HOUR_IN_SECONDS );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the results.
|
||||
$result = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
|
||||
// Bail if there were no results returned.
|
||||
if ( ! is_array( $result ) || ! isset( $result['approved'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache the result for 24 hours.
|
||||
set_transient( $transient_name, array( 'approved' => (bool) $result['approved'] ), DAY_IN_SECONDS );
|
||||
|
||||
return (bool) $result['approved'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active campaign status for a site.
|
||||
*
|
||||
* @param int $blog_id The blog ID to check.
|
||||
*
|
||||
* @return array Active campaign status.
|
||||
*/
|
||||
public static function get_active_campaigns_status( $blog_id ) {
|
||||
$blog_id = absint( $blog_id );
|
||||
|
||||
if ( empty( $blog_id ) ) {
|
||||
return self::get_unknown_active_campaigns_status();
|
||||
}
|
||||
|
||||
$transient_name = self::ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_PREFIX . $blog_id;
|
||||
$cached_result = get_transient( $transient_name );
|
||||
|
||||
if ( false !== $cached_result ) {
|
||||
return $cached_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the campaign statuses that should trigger the active campaign warning.
|
||||
*
|
||||
* @since 0.27.23
|
||||
*
|
||||
* @param string[] $statuses Campaign statuses to check.
|
||||
* @param int $blog_id The blog ID being checked.
|
||||
*/
|
||||
$statuses = apply_filters( 'jetpack_blaze_active_campaign_statuses', self::ACTIVE_CAMPAIGN_STATUSES, $blog_id );
|
||||
$statuses = array_filter( array_map( 'sanitize_key', (array) $statuses ) );
|
||||
|
||||
if ( empty( $statuses ) ) {
|
||||
$statuses = self::ACTIVE_CAMPAIGN_STATUSES;
|
||||
}
|
||||
|
||||
$url = add_query_arg(
|
||||
array(
|
||||
'status' => implode( ',', $statuses ),
|
||||
'limit' => 1,
|
||||
),
|
||||
sprintf( '/sites/%d/wordads/dsp/api/v1/search/campaigns/site/%d', $blog_id, $blog_id )
|
||||
);
|
||||
|
||||
$response = Client::wpcom_json_api_request_as_user(
|
||||
$url,
|
||||
'2',
|
||||
array( 'method' => 'GET' ),
|
||||
null,
|
||||
'wpcom'
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
return self::get_unknown_active_campaigns_status( $transient_name );
|
||||
}
|
||||
|
||||
$result = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
|
||||
if ( ! is_array( $result ) || ! isset( $result['campaigns'] ) || ! is_array( $result['campaigns'] ) ) {
|
||||
return self::get_unknown_active_campaigns_status( $transient_name );
|
||||
}
|
||||
|
||||
$has_active_campaigns = ! empty( $result['campaigns'] );
|
||||
$status = array(
|
||||
'has_active_campaigns' => $has_active_campaigns,
|
||||
'status' => $has_active_campaigns ? 'active' : 'none',
|
||||
);
|
||||
|
||||
if ( $has_active_campaigns ) {
|
||||
set_transient( $transient_name, $status, self::ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_TTL );
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unknown active campaign status response.
|
||||
*
|
||||
* @param string|null $transient_name Optional transient name used to cache the unknown status.
|
||||
* @return array Unknown active campaign status.
|
||||
*/
|
||||
private static function get_unknown_active_campaigns_status( $transient_name = null ) {
|
||||
$status = array(
|
||||
'has_active_campaigns' => false,
|
||||
'status' => 'unknown',
|
||||
);
|
||||
|
||||
if ( $transient_name ) {
|
||||
set_transient( $transient_name, $status, self::UNKNOWN_ACTIVE_CAMPAIGNS_STATUS_TRANSIENT_TTL );
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if criteria is met to enable Blaze features.
|
||||
* Keep in mind that this makes remote requests, so we want to avoid calling it when unnecessary, like in the frontend.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function should_initialize() {
|
||||
$is_wpcom = defined( 'IS_WPCOM' ) && IS_WPCOM;
|
||||
$connection = new Jetpack_Connection();
|
||||
$site_id = Jetpack_Connection::get_site_id();
|
||||
|
||||
// Only admins should be able to Blaze posts on a site.
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'user_not_admin',
|
||||
);
|
||||
}
|
||||
|
||||
// Allow short-circuiting the Blaze initialization via a filter.
|
||||
if ( has_filter( 'jetpack_blaze_enabled' ) ) {
|
||||
/**
|
||||
* Filter to disable all Blaze functionality.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*
|
||||
* @param bool $should_initialize Whether Blaze should be enabled. Default to true.
|
||||
*/
|
||||
$should_init = apply_filters( 'jetpack_blaze_enabled', true );
|
||||
|
||||
return array(
|
||||
'can_init' => $should_init,
|
||||
'reason' => $should_init ? null : 'initialization_disabled',
|
||||
);
|
||||
}
|
||||
|
||||
// On self-hosted sites, we must do some additional checks.
|
||||
if ( ! $is_wpcom ) {
|
||||
/*
|
||||
* These features currently only work on WordPress.com,
|
||||
* so the site must be connected to WordPress.com, and the user as well for things to work.
|
||||
*/
|
||||
if (
|
||||
is_wp_error( $site_id )
|
||||
) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'wp_error',
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $connection->is_connected() ) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'site_not_connected',
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! $connection->is_user_connected() ) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'user_not_connected',
|
||||
);
|
||||
}
|
||||
|
||||
// The whole thing is powered by Sync!
|
||||
if ( ! Sync_Settings::is_sync_enabled() ) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'sync_disabled',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the site supports Blaze.
|
||||
if ( is_numeric( $site_id ) && ! self::site_supports_blaze( $site_id ) ) {
|
||||
return array(
|
||||
'can_init' => false,
|
||||
'reason' => 'site_not_eligible',
|
||||
);
|
||||
}
|
||||
|
||||
// Final fallback.
|
||||
return array(
|
||||
'can_init' => true,
|
||||
'reason' => null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL to create a Blaze campaign for a specific post.
|
||||
*
|
||||
* This can return 2 different types of URL:
|
||||
* - Calypso Links
|
||||
* - wp-admin Links if access to the wp-admin Blaze Dashboard is enabled.
|
||||
*
|
||||
* @param int|string $post_id Post ID.
|
||||
*
|
||||
* @return array An array with the link, and whether this is a Calypso or a wp-admin link.
|
||||
*/
|
||||
public static function get_campaign_management_url( $post_id ) {
|
||||
if ( self::is_dashboard_enabled() ) {
|
||||
$admin_url = admin_url( 'tools.php?page=advertising' );
|
||||
$hostname = wp_parse_url( get_site_url(), PHP_URL_HOST );
|
||||
$blaze_url = sprintf(
|
||||
'%1$s#!/advertising/posts/promote/post-%2$s/%3$s',
|
||||
$admin_url,
|
||||
esc_attr( $post_id ),
|
||||
$hostname
|
||||
);
|
||||
|
||||
return array(
|
||||
'link' => $blaze_url,
|
||||
'external' => false,
|
||||
);
|
||||
}
|
||||
|
||||
// Default Calypso link.
|
||||
$blaze_url = Redirect::get_url(
|
||||
'jetpack-blaze',
|
||||
array(
|
||||
'query' => 'blazepress-widget=post-' . esc_attr( $post_id ),
|
||||
)
|
||||
);
|
||||
return array(
|
||||
'link' => $blaze_url,
|
||||
'external' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Promote link to the posts list row action.
|
||||
*
|
||||
* @param array $post_actions The current array of post actions.
|
||||
* @param WP_Post $post The current post in the post list table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function jetpack_blaze_row_action( $post_actions, $post ) {
|
||||
/**
|
||||
* Allow third-party plugins to disable Blaze row actions.
|
||||
*
|
||||
* @since 0.16.0
|
||||
*
|
||||
* @param bool $are_quick_links_enabled Should Blaze row actions be enabled.
|
||||
* @param WP_Post $post The current post in the post list table.
|
||||
*/
|
||||
$are_quick_links_enabled = apply_filters( 'jetpack_blaze_post_row_actions_enable', true, $post );
|
||||
|
||||
// Bail if we are not looking at one of the supported post types (post, page, or product).
|
||||
if (
|
||||
! $are_quick_links_enabled
|
||||
|| ! in_array( $post->post_type, array( 'post', 'page', 'product' ), true )
|
||||
) {
|
||||
return $post_actions;
|
||||
}
|
||||
|
||||
// Bail if the post is not published.
|
||||
if ( $post->post_status !== 'publish' ) {
|
||||
return $post_actions;
|
||||
}
|
||||
|
||||
// Bail if the post has a password.
|
||||
if ( '' !== $post->post_password ) {
|
||||
return $post_actions;
|
||||
}
|
||||
|
||||
$blaze_url = self::get_campaign_management_url( $post->ID );
|
||||
$text = __( 'Promote with Blaze', 'jetpack-blaze' );
|
||||
$title = get_the_title( $post );
|
||||
$label = sprintf(
|
||||
/* translators: post title */
|
||||
__( 'Blaze “%s” to Tumblr and WordPress.com audiences.', 'jetpack-blaze' ),
|
||||
$title
|
||||
);
|
||||
|
||||
$post_actions['blaze'] = sprintf(
|
||||
'<a href="%1$s" title="%2$s" aria-label="%2$s" %4$s>%3$s</a>',
|
||||
esc_url( $blaze_url['link'] ),
|
||||
esc_attr( $label ),
|
||||
esc_html( $text ),
|
||||
( true === $blaze_url['external'] ? 'target="_blank" rel="noopener noreferrer"' : '' )
|
||||
);
|
||||
|
||||
return $post_actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block editor assets.
|
||||
*/
|
||||
public static function enqueue_block_editor_assets() {
|
||||
/*
|
||||
* We do not want (nor need) Blaze in the site editor, or the widget editor, or the classic editor.
|
||||
* We only want it in the post editor.
|
||||
* Enqueueing the script in those editors would cause a fatal error.
|
||||
* See #20357 for more info.
|
||||
*/
|
||||
if ( ! function_exists( 'get_current_screen' ) ) { // When Gutenberg is loaded in the frontend.
|
||||
return;
|
||||
}
|
||||
$current_screen = get_current_screen();
|
||||
if (
|
||||
empty( $current_screen )
|
||||
|| $current_screen->base !== 'post'
|
||||
|| ! $current_screen->is_block_editor()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// Bail if criteria is not met to enable Blaze features.
|
||||
if ( ! self::should_initialize()['can_init'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assets::register_script(
|
||||
self::SCRIPT_HANDLE,
|
||||
self::$script_path,
|
||||
__FILE__,
|
||||
array(
|
||||
'enqueue' => true,
|
||||
'in_footer' => true,
|
||||
'textdomain' => 'jetpack-blaze',
|
||||
)
|
||||
);
|
||||
|
||||
// Adds Connection package initial state.
|
||||
Connection_Initial_State::render_script( self::SCRIPT_HANDLE );
|
||||
|
||||
// Pass additional data to our script.
|
||||
wp_localize_script(
|
||||
self::SCRIPT_HANDLE,
|
||||
'blazeInitialState',
|
||||
array(
|
||||
'blazeUrlTemplate' => self::get_campaign_management_url( '__POST_ID__' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
/**
|
||||
* Blaze dashboard Initial State
|
||||
*
|
||||
* @package automattic/jetpack-blaze
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Blaze;
|
||||
|
||||
use Automattic\Jetpack\Connection\Manager;
|
||||
use Automattic\Jetpack\Constants;
|
||||
use Automattic\Jetpack\Current_Plan;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
use Jetpack_Options;
|
||||
|
||||
/**
|
||||
* Class Dashboard_Config_Data
|
||||
*/
|
||||
class Dashboard_Config_Data {
|
||||
|
||||
/**
|
||||
* Blaze dashboard admin page. Default is tools.php.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $admin_page;
|
||||
|
||||
/**
|
||||
* Blaze dashboard menu slug. Default is 'advertising'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $menu_slug;
|
||||
|
||||
/**
|
||||
* Dashboard config constructor.
|
||||
*
|
||||
* @param string $admin_page Dashboard admin page. Default is tools.php.
|
||||
* @param string $menu_slug Dashboard menu slug. Default is 'advertising'.
|
||||
*/
|
||||
public function __construct( $admin_page = 'tools.php', $menu_slug = 'advertising' ) {
|
||||
$this->admin_page = $admin_page;
|
||||
$this->menu_slug = $menu_slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set configData to window.configData.
|
||||
*
|
||||
* @param array $config_data The config data.
|
||||
*/
|
||||
public function get_js_config_data( $config_data = null ) {
|
||||
return 'window.configData = ' . wp_json_encode(
|
||||
$config_data === null ? $this->get_data() : $config_data,
|
||||
JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP
|
||||
) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the config for the app.
|
||||
*/
|
||||
public function get_data() {
|
||||
$blog_id = Jetpack_Options::get_option( 'id' );
|
||||
$host = new Host();
|
||||
$empty_object = json_decode( '{}' );
|
||||
|
||||
$user = $this->get_connected_user_identity();
|
||||
|
||||
$data = array(
|
||||
'admin_page_base' => $this->get_admin_path(),
|
||||
'api_root' => esc_url_raw( rest_url() ),
|
||||
'blog_id' => $blog_id,
|
||||
'enable_all_sections' => false,
|
||||
'env_id' => 'production',
|
||||
'google_analytics_key' => 'UA-10673494-15',
|
||||
'hostname' => wp_parse_url( get_site_url(), PHP_URL_HOST ),
|
||||
'i18n_default_locale_slug' => 'en',
|
||||
'mc_analytics_enabled' => false,
|
||||
'meta' => array(),
|
||||
'nonce' => wp_create_nonce( 'wp_rest' ),
|
||||
'site_name' => \get_bloginfo( 'name' ),
|
||||
'sections' => array(),
|
||||
// Features are inlined in Calypso Blaze app (wp-calypso/apps/blaze-dashboard)
|
||||
'features' => array(
|
||||
'is_running_in_jetpack_site' => ! $host->is_wpcom_simple(),
|
||||
),
|
||||
'initial_state' => array(
|
||||
'currentUser' => array(
|
||||
'id' => $user['ID'],
|
||||
'user' => $user,
|
||||
'capabilities' => array(
|
||||
"$blog_id" => $this->get_current_user_capabilities(),
|
||||
),
|
||||
),
|
||||
'sites' => array(
|
||||
'items' => array(
|
||||
"$blog_id" => array(
|
||||
'ID' => $blog_id,
|
||||
'URL' => site_url(),
|
||||
'jetpack' => ! $host->is_wpcom_simple(),
|
||||
'visible' => true,
|
||||
'capabilities' => $empty_object,
|
||||
'products' => array(),
|
||||
'plan' => $empty_object, // we need this empty object, otherwise the front end would crash on insight page.
|
||||
'options' => array(
|
||||
'admin_url' => admin_url(),
|
||||
'gmt_offset' => $this->get_gmt_offset(),
|
||||
'is_wpcom_atomic' => $host->is_woa_site(),
|
||||
'is_wpcom_simple' => $host->is_wpcom_simple(),
|
||||
'jetpack_version' => Constants::get_constant( 'JETPACK__VERSION' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'features' => array( "$blog_id" => array( 'data' => $this->get_plan_features() ) ),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter to allow modification of the Blaze dashboard config data.
|
||||
*
|
||||
* @param bool $data Blaze dashboard config data.
|
||||
*
|
||||
* @since 0.21.0
|
||||
*/
|
||||
return apply_filters( 'jetpack_blaze_dashboard_config_data', $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WordPress.com user's identity, if connected.
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
protected function get_connected_user_identity() {
|
||||
$user_data = ( new Manager() )->get_connected_user_data();
|
||||
if ( ! $user_data ) {
|
||||
return array(
|
||||
'ID' => 1000,
|
||||
'username' => 'no-user',
|
||||
'localeSlug' => $this->get_locale(),
|
||||
'site_count' => 1,
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'ID' => $user_data['ID'],
|
||||
'username' => $user_data['login'],
|
||||
'email' => $user_data['email'],
|
||||
'localeSlug' => $this->get_locale(),
|
||||
'site_count' => 1,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current site GMT Offset.
|
||||
*
|
||||
* @return float The current site GMT Offset by hours.
|
||||
*/
|
||||
protected function get_gmt_offset() {
|
||||
return (float) get_option( 'gmt_offset' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Page base for the Calypso admin page.
|
||||
*/
|
||||
protected function get_admin_path() {
|
||||
if ( ! isset( $_SERVER['PHP_SELF'] ) || ! isset( $_SERVER['QUERY_STRING'] ) ) {
|
||||
$admin_path = $this->admin_page . '?page=' . $this->menu_slug;
|
||||
$parsed = wp_parse_url( admin_url( $admin_path ) );
|
||||
|
||||
return $parsed['path'] . '?' . $parsed['query'];
|
||||
}
|
||||
// We do this because page.js requires the exactly page base to be set otherwise it will not work properly.
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
return wp_unslash( $_SERVER['PHP_SELF'] ) . '?' . wp_unslash( $_SERVER['QUERY_STRING'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's locale acceptable by Calypso.
|
||||
*/
|
||||
protected function get_locale() {
|
||||
/**
|
||||
* In WP, locales are formatted as LANGUAGE_REGION, for example `en`, `en_US`, `es_AR`,
|
||||
* but Calypso expects language-region, e.g. `en-us`, `en`, `es-ar`. So we need to convert
|
||||
* them to lower case and replace the underscore with a dash.
|
||||
*/
|
||||
$locale = strtolower( get_user_locale() );
|
||||
$locale = str_replace( '_', '-', $locale );
|
||||
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the features of the current plan.
|
||||
*/
|
||||
protected function get_plan_features() {
|
||||
$plan = Current_Plan::get();
|
||||
if ( empty( $plan['features'] ) ) {
|
||||
return array();
|
||||
}
|
||||
return $plan['features'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the capabilities of the current user.
|
||||
*
|
||||
* @return array An array of capabilities.
|
||||
*/
|
||||
protected function get_current_user_capabilities() {
|
||||
$user = wp_get_current_user();
|
||||
if ( ! $user || is_wp_error( $user ) ) {
|
||||
return array();
|
||||
}
|
||||
return $user->allcaps;
|
||||
}
|
||||
}
|
||||
+1646
File diff suppressed because it is too large
Load Diff
+228
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* A class that adds a Blaze dashboard to wp-admin.
|
||||
*
|
||||
* @since 0.7.0
|
||||
*
|
||||
* @package automattic/jetpack-blaze
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Blaze;
|
||||
|
||||
use Automattic\Jetpack\Assets;
|
||||
|
||||
/**
|
||||
* Responsible for adding a Blaze dashboard menu to wp-admin.
|
||||
* The screen content itself is rendered remotely.
|
||||
*/
|
||||
class Dashboard {
|
||||
/**
|
||||
* Package version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PACKAGE_VERSION = '0.27.25';
|
||||
|
||||
/**
|
||||
* List of dependencies needed to render the dashboard in wp-admin.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const JS_DEPENDENCIES = array( 'lodash', 'react', 'react-dom', 'wp-components', 'wp-compose', 'wp-i18n', 'wp-is-shallow-equal', 'wp-primitives', 'wp-url', 'moment' );
|
||||
|
||||
/**
|
||||
* URL where we load the Blaze dashboard remotely.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CDN_URL = 'https://widgets.wp.com/blaze-dashboard/%s/%s';
|
||||
|
||||
/**
|
||||
* Script handle for the JS file we enqueue in the dashboard page.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SCRIPT_HANDLE = 'jetpack-blaze-dashboard';
|
||||
|
||||
/**
|
||||
* We bump the asset version when the Jetpack back end is not compatible anymore.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const BLAZEDASH_VERSION = 'v1';
|
||||
|
||||
/**
|
||||
* Cache key for the cache buster.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const BLAZEDASH_CACHE_BUSTER_CACHE_KEY = 'jetpack_blaze_admin_asset_cache_buster';
|
||||
|
||||
/**
|
||||
* Blaze dashboard admin page. Default is tools.php.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $admin_page;
|
||||
|
||||
/**
|
||||
* Blaze dashboard menu slug. Default is 'advertising'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $menu_slug;
|
||||
|
||||
/**
|
||||
* Blaze dashboard css prefix. Default is 'jp-blaze'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $css_prefix;
|
||||
|
||||
/**
|
||||
* Dashboard constructor.
|
||||
*
|
||||
* @param string $admin_page Dashboard admin page. Default is tools.php.
|
||||
* @param string $menu_slug Dashboard menu slug. Default is 'advertising'.
|
||||
* @param string $css_prefix Dashboard css prefix. Default is 'jp-blaze'.
|
||||
*/
|
||||
public function __construct( $admin_page = 'tools.php', $menu_slug = 'advertising', $css_prefix = 'jp-blaze' ) {
|
||||
$this->admin_page = $admin_page;
|
||||
$this->menu_slug = $menu_slug;
|
||||
$this->css_prefix = $css_prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override render funtion
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
?>
|
||||
<div id="wpcom" class="<?php echo esc_attr( $this->css_prefix ); ?>-dashboard" style="min-height: calc(100vh - 100px);">
|
||||
<div class="hide-if-js"><?php esc_html_e( 'Your Jetpack Blaze dashboard requires JavaScript to function properly.', 'jetpack-blaze' ); ?></div>
|
||||
<div class="hide-if-no-js" style="height: 100%">
|
||||
<img
|
||||
class="<?php echo esc_attr( $this->css_prefix ); ?>-dashboard-loading-spinner"
|
||||
width="32"
|
||||
height="32"
|
||||
style="position: absolute; left: 50%; top: 50%;"
|
||||
alt=<?php echo esc_attr( __( 'Loading', 'jetpack-blaze' ) ); ?>
|
||||
src="//en.wordpress.com/i/loading/loading-64.gif"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function($) {
|
||||
// Load SVG sprite.
|
||||
$.get("https://widgets.wp.com/blaze-dashboard/common/gridicons-506499ddac13811fee8e.svg", function(data) {
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
|
||||
div.style = 'display: none';
|
||||
document.body.insertBefore(div, document.body.childNodes[0]);
|
||||
});
|
||||
// we intercept on all anchor tags and change it to hashbang style.
|
||||
$("#wpcom").on('click', 'a', function (e) {
|
||||
const link = e && e.currentTarget && e.currentTarget.attributes && e.currentTarget.attributes.href && e.currentTarget.attributes.href.value;
|
||||
if (link && link.startsWith( '/<?php echo esc_attr( $this->menu_slug ); ?>' ) ) {
|
||||
location.hash = `#!${link}`;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the admin resources.
|
||||
*/
|
||||
public function admin_init() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_scripts' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the admin scripts.
|
||||
*
|
||||
* @param string $hook The current admin page.
|
||||
*/
|
||||
public function load_admin_scripts( $hook ) {
|
||||
if ( ! str_ends_with( $hook, 'page_' . $this->menu_slug ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$asset_handle = self::SCRIPT_HANDLE;
|
||||
$asset_name = 'build.min';
|
||||
|
||||
$dashboard_config = new Dashboard_Config_Data( $this->admin_page, $this->menu_slug );
|
||||
|
||||
$config_data = $dashboard_config->get_data();
|
||||
|
||||
if ( file_exists( __DIR__ . "/../dist/{$asset_name}.js" ) ) {
|
||||
// Load local assets for the convenience of development.
|
||||
Assets::register_script(
|
||||
$asset_handle,
|
||||
"../dist/{$asset_name}.js",
|
||||
__FILE__,
|
||||
array(
|
||||
'enqueue' => true,
|
||||
'in_footer' => true,
|
||||
'textdomain' => 'jetpack-blaze',
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$css_url = $asset_name . ( is_rtl() ? '.rtl' : '' ) . '.css';
|
||||
$css_handle = $asset_handle . '-style';
|
||||
|
||||
wp_enqueue_script(
|
||||
$asset_handle,
|
||||
sprintf( self::CDN_URL, self::BLAZEDASH_VERSION, "{$asset_name}.js" ),
|
||||
self::JS_DEPENDENCIES,
|
||||
$this->get_cdn_asset_cache_buster(),
|
||||
true
|
||||
);
|
||||
wp_enqueue_style(
|
||||
$css_handle,
|
||||
sprintf( self::CDN_URL, self::BLAZEDASH_VERSION, $css_url ),
|
||||
array(),
|
||||
$this->get_cdn_asset_cache_buster()
|
||||
);
|
||||
}
|
||||
|
||||
wp_add_inline_script(
|
||||
$asset_handle,
|
||||
$dashboard_config->get_js_config_data( $config_data ),
|
||||
'before'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cache buster string for assets.
|
||||
* Development mode doesn't need this, as it's handled by `Assets` class.
|
||||
*/
|
||||
protected function get_cdn_asset_cache_buster() {
|
||||
// Use cached cache buster in production.
|
||||
$remote_asset_version = get_transient( self::BLAZEDASH_CACHE_BUSTER_CACHE_KEY );
|
||||
if ( ! empty( $remote_asset_version ) ) {
|
||||
return $remote_asset_version;
|
||||
}
|
||||
|
||||
// If no cached cache buster, we fetch it from CDN and set to transient.
|
||||
$response = wp_remote_get( sprintf( self::CDN_URL, self::BLAZEDASH_VERSION, 'build_meta.json' ), array( 'timeout' => 5 ) );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
// fallback to the package version.
|
||||
return self::PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
$build_meta = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
if ( ! empty( $build_meta['cache_buster'] ) ) {
|
||||
// Cache the cache buster for 15 mins.
|
||||
set_transient( self::BLAZEDASH_CACHE_BUSTER_CACHE_KEY, $build_meta['cache_buster'], 15 * MINUTE_IN_SECONDS );
|
||||
return $build_meta['cache_buster'];
|
||||
}
|
||||
|
||||
// fallback to the package version.
|
||||
return self::PACKAGE_VERSION;
|
||||
}
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* The Blaze Rest Controller class.
|
||||
* Registers the REST routes for Blaze Dashboard.
|
||||
*
|
||||
* @package automattic/jetpack-blaze
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Blaze;
|
||||
|
||||
use Automattic\Jetpack\Blaze;
|
||||
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
use WP_Error;
|
||||
use WP_REST_Server;
|
||||
|
||||
/**
|
||||
* Registers general REST routes for Blaze.
|
||||
*/
|
||||
class REST_Controller {
|
||||
/**
|
||||
* Namespace for the REST API.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $namespace = 'jetpack/v4/blaze';
|
||||
|
||||
/**
|
||||
* Connection manager object.
|
||||
*
|
||||
* @var \Automattic\Jetpack\Connection\Manager
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* Creates the REST_Controller object.
|
||||
*
|
||||
* @param \Automattic\Jetpack\Connection\Manager $connection The connection manager object.
|
||||
*/
|
||||
public function __construct( $connection = null ) {
|
||||
$this->connection = $connection ?? new Connection_Manager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the REST routes on the `rest_api_init` hook.
|
||||
*
|
||||
* Instantiated here, rather than eagerly, so the controller class only loads
|
||||
* on requests that reach `rest_api_init`. Static so the callback can be
|
||||
* unregistered.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function register() {
|
||||
( new self() )->register_rest_routes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the REST routes.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function register_rest_routes() {
|
||||
$site_id = $this->get_site_id();
|
||||
|
||||
if ( ! is_wp_error( $site_id ) ) {
|
||||
register_rest_route(
|
||||
static::$namespace,
|
||||
'eligibility',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'blaze_eligibility' ),
|
||||
'permission_callback' => array( $this, 'can_user_view_blaze_settings' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
static::$namespace,
|
||||
'dashboard',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'is_dashboard_enabled' ),
|
||||
'permission_callback' => array( $this, 'can_user_view_blaze_settings' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
register_rest_route(
|
||||
static::$namespace,
|
||||
'active-campaigns',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_active_campaigns' ),
|
||||
'permission_callback' => array( $this, 'can_user_view_blaze_settings' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only administrators can access the API.
|
||||
*
|
||||
* @return bool|WP_Error True if a blog token was used to sign the request, WP_Error otherwise.
|
||||
*/
|
||||
public function can_user_view_blaze_settings() {
|
||||
if (
|
||||
$this->is_user_connected()
|
||||
&& current_user_can( 'manage_options' )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->get_forbidden_error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the eligibility for Blaze.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function blaze_eligibility() {
|
||||
$site_id = $this->get_site_id();
|
||||
if ( is_wp_error( $site_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) Blaze::site_supports_blaze( $site_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the dashboard is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_dashboard_enabled() {
|
||||
return (bool) Blaze::is_dashboard_enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active Blaze campaign status for the site.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_active_campaigns() {
|
||||
$site_id = $this->get_site_id();
|
||||
if ( is_wp_error( $site_id ) ) {
|
||||
return Blaze::get_active_campaigns_status( 0 );
|
||||
}
|
||||
|
||||
return Blaze::get_active_campaigns_status( $site_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user is connected.
|
||||
* On WordPress.com Simple, it is always connected.
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
private function is_user_connected() {
|
||||
if ( ( new Host() )->is_wpcom_simple() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->connection->is_connected() && $this->connection->is_user_connected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a WP_Error object with a forbidden error.
|
||||
*/
|
||||
protected function get_forbidden_error() {
|
||||
$error_msg = esc_html__(
|
||||
'You are not allowed to perform this action.',
|
||||
'jetpack-blaze'
|
||||
);
|
||||
|
||||
return new WP_Error( 'rest_forbidden', $error_msg, array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the site ID.
|
||||
*
|
||||
* @return int|WP_Error
|
||||
*/
|
||||
private function get_site_id() {
|
||||
return Connection_Manager::get_site_id();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user