Skip to content

Commit b5b8cd9

Browse files
miguelpeixedkoochickenn00dle
authored
feat(content-gate): content rules (#4265)
Co-authored-by: Derrick Koo <dkoo@users.noreply.github.com> Co-authored-by: Rasmy Nguyen <raz@automattic.com>
1 parent b0dff93 commit b5b8cd9

File tree

20 files changed

+949
-328
lines changed

20 files changed

+949
-328
lines changed

includes/collections/class-collection-category-taxonomy.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public static function init() {
7676
add_action( self::get_taxonomy() . '_edit_form_fields', [ __CLASS__, 'edit_term_meta_fields' ] );
7777
add_action( 'created_' . self::get_taxonomy(), [ __CLASS__, 'save_term_meta' ] );
7878
add_action( 'edited_' . self::get_taxonomy(), [ __CLASS__, 'save_term_meta' ] );
79+
add_filter( 'newspack_content_gate_supported_taxonomies', [ __CLASS__, 'add_support_for_content_gates' ] );
7980
}
8081

8182
/**
@@ -208,4 +209,18 @@ public static function save_term_meta( $term_id ) {
208209
}
209210
// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
210211
}
212+
213+
/**
214+
* Add support for content gates.
215+
*
216+
* @param array $taxonomies Taxonomies.
217+
* @return array Taxonomies.
218+
*/
219+
public static function add_support_for_content_gates( $taxonomies ) {
220+
$taxonomies[] = [
221+
'slug' => self::get_taxonomy(),
222+
'label' => __( 'Collection Categories', 'newspack-plugin' ),
223+
];
224+
return $taxonomies;
225+
}
211226
}

includes/content-gate/class-access-rules.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static function register_rule( $config ) {
5050
if ( ! isset( $config['id'] ) ) {
5151
return new \WP_Error( 'invalid_rule_id', __( 'Rule ID is required.', 'newspack' ) );
5252
}
53-
if ( isset( self::$registered_rules[ $config['id'] ] ) ) {
53+
if ( isset( self::$rules[ $config['id'] ] ) ) {
5454
return new \WP_Error( 'rule_already_registered', __( 'Rule already registered.', 'newspack' ) );
5555
}
5656
if ( ! isset( $config['callback'] ) ) {
@@ -62,7 +62,7 @@ public static function register_rule( $config ) {
6262
$rule = wp_parse_args(
6363
$config,
6464
[
65-
'label' => ucwords( str_replace( '_', ' ', $config['id'] ) ),
65+
'name' => ucwords( str_replace( '_', ' ', $config['id'] ) ),
6666
'description' => '',
6767
'default' => ! empty( $config['options'] ) ? [] : '',
6868
'options' => [],

includes/content-gate/class-content-gate.php

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -272,54 +272,19 @@ public static function register_meta() {
272272
}
273273
}
274274

275-
/**
276-
* Get the post types that can be restricted.
277-
*/
278-
public static function get_available_post_types() {
279-
$available_post_types = array_values(
280-
array_map(
281-
function( $post_type ) {
282-
return [
283-
'name' => $post_type->name,
284-
'label' => $post_type->label,
285-
];
286-
},
287-
get_post_types(
288-
[
289-
'public' => true,
290-
'show_in_rest' => true,
291-
'_builtin' => false,
292-
],
293-
'objects'
294-
)
295-
)
296-
);
297-
298-
return apply_filters(
299-
'newspack_content_gate_supported_post_types',
300-
array_merge(
301-
[
302-
[
303-
'name' => 'post',
304-
'label' => 'Posts',
305-
],
306-
[
307-
'name' => 'page',
308-
'label' => 'Pages',
309-
],
310-
],
311-
$available_post_types
312-
)
313-
);
314-
}
315-
316275
/**
317276
* Redirect the custom gate CPT to the Content Gating wizard
318277
*/
319278
public static function redirect_cpt() {
320279
global $pagenow;
321280
if ( 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && self::GATE_CPT === $_GET['post_type'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
322-
\wp_safe_redirect( \admin_url( 'admin.php?page=newspack-audience#/content-gating' ) );
281+
$redirect = \admin_url( 'admin.php?page=newspack-audience#/content-gating' );
282+
283+
// Once the feature is fully released, this should be the default redirect.
284+
if ( defined( 'NEWSPACK_CONTENT_GATES' ) && NEWSPACK_CONTENT_GATES ) {
285+
$redirect = \admin_url( 'admin.php?page=newspack-audience-content-gates' );
286+
}
287+
\wp_safe_redirect( $redirect );
323288
exit;
324289
}
325290
}
@@ -381,7 +346,7 @@ public static function enqueue_block_editor_assets() {
381346
'plans' => Memberships::get_plans(),
382347
'gate_plans' => Memberships::get_gate_plans( get_the_ID() ),
383348
'edit_plan_gate_url' => Memberships::get_edit_plan_gate_url(),
384-
'post_types' => self::get_available_post_types(),
349+
'post_types' => Content_Restriction_Control::get_available_post_types(),
385350
'access_rules' => Access_Rules::get_access_rules(),
386351
]
387352
);
@@ -772,10 +737,58 @@ public static function get_gate( $id ) {
772737
'metering' => Metering::get_metering_settings( $post->ID ),
773738
'priority' => (int) get_post_meta( $post->ID, 'gate_priority', true ),
774739
'access_rules' => Access_Rules::get_post_access_rules( $post->ID ),
775-
'content_rules' => [],
740+
'content_rules' => self::get_post_content_rules( $post->ID ),
776741
];
777742
}
778743

744+
/**
745+
* Get the content rules.
746+
*
747+
* @return array The content rules.
748+
*/
749+
public static function get_content_rules() {
750+
$content_rules = [
751+
'post_types' => [
752+
'name' => __( 'Post Types', 'newspack-plugin' ),
753+
'options' => Content_Restriction_Control::get_available_post_types(),
754+
'default' => [ 'post' ],
755+
],
756+
];
757+
$available_taxonomies = Content_Restriction_Control::get_available_taxonomies();
758+
foreach ( $available_taxonomies as $taxonomy ) {
759+
$content_rules[ $taxonomy['slug'] ] = [
760+
'name' => $taxonomy['label'],
761+
'default' => [],
762+
];
763+
}
764+
765+
return $content_rules;
766+
}
767+
768+
/**
769+
* Get the content rules for a post.
770+
*
771+
* @param int $post_id Post ID.
772+
*
773+
* @return array The content rules.
774+
*/
775+
public static function get_post_content_rules( $post_id ) {
776+
$rules = \get_post_meta( $post_id, 'content_rules', true );
777+
return $rules ? $rules : [];
778+
}
779+
780+
/**
781+
* Update content rules for bypassing a content gate.
782+
*
783+
* @param int $post_id Post ID.
784+
* @param array $rules Array of post content rules.
785+
*
786+
* @return void
787+
*/
788+
public static function update_post_content_rules( $post_id, $rules ) {
789+
\update_post_meta( $post_id, 'content_rules', $rules );
790+
}
791+
779792
/**
780793
* Update single gate setting
781794
*
@@ -856,7 +869,8 @@ public static function update_gate_settings( $id, $gate ) {
856869
// Update access rules.
857870
Access_Rules::update_post_access_rules( $id, $gate['access_rules'] );
858871

859-
// TODO: Update content rules.
872+
// Update content rules.
873+
self::update_post_content_rules( $id, $gate['content_rules'] );
860874

861875
return self::get_gate( $id );
862876
}

includes/content-gate/class-content-restriction-control.php

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,71 @@ public static function init() {
2121
add_filter( 'newspack_is_post_restricted', [ __CLASS__, 'is_post_restricted' ], 10, 2 );
2222
}
2323

24+
/**
25+
* Get the post types that can be restricted.
26+
*/
27+
public static function get_available_post_types() {
28+
$available_post_types = array_values(
29+
array_map(
30+
function( $post_type ) {
31+
return [
32+
'value' => $post_type->name,
33+
'label' => $post_type->label,
34+
];
35+
},
36+
get_post_types(
37+
[
38+
'public' => true,
39+
'show_in_rest' => true,
40+
'_builtin' => false,
41+
],
42+
'objects'
43+
)
44+
)
45+
);
46+
47+
return apply_filters(
48+
'newspack_content_gate_supported_post_types',
49+
array_merge(
50+
[
51+
[
52+
'value' => 'post',
53+
'label' => 'Posts',
54+
],
55+
[
56+
'value' => 'page',
57+
'label' => 'Pages',
58+
],
59+
],
60+
$available_post_types
61+
)
62+
);
63+
}
64+
65+
/**
66+
* Get the taxonomies that can be restricted.
67+
* By default, this includes all public taxonomies that apply to available post types.
68+
*
69+
* @return array Array of taxonomies.
70+
*/
71+
public static function get_available_taxonomies() {
72+
$available_taxonomies = [
73+
[
74+
'slug' => 'category',
75+
'label' => 'Categories',
76+
],
77+
[
78+
'slug' => 'post_tag',
79+
'label' => 'Tags',
80+
],
81+
];
82+
83+
return apply_filters(
84+
'newspack_content_gate_supported_taxonomies',
85+
$available_taxonomies
86+
);
87+
}
88+
2489
/**
2590
* Get post gates.
2691
*
@@ -32,15 +97,16 @@ public static function get_post_gates( $post_id = null ) {
3297
$post_id = $post_id ?? \get_the_ID();
3398
$post_type = \get_post_type( $post_id );
3499
$categories = \wp_get_post_categories( $post_id );
35-
$tags = \wp_get_post_tags( 2742, [ 'fields' => 'ids' ] );
100+
$tags = \wp_get_post_tags( $post_id, [ 'fields' => 'ids' ] );
36101

37102
$gate_post_ids = [];
38103
$gates = Content_Gate::get_gates();
39104

40105
foreach ( $gates as $gate ) {
41-
$gate_post_types = \get_post_meta( $gate->ID, 'post_types', true );
42-
$gate_categories = \wp_get_post_categories( $gate->ID );
43-
$gate_tags = \wp_get_post_tags( $gate->ID, [ 'fields' => 'ids' ] );
106+
// TODO: Change this to read from the gate rules.
107+
$gate_post_types = \get_post_meta( $gate['id'], 'post_types', true );
108+
$gate_categories = \wp_get_post_categories( $gate['id'] );
109+
$gate_tags = \wp_get_post_tags( $gate['id'], [ 'fields' => 'ids' ] );
44110

45111
if ( empty( $gate_post_types ) || ! in_array( $post_type, $gate_post_types, true ) ) {
46112
continue;
@@ -51,7 +117,7 @@ public static function get_post_gates( $post_id = null ) {
51117
if ( ! empty( $gate_tags ) && empty( array_intersect( $gate_tags, $tags ) ) ) {
52118
continue;
53119
}
54-
$gate_post_ids[] = $gate->ID;
120+
$gate_post_ids[] = $gate['id'];
55121
}
56122

57123
return $gate_post_ids;

0 commit comments

Comments
 (0)