Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions projects/packages/jetpack-mu-wpcom/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.1.1 - 2023-01-27

- Minor internal updates.

## 0.1.0 - 2023-01-19

- Testing initial package release.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: added
Comment: Migrate code from Automattic/jetpack/pull/27815


2 changes: 1 addition & 1 deletion projects/packages/jetpack-mu-wpcom/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"require-dev": {
"yoast/phpunit-polyfills": "1.0.4",
"automattic/jetpack-changelogger": "@dev",
"automattic/wordbless": "dev-master"
"automattic/wordbless": "0.4.1"
},
"autoload": {
"classmap": [
Expand Down
2 changes: 1 addition & 1 deletion projects/packages/jetpack-mu-wpcom/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@automattic/jetpack-mu-wpcom",
"version": "0.1.1-alpha",
"version": "0.1.2-alpha",
"description": "Enhances your site with features powered by WordPress.com",
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/packages/jetpack-mu-wpcom/#readme",
"bugs": {
Expand Down
7 changes: 5 additions & 2 deletions projects/packages/jetpack-mu-wpcom/phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<phpunit bootstrap="tests/php/bootstrap.php" backupGlobals="false" colors="true" convertDeprecationsToExceptions="true">
<testsuites>
<testsuite name="main">
<directory prefix="test" suffix=".php">tests/php</directory>
<testsuite name="features">
<directory suffix="-test.php">tests/php/features</directory>
</testsuite>
<testsuite name="common">
<directory suffix="-test.php">tests/php/common</directory>
</testsuite>
</testsuites>
<filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,43 @@
*/
class Jetpack_Mu_Wpcom {

const PACKAGE_VERSION = '0.1.1-alpha';
const PACKAGE_VERSION = '0.1.2-alpha';
const PKG_DIR = __DIR__ . '/../';

/**
* Initialize the class.
*
* @return void
*/
public static function init() {
if ( did_action( 'jetpack_mu_wpcom_initialized' ) ) {
return;
}

// Shared code for src/features
require_once self::PKG_DIR . 'src/common/index.php'; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath
// Todo: once coming-soon is removed from ETK, we can remove the has_action check.
if ( has_action( 'plugins_loaded', 'A8C\FSE\load_coming_soon' ) === false ) {
add_action( 'plugins_loaded', array( __CLASS__, 'load_coming_soon' ) );
}

/**
* Runs right after the Jetpack_Mu_Wpcom package is initialized.
*
* @since $$next-version$$
*/
do_action( 'jetpack_mu_wpcom_initialized' );
}

/**
* Load the Coming Soon feature.
*/
public static function load_coming_soon() {
if (
( defined( 'WPCOM_PUBLIC_COMING_SOON' ) && WPCOM_PUBLIC_COMING_SOON ) ||
apply_filters( 'a8c_enable_public_coming_soon', false )
) {
require_once __DIR__ . '/features/coming-soon/coming-soon.php';
}
}
}
31 changes: 31 additions & 0 deletions projects/packages/jetpack-mu-wpcom/src/common/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* File for various functionality which needs to be added to Simple and Atomic
* sites.
*
* @package automattic/jetpack-mu-wpcom
*/

namespace Automattic\Jetpack\Jetpack_Mu_Wpcom\Common;

/**
* Returns ISO 639 conforming locale string.
*
* @param string $language a language tag to be converted e.g. "en_US".
* @return string ISO 639 locale string e.g. "en"
*/
function get_iso_639_locale( $language ) {
$language = strtolower( $language );

if ( in_array( $language, array( 'pt_br', 'pt-br', 'zh_tw', 'zh-tw', 'zh_cn', 'zh-cn' ), true ) ) {
$language = str_replace( '_', '-', $language );
} else {
$language = preg_replace( '/([-_].*)$/i', '', $language );
}

if ( empty( $language ) ) {
return 'en';
}

return $language;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
<?php
/**
* Coming Soon
*
* @package A8C\FSE\Coming_soon
*/

namespace A8C\FSE\Coming_soon;

use Automattic\Jetpack\Jetpack_Mu_Wpcom;

/**
* Determines whether the coming soon page should be shown.
*
* @return boolean
*/
function should_show_coming_soon_page() {
if ( ! is_singular() && ! is_archive() && ! is_search() && ! is_front_page() && ! is_home() && ! is_404() ) {
return false;
}

$share_code = get_share_code();
if ( is_accessed_by_valid_share_link( $share_code ) ) {
track_preview_link_event();
setcookie( 'wp_share_code', $share_code, time() + 3600, '/', false, is_ssl(), true );
return false;
}

$should_show = ( (int) get_option( 'wpcom_public_coming_soon' ) === 1 );

// Everyone from Administrator to Subscriber will be able to see the site.
// See https://wordpress.org/support/article/roles-and-capabilities/ for all roles and capabilities.
// We can update to `edit_post` to be stricter, or open it up as an editable feature.
if ( is_user_logged_in() && current_user_can( 'read' ) ) {
$should_show = false;
}

// Allow folks to hook into this method to set their own rules.
// We'll use to on WordPress.com to check further user privileges.
return apply_filters( 'a8c_show_coming_soon_page', $should_show );
}

/**
* Gets share code from URL or Cookie.
*
* @return string
*/
function get_share_code() {
if ( isset( $_GET['share'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- No data written to site, used in conditionally displaying coming-soon page and adding robots headers.
return sanitize_key( wp_unslash( $_GET['share'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- No data written to site, used in conditionally displaying coming-soon page and adding robots headers.
} elseif ( isset( $_COOKIE['wp_share_code'] ) ) {
return sanitize_key( wp_unslash( $_COOKIE['wp_share_code'] ) );
}
return '';
}

/**
* Determines whether the coming soon page should be bypassed.
*
* It checks if share code is provided as GET parameter, or as a cookie.
* Then it validates the code against blog option, and if sharing code is valid,
* it allows bypassing the Coming Soon page.
*
* @param string $share_code Share code to check against blog option value.
*
* @return bool
*/
function is_accessed_by_valid_share_link( $share_code ) {
$preview_links_option = get_option( 'wpcom_public_preview_links' );

if ( ! is_array( $preview_links_option ) || ! count( $preview_links_option ) || ! $share_code ) {
return false;
}

if ( ! in_array( $share_code, array_column( $preview_links_option, 'code' ), true ) ) {
return false;
}

return true;
}

/**
* Add X-Robots-Tag header to prevent from indexing page that includes share code.
*
* @param array $headers Headers.
* @return array Headers.
*/
function maybe_add_x_robots_headers( $headers ) {
if ( get_share_code() ) {
$headers['X-Robots-Tag'] = 'noindex, nofollow';
}
return $headers;
}
add_filter( 'wp_headers', __NAMESPACE__ . '\maybe_add_x_robots_headers' );

/**
* Track site preview event.
*
* @return void
*/
function track_preview_link_event() {
$event_name = 'wpcom_site_previewed';
if ( function_exists( 'wpcomsh_record_tracks_event' ) ) {
wpcomsh_record_tracks_event( $event_name, array() );
} else {
require_lib( 'tracks/client' );
tracks_record_event( get_current_user_id(), $event_name, array() );
}
}

/**
* Returns the WP.com logo
*
* @return string
*/
function coming_soon_share_image() {
return 'https://s1.wp.com/home.logged-out/images/wpcom-og-image.jpg';
}

/**
* Renders a fallback coming soon page
*/
function render_fallback_coming_soon_page() {
if ( ! defined( 'GRAVATAR_HOVERCARDS__DISABLE' ) ) {
define( 'GRAVATAR_HOVERCARDS__DISABLE', true );
}

// Disable WP scripts, likes, social og meta, cookie banner.
remove_action( 'wp_enqueue_scripts', 'wpcom_actionbar_enqueue_scripts', 101 );
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'wp_head', 'header_js', 5 );
remove_action( 'wp_head', 'global_css', 5 );
remove_action( 'wp_footer', 'wpcom_subs_js' );
remove_action( 'wp_footer', 'stats_footer', 101 );
add_filter( 'infinite_scroll_archive_supported', '__return_false', 99 ); // Disable infinite scroll feature.
add_filter( 'jetpack_disable_eu_cookie_law_widget', '__return_true', 1 );
add_filter( 'wpcom_disable_logged_out_follow', '__return_true', 10, 1 ); // Disable follow actionbar.
add_filter( 'wpl_is_enabled_sitewide', '__return_false', 10, 1 ); // Disable likes.
add_filter( 'jetpack_implode_frontend_css', '__return_false', 99 ); // Jetpack "implodes" all registered CSS files into one file.
add_filter( 'woocommerce_demo_store', '__return_false' ); // Prevent the the wocommerce demo store notice from displaying.
add_filter( 'jetpack_open_graph_image_default', __NAMESPACE__ . '\coming_soon_share_image' ); // Set the default OG image.
add_filter( 'jetpack_twitter_cards_image_default', __NAMESPACE__ . '\coming_soon_share_image' ); // Set the default Twitter Card image.
wp_enqueue_style( 'recoleta-font', '//s1.wp.com/i/fonts/recoleta/css/400.min.css', array(), Jetpack_Mu_Wpcom::PACKAGE_VERSION );

include __DIR__ . '/fallback-coming-soon-page.php';
}

/**
* This filter makes sure it's possible to fetch `wpcom_public_coming_soon` option via public-api.wordpress.com.
*
* @param object $options array Retrieved site options, ready to be returned as API respomnse.
*
* @return array current value of `wpcom_public_coming_soon`
*/
function add_public_coming_soon_to_settings_endpoint_get( $options ) {
$wpcom_public_coming_soon = (int) get_option( 'wpcom_public_coming_soon' );
$options['wpcom_public_coming_soon'] = $wpcom_public_coming_soon;

return $options;
}
add_filter( 'site_settings_endpoint_get', __NAMESPACE__ . '\add_public_coming_soon_to_settings_endpoint_get' );

/**
* This filter makes sure it's possible to change `wpcom_public_coming_soon` option via public-api.wordpress.com.
*
* @param object $input Filtered POST input.
* @param object $unfiltered_input Raw and unfiltered POST input.
*
* @return mixed
*/
function add_public_coming_soon_to_settings_endpoint_post( $input, $unfiltered_input ) {
if ( array_key_exists( 'wpcom_public_coming_soon', $unfiltered_input ) ) {
$input['wpcom_public_coming_soon'] = (int) $unfiltered_input['wpcom_public_coming_soon'];
}
return $input;
}
add_filter( 'rest_api_update_site_settings', __NAMESPACE__ . '\add_public_coming_soon_to_settings_endpoint_post', 10, 2 );

/**
* Launch the site when the privacy mode changes from public-not-indexed
* This can happen due to clicking the launch button from the banner
* Or due to manually updating the setting in wp-admin or calypso settings page.
*
* @param string $old_value the old value of blog_public.
* @param string $value the new value of blog_public.
* @return bool whether an update occurred.
*/
function disable_coming_soon_on_privacy_change( $old_value, $value ) {
if ( 0 !== (int) $old_value || 0 === (int) $value ) {
// Do nothing if not moving from public-not-indexed.
return false;
}
update_option( 'wpcom_public_coming_soon', 0 );
return true;
}
add_action( 'update_option_blog_public', __NAMESPACE__ . '\disable_coming_soon_on_privacy_change', 10, 2 );

/**
* Adds the `wpcom_public_coming_soon` option to new sites if requested by the client.
*
* @param int $blog_id Blog ID.
* @param int $user_id User ID.
* @param string $domain Site domain.
* @param string $path Site path.
* @param int $network_id Network ID. Only relevant on multi-network installations.
* @param array $meta Meta data. Used to set initial site options.
* @return bool whether an update occurred.
*/
function add_option_to_new_site( $blog_id, $user_id, $domain, $path, $network_id, $meta ) {
if ( 0 === $meta['public']
&& array_key_exists( 'wpcom_public_coming_soon', $meta['options'] )
&& 1 === (int) $meta['options']['wpcom_public_coming_soon']
) {
if ( function_exists( 'add_blog_option' ) ) {
add_blog_option( $blog_id, 'wpcom_public_coming_soon', 1 );
}
return true;
}
return false;
}

add_action( 'wpmu_new_blog', __NAMESPACE__ . '\add_option_to_new_site', 10, 6 );

/**
* Decides whether to redirect to the site's coming soon page and performs
* the redirect.
*/
function coming_soon_page() {
if ( ! should_show_coming_soon_page() ) {
return;
}

render_fallback_coming_soon_page();
die();
}
add_action( 'template_redirect', __NAMESPACE__ . '\coming_soon_page' );
Loading