PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.3
Presto Player v4.3.3
4.3.3 4.3.2 4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Services / Player.php
presto-player / inc / Services Last commit date
API 2 months ago Blocks 5 days ago License 2 weeks ago AdminNotice.php 1 month ago AdminNotices.php 1 month ago AjaxActions.php 1 month ago Blocks.php 2 years ago Compatibility.php 10 months ago Learn.php 2 months ago Menu.php 5 days ago Migrations.php 2 years ago NpsSurvey.php 6 months ago Onboarding.php 1 month ago Player.php 5 days ago PluginInstaller.php 2 months ago PreloadService.php 1 year ago ProCompatibility.php 5 days ago ReusableVideos.php 1 month ago RewriteRulesManager.php 2 years ago Scripts.php 1 month ago Settings.php 2 months ago Shortcodes.php 2 months ago Streamer.php 1 month ago Translation.php 5 days ago Usage.php 1 month ago VideoPostType.php 5 days ago
Player.php
154 lines
1 <?php
2 /**
3 * Player progress AJAX service.
4 *
5 * @package PrestoPlayer
6 */
7
8 namespace PrestoPlayer\Services;
9
10 use PrestoPlayer\Contracts\Service;
11
12 /**
13 * Registers the AJAX endpoints used to track player progress.
14 */
15 class Player implements Service {
16
17 /**
18 * Nonce action the refresh endpoint issues for player tracking.
19 *
20 * Pro verifies this exact action in its analytics and email-capture AJAX
21 * handlers, so renaming it here breaks Pro. Keep both sides in sync.
22 *
23 * @var string
24 */
25 const PROGRESS_NONCE_ACTION = 'presto_player_progress';
26
27 /**
28 * Nonce action issued before the scoped one. Still handed out whenever an
29 * older Pro is active (its handlers verify wp_rest only), still carried by
30 * pages cached back then, and since 4.3.2 the email overlay sends the
31 * page's localized wp_rest nonce (Scripts.php) on every submit — so this
32 * can't be retired until that overlay moves off it.
33 *
34 * @var string
35 */
36 const LEGACY_NONCE_ACTION = 'wp_rest';
37
38 /**
39 * Register the AJAX hooks for this service.
40 *
41 * @return void
42 */
43 public function register() {
44 // Ajax percentage actions.
45 add_action( 'wp_ajax_presto_player_progress_percent', array( $this, 'progressAjaxPercent' ) );
46 add_action( 'wp_ajax_nopriv_presto_player_progress_percent', array( $this, 'progressAjaxPercent' ) );
47
48 add_action( 'wp_ajax_nopriv_presto_refresh_progress_nonce', array( $this, 'generateNonce' ) );
49 add_action( 'wp_ajax_presto_refresh_progress_nonce', array( $this, 'generateNonce' ) );
50 }
51
52 /**
53 * Send a freshly generated progress nonce as a JSON response.
54 *
55 * Prefers the progress-scoped action, because this endpoint is open to
56 * logged-out users and a general-purpose wp_rest nonce is a wider grant
57 * than progress tracking needs.
58 *
59 * It still falls back to wp_rest when Pro is active but predates 3.2.3,
60 * since those builds verify wp_rest only — scoping unconditionally is what
61 * took Pro analytics and email capture down in 4.3.1. Don't "tidy" this
62 * into an unconditional scoped nonce without dropping support for Pro
63 * older than 3.2.3.
64 *
65 * @return void
66 */
67 public function generateNonce() {
68 $pro_active = class_exists( '\PrestoPlayer\Pro\Plugin' );
69
70 /**
71 * Whether the active Pro version verifies the scoped progress nonce.
72 *
73 * Pro returns true from the version that accepts
74 * self::PROGRESS_NONCE_ACTION. Older builds check wp_rest only and
75 * never register this filter, which is how we detect them.
76 *
77 * @param bool $verifies Whether Pro verifies the scoped nonce.
78 */
79 $pro_verifies_scoped = (bool) apply_filters( 'presto_player_pro_verifies_scoped_nonce', false );
80
81 wp_send_json_success( wp_create_nonce( self::refreshNonceAction( $pro_active, $pro_verifies_scoped ) ) );
82 }
83
84 /**
85 * Decide which nonce action the refresh endpoint should issue.
86 *
87 * The player sends this one nonce to both the free progress handler and
88 * Pro's analytics/email-capture handlers. Pro versions before the scoped
89 * nonce landed verify wp_rest only, so they get the legacy nonce — without
90 * it their analytics and email capture reject every request with a 403.
91 *
92 * @param bool $pro_active Whether the Pro plugin is active.
93 * @param bool $pro_verifies_scoped Whether that Pro version verifies the scoped nonce.
94 * @return string Nonce action.
95 */
96 public static function refreshNonceAction( $pro_active, $pro_verifies_scoped ) {
97 if ( $pro_active && ! $pro_verifies_scoped ) {
98 return self::LEGACY_NONCE_ACTION;
99 }
100
101 return self::PROGRESS_NONCE_ACTION;
102 }
103
104 /**
105 * Run ajax percent action.
106 *
107 * @return void
108 */
109 public function progressAjaxPercent() {
110 $response = $this->progressAction();
111 if ( is_wp_error( $response ) ) {
112 wp_send_json_error( $response->get_error_message(), $response->get_all_error_data( 'status' ) );
113 }
114
115 wp_send_json_success();
116 }
117
118 /**
119 * Run the progress action.
120 *
121 * @return bool|\WP_Error True on success, or a WP_Error describing the failure.
122 */
123 public function progressAction() {
124 // Verify nonce. wp_rest still arrives from old cached pages and whenever
125 // the refresh endpoint falls back for an older Pro.
126 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
127 if ( ! wp_verify_nonce( $nonce, self::PROGRESS_NONCE_ACTION ) && ! wp_verify_nonce( $nonce, self::LEGACY_NONCE_ACTION ) ) {
128 return new \WP_Error( 'invalid', 'Nonce invalid', array( 'status' => 403 ) );
129 }
130
131 // Video id is required.
132 if ( empty( $_POST['id'] ) ) {
133 return new \WP_Error( 'invalid', 'You must provide a valid video id', array( 'status' => 400 ) );
134 }
135
136 // Must have a valid percentage.
137 if ( ! isset( $_POST['percent'] ) ) {
138 return new \WP_Error( 'invalid', 'You must provide a valid percentage', array( 'status' => 400 ) );
139 }
140
141 $id = (int) $_POST['id'];
142 $percent = (int) $_POST['percent'];
143 $visit_time = isset( $_POST['visit_time'] ) ? (int) $_POST['visit_time'] : false;
144
145 /**
146 * Progress event, sends video id and percent progress.
147 */
148 do_action( 'presto_player_progress', $id, $percent, $visit_time );
149
150 // Success.
151 return true;
152 }
153 }
154