option = $option;
$this->advice_manager = $advice_manager;
$this->analytics = $analytics;
add_action( 'template_redirect', array( $this, 'handle' ) );
add_filter( 'cl_smart_advice_email_template_data', array( $this, 'inject_unsubscribe_links' ), 10, 5 );
add_filter( 'cl_smart_advice_email_allowed', array( $this, 'check_if_email_allowed' ), 10, 5 );
}
/**
* Get option instance.
*
* @return Option
*/
public function option() {
return $this->option;
}
/**
* Get advice manager instance.
*
* @return AdviceManager
*/
public function advice_manager() {
return $this->advice_manager;
}
/**
* Get analytics manager instance.
*
* @return Analytics
*/
public function analytics() {
return $this->analytics;
}
/**
* Exit.
*/
public function do_exit() {
exit();
}
/**
* Gives view path.
*
* @return string
*/
public function get_unsubscription_view() {
return CL_SMART_ADVICE_FOLDER_PATH . '/views/unsubscribe.php';
}
/**
* Handles request if it contains unsubscription data.
*
* @phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotValidated
* - Attribute presence checked in is_unsubscribe_page().
*
* @phpcs:disable WordPress.Security.NonceVerification.Recommended
* - Nonces are not applicable for this functionality.
*/
public function handle() {
global $wp_query;
$query_vars = is_array( $wp_query->query_vars ) ? $wp_query->query_vars : array();
$request_params = is_array( $_GET ) ? $_GET : array();
if ( ! isset( $query_vars['name'] ) || $this->page_unsubscribe_slug !== $query_vars['name'] ) {
return;
}
if ( ! isset( $request_params[ $this->param_token ] ) ) {
return;
}
$token = (string) sanitize_text_field( wp_unslash( $request_params[ $this->param_token ] ) );
$subscription = $this->find_subscription_by_token( $token );
if ( ! $subscription ) {
// Redirect to home page if subscription not found.
$this->redirect_to_home();
}
// Process unsubscription.
$this->process_unsubscribe( $subscription );
}
/**
* Retrieves the subscription object based on token value in request params.
*
* @param string $token Subscription token.
*
* @return ?Model
*/
public function find_subscription_by_token( $token ) {
$items = $this->get_all_subscriptions();
foreach ( $items as $item ) {
if ( $item->token === $token ) {
return $item;
}
}
return null;
}
/**
* Redirects to home page.
*/
protected function redirect_to_home() {
wp_safe_redirect( home_url() );
$this->do_exit();
}
/**
* Processes unsubscription and render message.
*
* @param Model $subscription Subscription model.
*/
protected function process_unsubscribe( $subscription ) {
// Update subscription status.
$this->unsubscribe( $subscription );
// Generate message to display.
$type = $subscription->advice_type;
$advice = $this->advice_manager()->get_advice_by_type( $type );
$description = '';
$detailed_description = '';
$analytics_data = $subscription->toArray();
if ( ! is_null( $advice ) ) {
$description = $advice->description;
$detailed_description = $advice->detailed_description;
}
require $this->get_unsubscription_view();
// Send analytics event.
if ( false === $subscription->is_imunify() ) {
$this->post_analytics_event( $analytics_data );
}
$this->do_exit();
}
/**
* Unsubscribe.
*
* @param Model $subscription model.
*
* @return void
*/
public function unsubscribe( $subscription ) {
$items = $this->get_all_subscriptions();
foreach ( $items as $item ) {
if ( $item->token === $subscription->token ) {
$item->unsubscribed_at = time();
}
}
$this->option()->save( 'subscriptions', $items );
}
/**
* Injects the unsubscribe links to the end of the email template.
*
* @param array $data The data to use in template.
* @param string $email Email address.
* @param string $user_type User type.
* @param string $advice_type Advice type.
* @param string $email_type Email type.
*
* @return array
*/
public function inject_unsubscribe_links( $data, $email, $user_type, $advice_type, $email_type ) {
// Generate fresh set of unsubscribe tokens.
$subscription_advice_type = $this->generate_subscription( $advice_type, $email, $email_type );
$data['unsubscribe_text'] = esc_html__( 'Don\'t show me this advice again.', 'cl-smart-advice' );
$data['unsubscribe_link'] = add_query_arg(
$this->param_token,
$subscription_advice_type->token,
home_url( $this->page_unsubscribe_slug )
);
return $data;
}
/**
* Generate new subscription.
*
* @param string $advice_type Advice type or 'all'.
* @param string $email Email address.
* @param string $email_type Email type.
*
* @return Model
*/
public function generate_subscription( $advice_type, $email, $email_type ) {
$model = null;
$tokens = array();
$subscriptions = $this->get_all_subscriptions();
foreach ( $subscriptions as $subscription ) {
$tokens[] = $subscription->token;
if (
$subscription->advice_type === $advice_type &&
$subscription->email === $email
) {
$model = $subscription;
if ( $email_type !== $model->email_type ) {
$model->email_type = $email_type;
$this->option()->save( 'subscriptions', $subscriptions );
}
}
}
if ( is_null( $model ) ) {
// Generate a unique token. Multiple attempts may be needed it token already exists.
do {
$token = wp_generate_password( 16, false );
} while ( in_array( $token, $tokens ) );
$model = ( new Model() )->fill(
array(
'advice_type' => $advice_type,
'email' => $email,
'token' => $token,
'created_at' => time(),
'email_type' => $email_type,
)
);
$subscriptions[] = $model;
$this->option()->save( 'subscriptions', $subscriptions );
}
return $model;
}
/**
* All subscriptions.
*
* @return array