Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.00% covered (warning)
68.00%
34 / 50
62.50% covered (warning)
62.50%
5 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_Online_Subscription_Service
70.83% covered (warning)
70.83%
34 / 48
62.50% covered (warning)
62.50%
5 / 8
42.77
0.00% covered (danger)
0.00%
0 / 1
 available
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 visitor_can_view_content
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 get_subscriber_email
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 is_current_user_subscribed
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
5
 is_current_user_pending_subscriber
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 user_can_view_content
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 abbreviate_subscriptions
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
8.05
 get_site_id
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * This subscription service is used when a subscriber is online
4 *
5 * @package Automattic\Jetpack\Extensions\Premium_Content
6 */
7
8namespace Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service;
9
10if ( ! defined( 'ABSPATH' ) ) {
11    exit( 0 );
12}
13
14/**
15 * Class WPCOM_Offline_Subscription_Service
16 *
17 * @package Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service
18 */
19class WPCOM_Online_Subscription_Service extends Jetpack_Token_Subscription_Service {
20
21    /**
22     * Is available()
23     *
24     * @return bool
25     */
26    public static function available() {
27        // Return available if the user is logged in and we are on WPCOM.
28        return defined( 'IS_WPCOM' ) && IS_WPCOM && is_user_logged_in();
29    }
30
31    /**
32     * Lookup users subscriptions for a site and determine if the user has a valid subscription to match the plan ID
33     *
34     * @param array    $valid_plan_ids .
35     * @param string   $access_level .
36     * @param int|null $post_id Post to gate against. Defaults to the loop post, which is only right while rendering it.
37     *
38     * @return bool
39     */
40    public function visitor_can_view_content( $valid_plan_ids, $access_level, $post_id = null ) {
41        $is_blog_subscriber = $this->is_current_user_subscribed();
42
43        return $this->user_can_view_content( $valid_plan_ids, $access_level, $is_blog_subscriber, null === $post_id ? get_the_ID() : $post_id );
44    }
45
46    /**
47     * Retrieves the email of the currently authenticated subscriber.
48     *
49     * This function checks if the current user has an active subscription. If the user is subscribed,
50     * their email is returned. Otherwise, it returns an empty string to indicate no active subscription.
51     *
52     * @return string The email address of the subscribed user or an empty string if not subscribed.
53     */
54    public function get_subscriber_email() {
55        if ( ! is_user_logged_in() ) {
56            return '';
57        }
58        return wp_get_current_user()->user_email;
59    }
60
61    /**
62     * Returns true if the current authenticated user is subscribed to the current site,
63     * either via an active email subscription or by following it in the Reader.
64     *
65     * @return bool
66     */
67    public function is_current_user_subscribed(): bool {
68        include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php';
69        $email                = wp_get_current_user()->user_email;
70        $subscriber_object    = \Blog_Subscriber::get( $email );
71        $blog_id              = $this->get_site_id();
72        $has_active_email_sub = false;
73        if ( ! empty( $subscriber_object ) ) {
74            $subscription_status  = \Blog_Subscription::get_subscription_status_for_blog( $subscriber_object, $blog_id );
75            $has_active_email_sub = 'active' === $subscription_status;
76        }
77
78        $is_following = ! $has_active_email_sub && function_exists( 'wpcom_subs_is_subscribed' ) && wpcom_subs_is_subscribed(
79            array(
80                'user_id' => get_current_user_id(),
81                'blog_id' => $blog_id,
82            )
83        );
84
85        return $has_active_email_sub || $is_following;
86    }
87
88    /**
89     * Returns true if the current authenticated user has a pending subscription to the current site.
90     *
91     * @return bool
92     */
93    public function is_current_user_pending_subscriber(): bool {
94        include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php';
95        $email             = wp_get_current_user()->user_email;
96        $subscriber_object = \Blog_Subscriber::get( $email );
97        if ( empty( $subscriber_object ) ) {
98            return false;
99        }
100        $blog_id             = $this->get_site_id();
101        $subscription_status = \Blog_Subscription::get_subscription_status_for_blog( $subscriber_object, $blog_id );
102        if ( self::BLOG_SUB_PENDING !== $subscription_status ) {
103            return false;
104        }
105        return true;
106    }
107
108    /**
109     * Lookup users subscriptions for a site and determine if the user has a valid subscription to match the plan ID
110     *
111     * @param array  $valid_plan_ids .
112     * @param string $access_level .
113     * @param bool   $is_blog_subscriber .
114     * @param int    $post_id .
115     *
116     * @return bool
117     */
118    protected function user_can_view_content( $valid_plan_ids, $access_level, $is_blog_subscriber, $post_id ) {
119        $user_id = is_user_logged_in() ? wp_get_current_user()->ID : $this->user_id;
120        /**
121         * Filter the subscriptions attached to a specific user on a given site.
122         *
123         * @since 9.4.0
124         *
125         * @param array $subscriptions Array of subscriptions.
126         * @param int   $user_id The user's ID.
127         * @param int   $site_id ID of the current site.
128         */
129        $subscriptions = apply_filters( 'earn_get_user_subscriptions_for_site_id', array(), $user_id, $this->get_site_id() );
130        // format the subscriptions so that they can be validated.
131        $subscriptions      = self::abbreviate_subscriptions( $subscriptions );
132        $is_paid_subscriber = static::validate_subscriptions( $valid_plan_ids, $subscriptions );
133
134        return $this->user_has_access( $access_level, $is_blog_subscriber, $is_paid_subscriber, $post_id, $subscriptions );
135    }
136
137    /**
138     * Report the subscriptions as an ID => [ 'end_date' => ]. mapping
139     *
140     * @param array $subscriptions_from_bd .
141     *
142     * @return array<int, object>
143     */
144    public static function abbreviate_subscriptions( $subscriptions_from_bd ) {
145        $subscriptions = array();
146        foreach ( $subscriptions_from_bd as $subscription ) {
147            // We are picking the expiry date that is the most in the future.
148            if (
149                'active' === $subscription['status'] && (
150                    ! isset( $subscriptions[ $subscription['product_id'] ] ) ||
151                    empty( $subscription['end_date'] ) || // Special condition when subscription has no expiry date - we will default to a year from now for the purposes of the token.
152                    strtotime( $subscription['end_date'] ) > strtotime( (string) $subscriptions[ $subscription['product_id'] ]->end_date )
153                )
154            ) {
155                $subscriptions[ $subscription['product_id'] ]           = new \stdClass();
156                $subscriptions[ $subscription['product_id'] ]->end_date = empty( $subscription['end_date'] ) ? gmdate( 'Y-m-d H:i:s', ( time() + 365 * 24 * 3600 ) ) : $subscription['end_date'];
157                if ( ! empty( $subscription['is_comp'] ) ) {
158                    $subscriptions[ $subscription['product_id'] ]->is_comp = true;
159                }
160            }
161        }
162        return $subscriptions;
163    }
164
165    /**
166     * Get the site ID.
167     *
168     * @return int The site ID.
169     */
170    public function get_site_id() {
171        return get_current_blog_id();
172    }
173}