Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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/podcast/changelog/pods-141-add-gate
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Podcast: add product-access gate (Podcast_Gate::has_product_access) and grandfather sticker constant.
1 change: 1 addition & 0 deletions projects/packages/podcast/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.2",
"automattic/jetpack-plans": "@dev",
"automattic/jetpack-status": "@dev",
"automattic/jetpack-wp-build-polyfills": "@dev"
},
Expand Down
45 changes: 45 additions & 0 deletions projects/packages/podcast/src/class-podcast-gate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/**
* Podcast product-access gate.
*
* @package automattic/jetpack-podcast
*/

namespace Automattic\Jetpack\Podcast;

use Automattic\Jetpack\Current_Plan;

/**
* Premium podcast feature gate.
*
* Operates on the current blog. `Current_Plan::supports` reads request-scoped
* state, so callers that need to gate a different blog must `switch_to_blog`
* first.
*/
class Podcast_Gate {

const GRANDFATHER_STICKER = 'podcasting-grandfathered';

const FEATURE_SLUG = 'podcasting';

/**
* Whether the current blog can use Premium podcast features.
*
* @return bool
*/
public static function has_product_access(): bool {
$blog_id = get_current_blog_id();
if ( $blog_id <= 0 ) {
return false;
}

if (
function_exists( 'wpcom_has_blog_sticker' )
&& wpcom_has_blog_sticker( self::GRANDFATHER_STICKER, $blog_id )
) {
return true;
}

return (bool) Current_Plan::supports( self::FEATURE_SLUG );
}
}
2 changes: 0 additions & 2 deletions projects/packages/podcast/src/class-tracks.php
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ private static function maybe_record_status_change( int $old_value, int $new_val
// pattern as `Masterbar\Dashboard_Switcher_Tracking::get_plan()`.
$plan = class_exists( '\WPCOM_Store_API' )
? \WPCOM_Store_API::get_current_plan( (int) get_current_blog_id() )
// @phan-suppress-next-line PhanUndeclaredClassMethod -- Provided by the connection package on Atomic; not a hard dep.
: ( class_exists( '\Automattic\Jetpack\Current_Plan' ) ? \Automattic\Jetpack\Current_Plan::get() : array() );

self::record_event(
Expand Down Expand Up @@ -423,7 +422,6 @@ private static function record_event( string $event_name, array $properties, ?WP
}

if ( class_exists( '\Automattic\Jetpack\Tracking' ) ) {
// @phan-suppress-next-line PhanUndeclaredClassMethod -- Provided by the connection package on Atomic; not a hard dep.
return ( new \Automattic\Jetpack\Tracking() )->tracks_record_event( $user, $event_name, $properties );
}
} catch ( Throwable $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
Expand Down
68 changes: 68 additions & 0 deletions projects/packages/podcast/tests/php/Podcast_Gate_Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
/**
* Tests for the Podcast_Gate product-access helper.
*
* @package automattic/jetpack-podcast
*/

namespace Automattic\Jetpack\Podcast\Tests;

use Automattic\Jetpack\Current_Plan;
use Automattic\Jetpack\Podcast\Podcast_Gate;
use PHPUnit\Framework\Attributes\CoversClass;
use WorDBless\BaseTestCase;
use WorDBless\Options as WorDBless_Options;

/**
* @covers \Automattic\Jetpack\Podcast\Podcast_Gate
*/
#[CoversClass( Podcast_Gate::class )]
class Podcast_Gate_Test extends BaseTestCase {

protected function setUp(): void {
parent::setUp();
$GLOBALS['jetpack_podcast_test_stickers'] = array();
self::reset_active_plan_cache();
}

protected function tearDown(): void {
unset( $GLOBALS['jetpack_podcast_test_stickers'] );
WorDBless_Options::init()->clear_options();
self::reset_active_plan_cache();
parent::tearDown();
}

/**
* `Current_Plan::get()` memoizes for the request, leaking option writes between tests.
*/
private static function reset_active_plan_cache(): void {
$property = ( new \ReflectionClass( Current_Plan::class ) )->getProperty( 'active_plan_cache' );
// @todo Remove once we drop PHP < 8.1 support.
if ( PHP_VERSION_ID < 80100 ) {
$property->setAccessible( true );
}
$property->setValue( null, null );
}

public function test_grandfather_sticker_grants_access(): void {
$GLOBALS['jetpack_podcast_test_stickers'][ get_current_blog_id() ] = array( Podcast_Gate::GRANDFATHER_STICKER );

$this->assertTrue( Podcast_Gate::has_product_access() );
}

public function test_plan_supports_feature_grants_access(): void {
$plan = Current_Plan::PLAN_DATA['free'];
$plan['features']['active'] = array( Podcast_Gate::FEATURE_SLUG );
update_option( Current_Plan::PLAN_OPTION, $plan, true );

$this->assertTrue( Podcast_Gate::has_product_access() );
}

public function test_no_sticker_and_unsupported_plan_denies_access(): void {
$plan = Current_Plan::PLAN_DATA['free'];
$plan['features']['active'] = array();
update_option( Current_Plan::PLAN_OPTION, $plan, true );

$this->assertFalse( Podcast_Gate::has_product_access() );
}
}
10 changes: 10 additions & 0 deletions projects/packages/podcast/tests/php/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ function tracks_record_event( $user, $event_name, $properties = array() ) {
return true;
}
}

/**
* Mirror the jetpack-mu-wpcom sticker dispatcher.
*/
if ( ! function_exists( 'wpcom_has_blog_sticker' ) ) {
function wpcom_has_blog_sticker( $sticker, $blog_id ) {
$stickers = $GLOBALS['jetpack_podcast_test_stickers'][ $blog_id ] ?? array();
return in_array( $sticker, $stickers, true );
}
}
4 changes: 4 additions & 0 deletions projects/plugins/jetpack/changelog/pods-141-add-gate
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: other

Comment thread
robertbpugh marked this conversation as resolved.
Outdated
Comment: Podcast: composer.lock picks up jetpack-plans transitively from the podcast package; no plugin-level behavior change.
3 changes: 2 additions & 1 deletion projects/plugins/jetpack/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions projects/plugins/mu-wpcom-plugin/changelog/pods-141-add-gate
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Updated composer.lock to pick up jetpack-plans transitively via jetpack-podcast.
3 changes: 2 additions & 1 deletion projects/plugins/mu-wpcom-plugin/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions projects/plugins/wpcomsh/changelog/pods-141-add-gate
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Updated composer.lock to pick up jetpack-plans transitively via jetpack-podcast.
3 changes: 2 additions & 1 deletion projects/plugins/wpcomsh/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading