From d416736b9222918beac33b87f9ad4b4207ee7b7c Mon Sep 17 00:00:00 2001 From: Jeremy Herve Date: Fri, 6 Dec 2024 16:29:25 +0100 Subject: [PATCH] wpcom Features: add new Holiday Snow feature (#40478) This commit brings a new feature to the mu-wpcom package: - That feature can be toggled via Settings > General in wp-admin. - It is active from December 1st to January 4th by default. --- .../packages/jetpack-mu-wpcom/.eslintignore | 1 + .../changelog/add-holiday-snow | 4 + .../src/class-jetpack-mu-wpcom.php | 3 + .../holiday-snow/class-holiday-snow.php | 216 ++++++++++++++++++ .../src/features/holiday-snow/snowstorm.js | 29 +++ .../packages/sync/changelog/add-holiday-snow | 4 + projects/packages/sync/src/class-defaults.php | 1 + .../jetpack/changelog/add-holiday-snow | 4 + .../sync/test_class.jetpack-sync-options.php | 1 + 9 files changed, 263 insertions(+) create mode 100644 projects/packages/jetpack-mu-wpcom/changelog/add-holiday-snow create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/class-holiday-snow.php create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/snowstorm.js create mode 100644 projects/packages/sync/changelog/add-holiday-snow create mode 100644 projects/plugins/jetpack/changelog/add-holiday-snow diff --git a/projects/packages/jetpack-mu-wpcom/.eslintignore b/projects/packages/jetpack-mu-wpcom/.eslintignore index 6a0ddf86aeb10..3ccc072cf2684 100644 --- a/projects/packages/jetpack-mu-wpcom/.eslintignore +++ b/projects/packages/jetpack-mu-wpcom/.eslintignore @@ -1 +1,2 @@ src/features/newspack-blocks/synced-newspack-blocks +src/features/holiday-snow/snowstorm.js diff --git a/projects/packages/jetpack-mu-wpcom/changelog/add-holiday-snow b/projects/packages/jetpack-mu-wpcom/changelog/add-holiday-snow new file mode 100644 index 0000000000000..59dee1913ffb6 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/add-holiday-snow @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +WordPress.com Features: add Holiday Snow functionality. diff --git a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php index 05261495c7668..a607b7e67d910 100644 --- a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php +++ b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php @@ -103,6 +103,7 @@ public static function load_features() { require_once __DIR__ . '/features/first-posts-stream/first-posts-stream-helpers.php'; require_once __DIR__ . '/features/font-smoothing-antialiased/font-smoothing-antialiased.php'; require_once __DIR__ . '/features/google-analytics/google-analytics.php'; + require_once __DIR__ . '/features/holiday-snow/class-holiday-snow.php'; require_once __DIR__ . '/features/import-customizations/import-customizations.php'; require_once __DIR__ . '/features/marketplace-products-updater/class-marketplace-products-updater.php'; require_once __DIR__ . '/features/media/heif-support.php'; @@ -118,6 +119,8 @@ public static function load_features() { \Automattic\Jetpack\Classic_Theme_Helper\Main::init(); \Automattic\Jetpack\Classic_Theme_Helper\Featured_Content::setup(); + \Automattic\Jetpack\Jetpack_Mu_Wpcom\Holiday_Snow::init(); + // Gets autoloaded from the Scheduled_Updates package. if ( class_exists( 'Automattic\Jetpack\Scheduled_Updates' ) ) { Scheduled_Updates::init(); diff --git a/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/class-holiday-snow.php b/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/class-holiday-snow.php new file mode 100644 index 0000000000000..cd53e73d43957 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/class-holiday-snow.php @@ -0,0 +1,216 @@ += $first_snow_day || $today < $last_snow_day ) { + $is_snow_season = true; + } + + /** + * Filter to check if it is the snow season. + * It allows to change the start and end dates of the season, + * for regions where the holiday season may be different. + * + * @since $$next-version$$ + * + * @param bool $is_holiday_snow_season Is it the snow season? + */ + return apply_filters( 'jetpack_is_holiday_snow_season', $is_snow_season ); + } + + /** + * Check if the snow is enabled. + * + * @return bool + */ + public static function is_snow_enabled() { + return (bool) get_option( self::HOLIDAY_SNOW_OPTION_NAME ); + } + + /** + * Register the hooks. + * + * @return void + */ + public static function init() { + if ( ! self::is_snow_season() ) { + return; + } + + add_filter( 'site_settings_endpoint_get', array( __CLASS__, 'add_option_api' ) ); + add_filter( 'rest_api_update_site_settings', array( __CLASS__, 'update_option_api' ), 10, 2 ); + add_action( 'admin_init', array( __CLASS__, 'register_settings' ) ); + add_action( 'update_option_' . self::HOLIDAY_SNOW_OPTION_NAME, array( __CLASS__, 'holiday_snow_option_updated' ) ); + + if ( self::is_snow_enabled() ) { + add_action( 'wp_enqueue_scripts', array( __CLASS__, 'holiday_snow_script' ) ); + } + } + + /** + * Enqueue the snowstorm script on the frontend. + * + * @return void + */ + public static function holiday_snow_script() { + if ( + /** + * Allow short-circuiting the snow, even when enabled on the site in settings. + * + * @since $$next-version$$ + * + * @param bool true Whether to show the snow. + */ + ! apply_filters( 'jetpack_holiday_chance_of_snow', true ) + ) { + return; + } + + /** + * Fires when the snow is falling. + * + * @since $$next-version$$ + */ + do_action( 'jetpack_stats_extra', 'holiday_snow', 'snowing' ); + + /** + * Filter the URL of the snowstorm script. + * + * @since $$next-version$$ + * + * @param string $snowstorm_url URL of the snowstorm script. + */ + $snowstorm_url = apply_filters( + 'jetpack_holiday_snow_js_url', + plugins_url( 'snowstorm.js', __FILE__ ) + ); + + wp_enqueue_script( + 'snowstorm', + $snowstorm_url, + array(), + \Automattic\Jetpack\Jetpack_Mu_Wpcom::PACKAGE_VERSION, + true + ); + } + + /** + * Add the option to the v1 API site settings endpoint. + * + * @param array $settings A single site's settings. + * @return array + */ + public static function add_option_api( $settings ) { + $settings[ self::HOLIDAY_SNOW_OPTION_NAME ] = self::is_snow_enabled(); + + return $settings; + } + + /** + * Update settings via public-api.wordpress.com. + * + * @param array $input Associative array of site settings to be updated. + * Cast and filtered based on documentation. + * @param array $unfiltered_input Associative array of site settings to be updated. + * Neither cast nor filtered. Contains raw input. + * @return array + */ + public static function update_option_api( $input, $unfiltered_input ) { + if ( isset( $unfiltered_input[ self::HOLIDAY_SNOW_OPTION_NAME ] ) ) { + $input[ self::HOLIDAY_SNOW_OPTION_NAME ] = (bool) $unfiltered_input[ self::HOLIDAY_SNOW_OPTION_NAME ]; + } + + return $input; + } + + /** + * Registers the settings section and fields. + * + * @return void + */ + public static function register_settings() { + register_setting( + 'general', + self::HOLIDAY_SNOW_OPTION_NAME, + array( + 'type' => 'boolean', + 'description' => esc_attr__( 'Show falling snow on my site', 'jetpack-mu-wpcom' ), + 'show_in_rest' => true, + 'default' => false, + 'sanitize_callback' => function ( $value ) { + return (bool) $value; + }, + ) + ); + + add_settings_field( + self::HOLIDAY_SNOW_OPTION_NAME, + esc_attr__( 'Snow', 'jetpack-mu-wpcom' ), + array( __CLASS__, 'option_field_display' ), + 'general', + 'default', + array( + 'label_for' => self::HOLIDAY_SNOW_OPTION_NAME, + ) + ); + } + + /** + * Renders the Snow settings markup. + * + * @return void + */ + public static function option_field_display() { + printf( + '', + esc_attr( self::HOLIDAY_SNOW_OPTION_NAME ), + checked( self::is_snow_enabled(), true, false ), + wp_kses( + __( 'Show falling snow on my site until January 4th.', 'jetpack-mu-wpcom' ), + array( + 'sup' => array(), + ) + ) + ); + } + + /** + * Fires whenever the holiday snow option is updated. + * Used to gather stats about modified options. + * + * @return void + */ + public static function holiday_snow_option_updated() { + /** This action is already documented in modules/widgets/gravatar-profile.php */ + do_action( 'jetpack_stats_extra', 'holiday_snow', 'toggle' ); + } +} diff --git a/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/snowstorm.js b/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/snowstorm.js new file mode 100644 index 0000000000000..1559e4e4df738 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/holiday-snow/snowstorm.js @@ -0,0 +1,29 @@ +/** @license + + DHTML Snowstorm! JavaScript-based snow for web pages + Making it snow on the internets since 2003. You're welcome. + ----------------------------------------------------------- + Version 1.44.20131215 (Previous rev: 1.44.20131208) + Copyright (c) 2007, Scott Schiller. All rights reserved. + Code provided under the BSD License + http://schillmania.com/projects/snowstorm/license.txt +*/ +var snowStorm=function(g,f){function k(a,d){isNaN(d)&&(d=0);return Math.random()*a+d}function x(){g.setTimeout(function(){a.start(!0)},20);a.events.remove(m?f:g,"mousemove",x)}function y(){(!a.excludeMobile||!D)&&x();a.events.remove(g,"load",y)}this.excludeMobile=this.autoStart=!0;this.flakesMax=128;this.flakesMaxActive=64;this.animationInterval=33;this.useGPU=!0;this.className=null;this.excludeMobile=!0;this.flakeBottom=null;this.followMouse=!0;this.snowColor="#fff";this.snowCharacter="•";this.snowStick= +!0;this.targetElement=null;this.useMeltEffect=!0;this.usePixelPosition=this.usePositionFixed=this.useTwinkleEffect=!1;this.freezeOnBlur=!0;this.flakeRightOffset=this.flakeLeftOffset=0;this.flakeHeight=this.flakeWidth=8;this.vMaxX=5;this.vMaxY=4;this.zIndex=0;var a=this,q,m=navigator.userAgent.match(/msie/i),E=navigator.userAgent.match(/msie 6/i),D=navigator.userAgent.match(/mobile|opera m(ob|in)/i),r=m&&"BackCompat"===f.compatMode||E,h=null,n=null,l=null,p=null,s=null,z=null,A=null,v=1,t=!1,w=!1, +u;a:{try{f.createElement("div").style.opacity="0.5"}catch(F){u=!1;break a}u=!0}var B=!1,C=f.createDocumentFragment();q=function(){function c(b){g.setTimeout(b,1E3/(a.animationInterval||20))}function d(a){return void 0!==h.style[a]?a:null}var e,b=g.requestAnimationFrame||g.webkitRequestAnimationFrame||g.mozRequestAnimationFrame||g.oRequestAnimationFrame||g.msRequestAnimationFrame||c;e=b?function(){return b.apply(g,arguments)}:null;var h;h=f.createElement("div");e={transform:{ie:d("-ms-transform"), +moz:d("MozTransform"),opera:d("OTransform"),webkit:d("webkitTransform"),w3:d("transform"),prop:null},getAnimationFrame:e};e.transform.prop=e.transform.w3||e.transform.moz||e.transform.webkit||e.transform.ie||e.transform.opera;h=null;return e}();this.timer=null;this.flakes=[];this.active=this.disabled=!1;this.meltFrameCount=20;this.meltFrames=[];this.setXY=function(c,d,e){if(!c)return!1;a.usePixelPosition||w?(c.style.left=d-a.flakeWidth+"px",c.style.top=e-a.flakeHeight+"px"):r?(c.style.right=100-100* +(d/h)+"%",c.style.top=Math.min(e,s-a.flakeHeight)+"px"):a.flakeBottom?(c.style.right=100-100*(d/h)+"%",c.style.top=Math.min(e,s-a.flakeHeight)+"px"):(c.style.right=100-100*(d/h)+"%",c.style.bottom=100-100*(e/l)+"%")};this.events=function(){function a(c){c=b.call(c);var d=c.length;e?(c[1]="on"+c[1],3b.vX?b.vX=0.2:0>b.vX&&-0.2b.vY&&(b.vY=0.2)};this.move=function(){var c=b.vX*v;b.x+=c;b.y+=b.vY*b.vAmp;b.x>=h||h-b.xc&&b.x-a.flakeLeftOffset<-a.flakeWidth&&(b.x=h-a.flakeWidth-1);b.refresh();l+p-b.y+a.flakeHeightb.type&&!b.melting&&0.998b.twinkleFrame?0.97a.flakesMaxActive)a.flakes[a.flakes.length-1].active=-1;a.targetElement.appendChild(C)};this.timerInit= +function(){a.timer=!0;a.snow()};this.init=function(){var c;for(c=0;c 'pineapple', 'carousel_display_exif' => 'pineapple', 'carousel_display_comments' => 'pineapple', + 'jetpack_holiday_snow_enabled' => false, 'jetpack_portfolio' => 'pineapple', 'jetpack_portfolio_posts_per_page' => 'pineapple', 'jetpack_testimonial' => 'pineapple',