Skip to content
Open
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/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 );
}
}
3 changes: 3 additions & 0 deletions projects/plugins/jetpack/changelog/pods-141-add-gate
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Significance: patch
Type: other
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