diff --git a/_inc/client/security/index.jsx b/_inc/client/security/index.jsx
index 15a149da7e32d..f9bb266f1a166 100644
--- a/_inc/client/security/index.jsx
+++ b/_inc/client/security/index.jsx
@@ -21,6 +21,7 @@ import BackupsScan from './backups-scan';
import Antispam from './antispam';
import { ManagePlugins } from './manage-plugins';
import { Monitor } from './monitor';
+import { Private } from './private';
import { Protect } from './protect';
import { SSO } from './sso';
@@ -72,13 +73,14 @@ export class Security extends Component {
foundAkismet = this.isAkismetFound(),
rewindActive = 'active' === get( this.props.rewindStatus, [ 'state' ], false ),
foundBackups = this.props.isModuleFound( 'vaultpress' ) || rewindActive,
- foundMonitor = this.props.isModuleFound( 'monitor' );
+ foundMonitor = this.props.isModuleFound( 'monitor' ),
+ foundPrivateSites = this.props.isModuleFound( 'private' );
if ( ! this.props.searchTerm && ! this.props.active ) {
return null;
}
- if ( ! foundSso && ! foundProtect && ! foundAkismet && ! foundBackups && ! foundMonitor ) {
+ if ( ! foundSso && ! foundProtect && ! foundAkismet && ! foundBackups && ! foundMonitor && ! foundPrivateSites ) {
return null;
}
@@ -106,6 +108,7 @@ export class Security extends Component {
+ { __(
+ 'Private sites can only be seen by you ' +
+ 'and other users who are members of this site.'
+ ) }
+
' . $content;
+ }
+
+ /**
+ * Basic styling for the wp-admin 'At a Glance' dashboard widget.
+ * This is applied when the private module is inactive.
+ *
+ * @param string $hook Page Hook Suffix for the current page.
+ */
+ public static function wp_admin_glance_dashboard_style( $hook ) {
+ if ( 'index.php' !== $hook ) {
+ return;
+ }
+
+ $custom_css = '
+ .jp-at-a-glance__site-public {
+ color: #46B450;
+ }
+ ';
+ wp_add_inline_style( 'dashboard', $custom_css );
+ }
+
+ /**
+ * Adds a message to the 'At a Glance' dashboard widget.
+ *
+ * @param string $content Content of 'At A Glance' wp-admin dashboard widget.
+ * @return string The modified content of the 'At a Glance' dashboard widget.
+ */
+ public static function add_public_dashboard_glance_items( $content ) {
+ return
+ $content .
+ '
' .
+ wp_kses(
+ sprintf(
+ /* translators: URL for Jetpack dashboard. */
+ __( 'This site is set to public. Make private.', 'jetpack' ),
+ esc_attr( 'jp-at-a-glance__site-public' ),
+ esc_url( admin_url( 'admin.php?page=jetpack#/security?term=private' ) )
+ ),
+ array(
+ 'a' => array( 'href' => true ),
+ 'span' => array( 'class' => true ),
+ )
+ );
+ }
+
+ /**
+ * Loads modules from given array, otherwise all the currently active modules.
+ *
+ * @param array $modules Specific modules to be loaded.
+ */
+ public static function load_modules( $modules = array() ) {
if (
! self::is_active()
&& ! self::is_development_mode()
@@ -1831,9 +1902,13 @@ public static function load_modules() {
do_action( 'updating_jetpack_version', $version, false );
Jetpack_Options::update_options( compact( 'version', 'old_version' ) );
}
- list( $version ) = explode( ':', $version );
+ list( $version ) = explode( ':', $version );
+ $fetched_all_active_modules = false;
- $modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
+ if ( empty( $modules ) ) {
+ $modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
+ $fetched_all_active_modules = true;
+ }
$modules_data = array();
@@ -1890,12 +1965,14 @@ public static function load_modules() {
do_action( 'jetpack_module_loaded_' . $module );
}
- /**
- * Fires when all the modules are loaded.
- *
- * @since 1.1.0
- */
- do_action( 'jetpack_modules_loaded' );
+ if ( $fetched_all_active_modules ) {
+ /**
+ * Fires when all the modules are loaded.
+ *
+ * @since 1.1.0
+ */
+ do_action( 'jetpack_modules_loaded' );
+ }
// Load module-specific code that is needed even when a module isn't active. Loaded here because code contained therein may need actions such as setup_theme.
require_once( JETPACK__PLUGIN_DIR . 'modules/module-extras.php' );
diff --git a/jetpack.php b/jetpack.php
index 2036ecb672e52..cf934b3670d65 100644
--- a/jetpack.php
+++ b/jetpack.php
@@ -248,6 +248,7 @@ function jetpack_admin_missing_autoloader() { ?>
add_action( 'updating_jetpack_version', array( 'Jetpack', 'do_version_bump' ), 10, 2 );
add_action( 'init', array( 'Jetpack', 'init' ) );
add_action( 'plugins_loaded', array( 'Jetpack', 'plugin_textdomain' ), 99 );
+add_action( 'plugins_loaded', array( 'Jetpack', 'load_private' ), 99 );
add_action( 'plugins_loaded', array( 'Jetpack', 'load_modules' ), 100 );
add_filter( 'jetpack_static_url', array( 'Jetpack', 'staticize_subdomain' ) );
add_filter( 'is_jetpack_site', '__return_true' );
diff --git a/modules/module-extras.php b/modules/module-extras.php
index 989512dcbf516..e762d38a047ec 100644
--- a/modules/module-extras.php
+++ b/modules/module-extras.php
@@ -83,3 +83,28 @@ function jetpack_widgets_add_suffix( $widget_name ) {
);
}
add_filter( 'jetpack_widget_name', 'jetpack_widgets_add_suffix' );
+
+add_action( 'blog_privacy_selector', 'jetpack_priv_notice_privacy_selector' );
+
+/**
+ * Echos notice directing site owners to Jetpack's Private Site feature.
+ */
+function jetpack_priv_notice_privacy_selector() {
+ ?>
+
+ Go to Private Site settings.', 'jetpack' ), + esc_url( admin_url( 'admin.php?page=jetpack#/security?term=private' ) ) + ), + array( 'a' => array( 'href' => true ) ) + ); + ?> +
+ + _x( 'Publish posts by sending an email', 'Module Description', 'jetpack' ), ), + 'private' => array( + 'name' => _x( 'Private site', 'Module Name', 'jetpack' ), + 'description' => _x( 'Make your site only visible to you and users you approve.', 'Module Description', 'jetpack' ), + ), + 'protect' => array( 'name' => _x( 'Protect', 'Module Name', 'jetpack' ), 'description' => _x( 'Protect yourself from brute force and distributed brute force attacks, which are the most common way for hackers to get into your site.', 'Module Description', 'jetpack' ), @@ -328,6 +333,10 @@ function jetpack_get_module_i18n_tag( $key ) { // - modules/minileven.php 'Mobile' =>_x( 'Mobile', 'Module Tag', 'jetpack' ), + // Modules with `Private` tag: + // - modules/private.php + 'Private' =>_x( 'Private', 'Module Tag', 'jetpack' ), + // Modules with `Traffic` tag: // - modules/sitemaps.php // - modules/wordads.php diff --git a/modules/module-info.php b/modules/module-info.php index f13964de081a0..b3b0b2d7d1a7d 100644 --- a/modules/module-info.php +++ b/modules/module-info.php @@ -912,3 +912,22 @@ function jetpack_more_info_copy_post() { esc_html_e( 'Create a new post based on an existing post.', 'jetpack' ); } add_action( 'jetpack_module_more_info_copy-post', 'jetpack_more_info_copy_post' ); + +/** + * Private sites support link. + */ +function jetpack_private_more_link() { + echo 'https://jetpack.com/support/private'; +} +add_action( 'jetpack_learn_more_button_private', 'jetpack_private_more_link' ); + +/** + * Private sites description. + */ +function jetpack_private_more_info() { + esc_html_e( + 'Make your site private. It will only be visible to registered users.', + 'jetpack' + ); +} +add_action( 'jetpack_module_more_info_private', 'jetpack_private_more_info' ); diff --git a/modules/private.php b/modules/private.php new file mode 100644 index 0000000000000..cb54988da9591 --- /dev/null +++ b/modules/private.php @@ -0,0 +1,19 @@ +query_vars['robots'] ) ) { + return; + } + + if ( is_user_logged_in() && self::is_private_blog_user( get_current_blog_id() ) ) { + return; + } + + include JETPACK__PLUGIN_DIR . '/modules/private/private.php'; + + exit; + } + + /** + * Does not check whether the blog is private. Accepts blog and user in various types. + * Returns true for super admins. + * + * @param int $blog Current WordPress blod id.. + */ + private static function is_private_blog_user( $blog ) { + if ( is_numeric( $blog ) ) { + $blog_id = intval( $blog ); + } elseif ( is_object( $blog ) ) { + $blog_id = $blog->blog_id; + } elseif ( is_string( $blog ) ) { + $fields = array( + 'domain' => $blog, + 'path' => '/', + ); + $blog = get_blog_details( $fields ); + $blog_id = $blog->blog_id; + } else { + $blog_id = get_current_blog_id(); + } + + /** + * Filter the capabilites a user needs to have to see the site + * + * @module private + * + * @since 7.4.0 + * + * @param string $cap The lowest capability a user needs to have + */ + $capability = apply_filters( 'jetpack_private_capability', 'read' ); + return current_user_can_for_blog( $blog_id, $capability ); + } + + /** + * Hides the blog's name on the login form for private blogs. + */ + public static function privatize_blog_maybe_mask_blog_name() { + add_filter( 'bloginfo', array( __CLASS__, 'privatize_blog_mask_blog_name' ), 3, 2 ); + } + + /** + * Replaces the the blog's "name" value with "Private Site" + * + * @see privatize_blog_maybe_mask_blog_name() + * @param mixed $value The requested non-URL site information. + * @param mixed $what Type of information requested. + */ + public static function privatize_blog_mask_blog_name( $value, $what ) { + if ( in_array( $what, array( 'name', 'title' ), true ) ) { + $value = __( 'Private Site', 'jetpack' ); + } + + return $value; + } + + /** + * Remove the privatize_blog_mask_blog_name filter + */ + public static function remove_privatize_blog_mask_blog_name_filter() { + remove_filter( 'bloginfo', array( __CLASS__, 'privatize_blog_mask_blog_name' ) ); + } + + /** + * Filters new comments so that users can't comment on private blogs + * + * @param array $comment Documented in wp-includes/comment.php. + */ + public static function privatize_blog_comments( $comment ) { + self::privatize_blog( null ); + return $comment; + } + + /** + * Extend the 'Site Visibility' privacy options to also include a private option + **/ + public static function privatize_blog_priv_selector() { + ?> + + +