Skip to content

Commit

Permalink
Merge pull request #764 from Kit/restrict-content-tag-login
Browse files Browse the repository at this point in the history
Restrict Content by Tag: `Require Login` option
  • Loading branch information
n7studios authored Jan 30, 2025
2 parents 5ae3b70 + f7e4cf5 commit 1f81530
Show file tree
Hide file tree
Showing 16 changed files with 309 additions and 122 deletions.
112 changes: 73 additions & 39 deletions admin/class-convertkit-admin-settings-restrict-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,51 @@ public function register_fields() {
)
);

// Restrict by Tag.
add_settings_field(
'subscribe_heading_tag',
__( 'Subscribe Heading', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-tags',
array(
'name' => 'subscribe_heading_tag',
'label_for' => 'subscribe_heading_tag',
'description' => array(
__( 'Displays text in a heading explaining why the content is only available to subscribers.', 'convertkit' ),
),
)
);

add_settings_field(
'subscribe_text_tag',
__( 'Subscribe Text', 'convertkit' ),
array( $this, 'textarea_callback' ),
$this->settings_key,
$this->name . '-tags',
array(
'name' => 'subscribe_text_tag',
'label_for' => 'subscribe_text_tag',
'description' => array(
__( 'Displays text explaining why the content is only available to subscribers.', 'convertkit' ),
),
)
);

add_settings_field(
'require_tag_login',
__( 'Require Login', 'convertkit' ),
array( $this, 'require_tag_login_callback' ),
$this->settings_key,
$this->name . '-tags',
array(
'name' => 'require_tag_login',
'label_for' => 'require_tag_login',
'label' => __( 'When checked, subscribers are sent a code in an email to login after being subscribed and tagged.', 'convertkit' ),
'description' => '',
)
);

// reCAPTCHA.
add_settings_field(
'recaptcha_site_key',
Expand Down Expand Up @@ -146,37 +191,6 @@ public function register_fields() {
)
);

// Restrict by Tag.
add_settings_field(
'subscribe_heading_tag',
__( 'Subscribe Heading', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-tags',
array(
'name' => 'subscribe_heading_tag',
'label_for' => 'subscribe_heading_tag',
'description' => array(
__( 'Displays text in a heading explaining why the content is only available to subscribers.', 'convertkit' ),
),
)
);

add_settings_field(
'subscribe_text_tag',
__( 'Subscribe Text', 'convertkit' ),
array( $this, 'textarea_callback' ),
$this->settings_key,
$this->name . '-tags',
array(
'name' => 'subscribe_text_tag',
'label_for' => 'subscribe_text_tag',
'description' => array(
__( 'Displays text explaining why the content is only available to subscribers.', 'convertkit' ),
),
)
);

// All.
add_settings_field(
'subscribe_button_label',
Expand Down Expand Up @@ -229,7 +243,7 @@ public function register_fields() {
__( 'Email Text', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_text',
'label_for' => 'email_text',
Expand All @@ -244,7 +258,7 @@ public function register_fields() {
__( 'Email Heading', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_heading',
'label_for' => 'email_heading',
Expand All @@ -259,7 +273,7 @@ public function register_fields() {
__( 'Email Field Description', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_description_text',
'label_for' => 'email_description_text',
Expand All @@ -274,7 +288,7 @@ public function register_fields() {
__( 'Email Button Label', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_button_label',
'label_for' => 'email_button_label',
Expand All @@ -289,7 +303,7 @@ public function register_fields() {
__( 'Email Check Heading', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_check_heading',
'label_for' => 'email_check_heading',
Expand All @@ -304,7 +318,7 @@ public function register_fields() {
__( 'Email Check Text', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'email_check_text',
'label_for' => 'email_check_text',
Expand All @@ -319,7 +333,7 @@ public function register_fields() {
__( 'No Access Text', 'convertkit' ),
array( $this, 'text_callback' ),
$this->settings_key,
$this->name . '-products',
$this->name,
array(
'name' => 'no_access_text',
'label_for' => 'no_access_text',
Expand Down Expand Up @@ -384,7 +398,7 @@ public function documentation_url() {
}

/**
* Renders the input for the Enable setting.
* Renders the input for the Permit Crawlers setting.
*
* @since 2.4.1
*
Expand All @@ -403,6 +417,26 @@ public function permit_crawlers_callback( $args ) {

}

/**
* Renders the input for the Require Login setting.
*
* @since 2.7.2
*
* @param array $args Setting field arguments (name,description).
*/
public function require_tag_login_callback( $args ) {

// Output field.
echo $this->get_checkbox_field( // phpcs:ignore WordPress.Security.EscapeOutput
$args['name'],
'on',
$this->settings->require_tag_login(), // phpcs:ignore WordPress.Security.EscapeOutput
$args['label'], // phpcs:ignore WordPress.Security.EscapeOutput
$args['description'] // phpcs:ignore WordPress.Security.EscapeOutput
);

}

/**
* Renders the input for the text setting.
*
Expand Down
6 changes: 3 additions & 3 deletions includes/class-convertkit-ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,14 @@ public function subscriber_authentication_send_code() {
// If an error occured, build the email form view with the error message.
if ( is_wp_error( $output_restrict_content->error ) ) {
ob_start();
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-email.php';
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-email.php';
$output = trim( ob_get_clean() );
wp_send_json_success( $output );
}

// Build authentication code view to return for output.
ob_start();
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-code.php';
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-code.php';
$output = trim( ob_get_clean() );
wp_send_json_success( $output );

Expand All @@ -209,7 +209,7 @@ public function subscriber_verification() {
// If an error occured, build the code form view with the error message.
if ( is_wp_error( $output_restrict_content->error ) ) {
ob_start();
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-code.php';
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-code.php';
$output = trim( ob_get_clean() );
wp_send_json_error( $output );
}
Expand Down
79 changes: 71 additions & 8 deletions includes/class-convertkit-output-restrict-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,42 @@ public function maybe_run_subscriber_authentication() {
break;

case 'tag':
// If require login is enabled, show the login screen.
if ( $this->restrict_content_settings->require_tag_login() ) {
// Tag the subscriber.
$result = $this->api->tag_subscribe( $this->resource_id, $email );

// Bail if an error occured.
if ( is_wp_error( $result ) ) {
$this->error = $result;
return;
}

// Send email to subscriber with a link to authenticate they have access to the email address submitted.
$result = $this->api->subscriber_authentication_send_code(
$email,
$this->get_url()
);

// Bail if an error occured.
if ( is_wp_error( $result ) ) {
$this->error = $result;
return;
}

// Clear any existing subscriber ID cookie, as the authentication flow has started by sending the email.
$subscriber = new ConvertKit_Subscriber();
$subscriber->forget();

// Store the token so it's included in the subscriber code form.
$this->token = $result;
break;
}

// If here, require login is disabled.
// Check reCAPTCHA, tag subscriber and assign subscriber ID integer to cookie
// without email link.

// If Google reCAPTCHA is enabled, check if the submission is spam.
if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) {
$response = wp_remote_post(
Expand Down Expand Up @@ -835,6 +871,12 @@ private function subscriber_has_access( $subscriber_id ) { // phpcs:ignore Gener
case 'tag':
// If the subscriber ID is numeric, check using get_subscriber_tags().
if ( is_numeric( $subscriber_id ) ) {
// If require login is enabled, only a signed subscriber ID is accepted, as this is generated
// via the subscriber verify email flow.
if ( $this->restrict_content_settings->require_tag_login() ) {
return false;
}

return $this->subscriber_has_access_to_tag_by_subscriber_id( $subscriber_id, absint( $this->resource_id ) );
}

Expand Down Expand Up @@ -1129,17 +1171,21 @@ private function get_call_to_action( $post_id ) { // phpcs:ignore Generic.CodeAn

}

// Output code form if this request is after the user entered their email address,
// which means we're going through the authentication flow.
if ( $this->in_authentication_flow() ) { // phpcs:ignore WordPress.Security.NonceVerification
ob_start();
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/code.php';
return trim( ob_get_clean() );
}

// This is deliberately a switch statement, because we will likely add in support
// for restrict by tag and form later.
switch ( $this->resource_type ) {
case 'product':
// Output product code form if this request is after the user entered their email address,
// which means we're going through the authentication flow.
if ( $this->in_authentication_flow() ) { // phpcs:ignore WordPress.Security.NonceVerification
ob_start();
include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-code.php';
return trim( ob_get_clean() );
}
// Get header and text from settings for Products.
$heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading' );
$text = $this->restrict_content_settings->get_by_key( 'subscribe_text' );

// Output product restricted message and email form.
// Get Product.
Expand All @@ -1159,7 +1205,7 @@ private function get_call_to_action( $post_id ) { // phpcs:ignore Generic.CodeAn
'wp_footer',
function () {

include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal.php';
include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php';

}
);
Expand All @@ -1172,6 +1218,23 @@ function () {
return trim( ob_get_clean() );

case 'tag':
// Get header and text from settings for Tags.
$heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading_tag' );
$text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' );

// If require login is enabled and scripts are enabled, output the email login form in a modal, which will be displayed
// when the 'log in' link is clicked.
if ( $this->restrict_content_settings->require_tag_login() && ! $this->settings->scripts_disabled() ) {
add_action(
'wp_footer',
function () {

include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php';

}
);
}

// Enqueue Google reCAPTCHA JS if site and secret keys specified.
if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) {
add_filter(
Expand Down
22 changes: 17 additions & 5 deletions includes/class-convertkit-settings-restrict-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ public function permit_crawlers() {

}

/**
* Returns whether login by email is required for Member Content by Tag functionality.
*
* @since 2.7.2
*
* @return bool
*/
public function require_tag_login() {

return ( $this->settings['require_tag_login'] === 'on' ? true : false );

}

/**
* Returns the reCAPTCHA Site Key Plugin setting.
*
Expand Down Expand Up @@ -195,18 +208,17 @@ public function get_defaults() {
// Permit Crawlers.
'permit_crawlers' => '',

// Google reCAPTCHA.
'recaptcha_site_key' => '',
'recaptcha_secret_key' => '',
'recaptcha_minimum_score' => '0.5',

// Restrict by Product.
'subscribe_heading' => __( 'Read this post with a premium subscription', 'convertkit' ),
'subscribe_text' => __( 'This post is only available to premium subscribers. Join today to get access to all posts.', 'convertkit' ),

// Restrict by Tag.
'subscribe_heading_tag' => __( 'Subscribe to keep reading', 'convertkit' ),
'subscribe_text_tag' => __( 'This post is free to read but only available to subscribers. Join today to get access to all posts.', 'convertkit' ),
'require_tag_login' => '', // blank|on.
'recaptcha_site_key' => '',
'recaptcha_secret_key' => '',
'recaptcha_minimum_score' => '0.5',

// All.
'subscribe_button_label' => __( 'Subscribe', 'convertkit' ),
Expand Down
1 change: 0 additions & 1 deletion resources/frontend/js/restrict-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ document.addEventListener(

function convertKitRestrictContentTagFormSubmit( token ) {

console.log( token );
document.getElementById( 'convertkit-restrict-content-form' ).submit();

}
Expand Down
Loading

0 comments on commit 1f81530

Please sign in to comment.