Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.31% covered (warning)
78.31%
65 / 83
69.23% covered (warning)
69.23%
9 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Ads_Settings_Home
81.25% covered (warning)
81.25%
65 / 80
69.23% covered (warning)
69.23%
9 / 13
46.02
0.00% covered (danger)
0.00%
0 / 1
 init
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 is_on_monetize_page
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 is_moved_off_settings
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 get_url
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 filter_configure_url
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 add_script_data
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
6.02
 enqueue_tracks_transport
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 is_tab_request
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 can_use_analytics
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 add_tracks_identity
30.77% covered (danger)
30.77%
4 / 13
0.00% covered (danger)
0.00%
0 / 1
9.31
 is_consolidation_on
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 get_dashboard_data
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
 get_upgrade_url
88.89% covered (warning)
88.89%
16 / 18
0.00% covered (danger)
0.00%
0 / 1
4.02
1<?php
2/**
3 * Where the Ads settings live once they leave Jetpack › Settings.
4 *
5 * @package automattic/jetpack
6 */
7
8use Automattic\Jetpack\Connection\Manager as Connection_Manager;
9use Automattic\Jetpack\Current_Plan;
10use Automattic\Jetpack\Monetize\Dashboard;
11use Automattic\Jetpack\My_Jetpack\Initializer;
12use Automattic\Jetpack\Partner;
13use Automattic\Jetpack\Redirect;
14use Automattic\Jetpack\Status;
15use Automattic\Jetpack\Status\Host;
16use Automattic\Jetpack\Terms_Of_Service;
17use Automattic\Jetpack\Tracking;
18
19if ( ! defined( 'ABSPATH' ) ) {
20    exit( 0 );
21}
22
23/**
24 * Picks this site's home for the Ads settings, for the Settings app, the Monetize page and configure_url.
25 *
26 * @since $$next-version$$
27 */
28class Jetpack_Ads_Settings_Home {
29
30    /**
31     * Monetize › Settings, for a Monetize package older than `Dashboard::get_tab_url()`.
32     *
33     * @var string
34     */
35    const MONETIZE_SETTINGS_PATH = 'admin.php?page=jetpack-monetize&p=%2F%3Ftab%3Dsettings';
36
37    /**
38     * Hook the configure URL and the script data.
39     *
40     * @return void
41     */
42    public static function init() {
43        add_filter( 'jetpack_module_configuration_url_wordads', array( __CLASS__, 'filter_configure_url' ) );
44        add_filter( 'jetpack_admin_js_script_data', array( __CLASS__, 'add_script_data' ) );
45        add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_tracks_transport' ) );
46    }
47
48    /**
49     * Whether the Monetize page shows the Ads settings. Needs no admin menu, so REST requests agree.
50     *
51     * @return bool
52     */
53    public static function is_on_monetize_page() {
54        return class_exists( Dashboard::class )
55            && Dashboard::is_enabled()
56            && Jetpack::is_module_active( 'monetize' )
57            // The module needs a connection: it stays listed as active, but never loads offline or disconnected.
58            && Jetpack::is_connection_ready()
59            && ! ( new Status() )->is_offline_mode();
60    }
61
62    /**
63     * Whether Jetpack › Settings drops its Ads card for Monetize › Settings.
64     *
65     * @return bool
66     */
67    public static function is_moved_off_settings() {
68        return self::is_consolidation_on() && self::is_on_monetize_page();
69    }
70
71    /**
72     * Monetize › Settings, or null where the Monetize page doesn't show the Ads settings.
73     *
74     * @return string|null
75     */
76    public static function get_url() {
77        if ( ! self::is_on_monetize_page() ) {
78            return null;
79        }
80
81        return method_exists( Dashboard::class, 'get_tab_url' )
82            ? Dashboard::get_tab_url( 'settings' )
83            : admin_url( self::MONETIZE_SETTINGS_PATH );
84    }
85
86    /**
87     * Point the WordAds configure URL at its home.
88     *
89     * @param string $url Jetpack's settings-search default.
90     * @return string
91     */
92    public static function filter_configure_url( $url ) {
93        return self::get_url() ?? $url;
94    }
95
96    /**
97     * Add the tab's data on the Monetize page, and the URL Jetpack › Settings points to once it drops its card.
98     *
99     * @param array $data Script data.
100     * @return array
101     */
102    public static function add_script_data( $data ) {
103        $is_tab_request = self::is_tab_request();
104        $is_moved       = self::is_moved_off_settings();
105        if ( ! $is_tab_request && ! $is_moved ) {
106            return $data;
107        }
108
109        if ( ! is_array( $data ) ) {
110            $data = array();
111        }
112
113        if ( $is_moved ) {
114            $data['monetize']['adsSettingsUrl'] = self::get_url();
115        }
116
117        if ( $is_tab_request ) {
118            $data['monetize']['adsSettings'] = self::get_dashboard_data();
119            $data                            = self::add_tracks_identity( $data );
120        }
121
122        return $data;
123    }
124
125    /**
126     * Load the Tracks script on the tab, as Jetpack › Settings does; other packages load it only for some plans.
127     *
128     * @return void
129     */
130    public static function enqueue_tracks_transport() {
131        if ( self::is_tab_request() && self::can_use_analytics() ) {
132            wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true );
133        }
134    }
135
136    /**
137     * Whether this request opens the Monetize page that holds the Ads settings.
138     *
139     * @return bool
140     */
141    private static function is_tab_request() {
142        // Do not reorder: is_on_monetize_page() checks that Dashboard exists.
143        return self::is_on_monetize_page() && Dashboard::is_dashboard_request();
144    }
145
146    /**
147     * Whether the site and user allow Tracks, as on Jetpack's other admin pages.
148     *
149     * @return bool
150     */
151    private static function can_use_analytics() {
152        $tracking = new Tracking( 'jetpack', new Connection_Manager( 'jetpack' ) );
153
154        return $tracking->should_enable_tracking( new Terms_Of_Service(), new Status() );
155    }
156
157    /**
158     * Add the connected WordPress.com user for Tracks, unless another package already did.
159     *
160     * @param array $data Script data.
161     * @return array
162     */
163    private static function add_tracks_identity( $data ) {
164        if ( ! empty( $data['user']['current_user']['wpcom']['ID'] ) ) {
165            return $data;
166        }
167
168        $connected = ( new Connection_Manager() )->get_connected_user_data();
169        if ( empty( $connected['ID'] ) || empty( $connected['login'] ) ) {
170            return $data;
171        }
172
173        $data['user']['current_user']['wpcom'] = array_merge(
174            $data['user']['current_user']['wpcom'] ?? array(),
175            array(
176                'ID'    => $connected['ID'],
177                'login' => $connected['login'],
178            )
179        );
180
181        return $data;
182    }
183
184    /**
185     * Whether settings consolidation is on for the site, guarded against an older My Jetpack.
186     *
187     * @return bool
188     */
189    private static function is_consolidation_on() {
190        return class_exists( Initializer::class )
191            && method_exists( Initializer::class, 'is_settings_consolidation_on_for_site' )
192            && Initializer::is_settings_consolidation_on_for_site();
193    }
194
195    /**
196     * What the Settings tab needs from the server, built as the Settings app's Ads card builds it.
197     *
198     * @return array
199     */
200    private static function get_dashboard_data() {
201        $connection = new Connection_Manager();
202        $suffix     = ( new Status() )->get_site_suffix();
203        $blog_id    = Jetpack_Options::get_option( 'id' );
204        $site       = $blog_id ? (string) $blog_id : $suffix;
205
206        return array(
207            'hasWordAds'         => Current_Plan::supports( 'wordads' ),
208            'hasConnectedOwner'  => $connection->has_connected_owner(),
209            'upgradeUrl'         => self::get_upgrade_url( $site, $connection ),
210            'earningsUrl'        => Redirect::get_url( 'calypso-stats-ads-day', array( 'site' => $site ) ),
211            'isSubdirectorySite' => str_contains( $suffix, '::' ),
212            'moduleOverride'     => Jetpack_Modules_Overrides::instance()->get_module_override( 'wordads' ),
213            'tracks'             => self::can_use_analytics(),
214        );
215    }
216
217    /**
218     * The Ads upgrade URL, with the same arguments as the Settings app's `getUpgradeUrl()`.
219     *
220     * @param string             $site       Blog ID, or the site suffix without one.
221     * @param Connection_Manager $connection Connection manager.
222     * @return string
223     */
224    private static function get_upgrade_url( $site, $connection ) {
225        if ( ! class_exists( 'Jetpack_Redux_State_Helper' ) ) {
226            require_once JETPACK__PLUGIN_DIR . '_inc/lib/admin-pages/class-jetpack-redux-state-helper.php';
227        }
228
229        $query = $connection->is_user_connected() ? '' : 'unlinked=1&';
230
231        $purchase_token = Jetpack_Redux_State_Helper::get_purchase_token();
232        if ( $purchase_token ) {
233            $query .= 'purchasetoken=' . $purchase_token;
234        }
235
236        $partner = Partner::init();
237
238        return Redirect::get_url(
239            'jetpack-creator-cta',
240            array(
241                'site'         => $site,
242                'aff'          => $partner->get_partner_code( Partner::AFFILIATE_CODE ),
243                'u'            => (string) get_current_user_id(),
244                'subsidiaryId' => $partner->get_partner_code( Partner::SUBSIDIARY_CODE ),
245                'query'        => $query,
246                'calypso_env'  => ( new Host() )->get_calypso_env(),
247            )
248        );
249    }
250}
251
252Jetpack_Ads_Settings_Home::init();