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
40.51
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
1
 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     *
37     * @return bool
38     */
39    public function visitor_can_view_content( $valid_plan_ids, $access_level ) {
40        $is_blog_subscriber = $this->is_current_user_subscribed();
41
42        return $this->user_can_view_content( $valid_plan_ids, $access_level, $is_blog_subscriber, get_the_ID() );
43    }
44
45    /**
46     * Retrieves the email of the currently authenticated subscriber.
47     *
48     * This function checks if the current user has an active subscription. If the user is subscribed,
49     * their email is returned. Otherwise, it returns an empty string to indicate no active subscription.
50     *
51     * @return string The email address of the subscribed user or an empty string if not subscribed.
52     */
53    public function get_subscriber_email() {
54        if ( ! is_user_logged_in() ) {
55            return '';
56        }
57        return wp_get_current_user()->user_email;
58    }
59
60    /**
61     * Returns true if the current authenticated user is subscribed to the current site,
62     * either via an active email subscription or by following it in the Reader.
63     *
64     * @return bool
65     */
66    public function is_current_user_subscribed(): bool {
67        include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php';
68        $email                = wp_get_current_user()->user_email;
69        $subscriber_object    = \Blog_Subscriber::get( $email );
70        $blog_id              = $this->get_site_id();
71        $has_active_email_sub = false;
72        if ( ! empty( $subscriber_object ) ) {
73            $subscription_status  = \Blog_Subscription::get_subscription_status_for_blog( $subscriber_object, $blog_id );
74            $has_active_email_sub = 'active' === $subscription_status;
75        }
76
77        $is_following = ! $has_active_email_sub && function_exists( 'wpcom_subs_is_subscribed' ) && wpcom_subs_is_subscribed(
78            array(
79                'user_id' => get_current_user_id(),
80                'blog_id' => $blog_id,
81            )
82        );
83
84        return $has_active_email_sub || $is_following;
85    }
86
87    /**
88     * Returns true if the current authenticated user has a pending subscription to the current site.
89     *
90     * @return bool
91     */
92    public function is_current_user_pending_subscriber(): bool {
93        include_once WP_CONTENT_DIR . '/mu-plugins/email-subscriptions/subscriptions.php';
94        $email             = wp_get_current_user()->user_email;
95        $subscriber_object = \Blog_Subscriber::get( $email );
96        if ( empty( $subscriber_object ) ) {
97            return false;
98        }
99        $blog_id             = $this->get_site_id();
100        $subscription_status = \Blog_Subscription::get_subscription_status_for_blog( $subscriber_object, $blog_id );
101        if ( self::BLOG_SUB_PENDING !== $subscription_status ) {
102            return false;
103        }
104        return true;
105    }
106
107    /**
108     * Lookup users subscriptions for a site and determine if the user has a valid subscription to match the plan ID
109     *
110     * @param array  $valid_plan_ids .
111     * @param string $access_level .
112     * @param bool   $is_blog_subscriber .
113     * @param int    $post_id .
114     *
115     * @return bool
116     */
117    protected function user_can_view_content( $valid_plan_ids, $access_level, $is_blog_subscriber, $post_id ) {
118        $user_id = is_user_logged_in() ? wp_get_current_user()->ID : $this->user_id;
119        /**
120         * Filter the subscriptions attached to a specific user on a given site.
121         *
122         * @since 9.4.0
123         *
124         * @param array $subscriptions Array of subscriptions.
125         * @param int   $user_id The user's ID.
126         * @param int   $site_id ID of the current site.
127         */
128        $subscriptions = apply_filters( 'earn_get_user_subscriptions_for_site_id', array(), $user_id, $this->get_site_id() );
129        // format the subscriptions so that they can be validated.
130        $subscriptions      = self::abbreviate_subscriptions( $subscriptions );
131        $is_paid_subscriber = static::validate_subscriptions( $valid_plan_ids, $subscriptions );
132
133        return $this->user_has_access( $access_level, $is_blog_subscriber, $is_paid_subscriber, $post_id, $subscriptions );
134    }
135
136    /**
137     * Report the subscriptions as an ID => [ 'end_date' => ]. mapping
138     *
139     * @param array $subscriptions_from_bd .
140     *
141     * @return array<int, object>
142     */
143    public static function abbreviate_subscriptions( $subscriptions_from_bd ) {
144        $subscriptions = array();
145        foreach ( $subscriptions_from_bd as $subscription ) {
146            // We are picking the expiry date that is the most in the future.
147            if (
148                'active' === $subscription['status'] && (
149                    ! isset( $subscriptions[ $subscription['product_id'] ] ) ||
150                    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.
151                    strtotime( $subscription['end_date'] ) > strtotime( (string) $subscriptions[ $subscription['product_id'] ]->end_date )
152                )
153            ) {
154                $subscriptions[ $subscription['product_id'] ]           = new \stdClass();
155                $subscriptions[ $subscription['product_id'] ]->end_date = empty( $subscription['end_date'] ) ? gmdate( 'Y-m-d H:i:s', ( time() + 365 * 24 * 3600 ) ) : $subscription['end_date'];
156                if ( ! empty( $subscription['is_comp'] ) ) {
157                    $subscriptions[ $subscription['product_id'] ]->is_comp = true;
158                }
159            }
160        }
161        return $subscriptions;
162    }
163
164    /**
165     * Get the site ID.
166     *
167     * @return int The site ID.
168     */
169    public function get_site_id() {
170        return get_current_blog_id();
171    }
172}