PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.25
Advanced Ads – Ad Manager & AdSense v2.0.25
2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / includes / admin / class-license-admin-post.php
advanced-ads / includes / admin Last commit date
ads 1 week ago groups 1 week ago metaboxes 1 year ago pages 1 day ago placements 1 day ago class-action-links.php 1 week ago class-addon-box.php 1 day ago class-addon-updater.php 1 day ago class-admin-menu.php 1 day ago class-admin-notices.php 1 year ago class-ajax.php 1 day ago class-app.php 1 day ago class-assets.php 1 day ago class-authors.php 1 year ago class-edd-updater.php 1 day ago class-license-admin-post.php 1 day ago class-list-filters.php 1 week ago class-marketing.php 1 year ago class-metabox-ad-settings.php 1 year ago class-metabox-ad.php 1 year ago class-misc.php 1 week ago class-page-quick-edit.php 1 day ago class-plugin-auto-update.php 1 day ago class-plugin-installer.php 1 day ago class-post-list.php 1 year ago class-post-types.php 1 week ago class-screen-options.php 3 months ago class-settings.php 1 day ago class-shortcode-creator.php 1 year ago class-system-info.php 1 year ago class-tinymce.php 2 years ago class-translation-promo.php 1 year ago class-upgrades.php 1 year ago class-version-control.php 3 months ago class-welcome.php 1 year ago class-wordpress-dashboard.php 1 year ago index.php 2 years ago
class-license-admin-post.php
244 lines
1 <?php
2 /**
3 * Admin-post handler for shop token exchange.
4 *
5 * @package AdvancedAds
6 * @author Advanced Ads <info@wpadvancedads.com>
7 */
8
9 namespace AdvancedAds\Admin;
10
11 use AdvancedAds\Framework\Interfaces\Integration_Interface;
12 use AdvancedAds\Framework\Utilities\Params;
13 use AdvancedAds\License\License;
14 use AdvancedAds\License\License_Exchange;
15 use AdvancedAds\License\License_Utils;
16 use AdvancedAds\Utilities\Conditional;
17 use WP_Error;
18
19 defined( 'ABSPATH' ) || exit;
20
21 /**
22 * Exchanges one-time shop tokens server-side after connect or checkout.
23 */
24 class License_Admin_Post implements Integration_Interface {
25
26 public const ACTION = 'advanced-ads-license';
27
28 /**
29 * Register WordPress hooks.
30 *
31 * @return void
32 */
33 public function hooks(): void {
34 add_action( 'admin_post_' . self::ACTION, [ $this, 'handle' ] );
35 }
36
37 /**
38 * Exchange token, optionally activate on shop, save licenses, redirect.
39 *
40 * @return void
41 */
42 public function handle(): void {
43 if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
44 wp_die( esc_html__( 'Forbidden.', 'advanced-ads' ), '', [ 'response' => 403 ] );
45 }
46
47 $token = sanitize_text_field( (string) Params::request( 'token', '' ) );
48 $license_id = absint( Params::request( 'license_id', 0, FILTER_VALIDATE_INT ) );
49 $purchase_id = absint( Params::request( 'purchase_id', 0, FILTER_VALIDATE_INT ) );
50 $checkout_intent = sanitize_key( (string) Params::request( 'checkout_intent', '' ) );
51
52 if ( '' === $token ) {
53 $this->redirect_with_error( 'invalid_token' );
54 }
55
56 $rows = License_Exchange::request_by_token( $token );
57 if ( is_wp_error( $rows ) ) {
58 $this->redirect_with_error( $this->map_error_code( $rows ) );
59 }
60 if ( empty( $rows ) ) {
61 $this->redirect_with_error( 'no_licenses' );
62 }
63
64 $activating_key = $this->resolve_checkout_activating_key( $rows, $license_id );
65
66 $saved = License::save_licenses(
67 $rows,
68 '' !== $activating_key,
69 $activating_key,
70 '',
71 false,
72 '',
73 '',
74 true
75 );
76
77 if ( is_wp_error( $saved ) ) {
78 $this->redirect_with_activation_error( $saved );
79 }
80
81 $args = [];
82 if ( $purchase_id > 0 ) {
83 $args['purchase_id'] = $purchase_id;
84 }
85 if ( in_array( $checkout_intent, [ 'buy', 'upgrade', 'renew' ], true ) ) {
86 $args['checkout_intent'] = $checkout_intent;
87 }
88 if ( $license_id > 0 ) {
89 $args['license_id'] = $license_id;
90 }
91
92 wp_safe_redirect( $this->license_admin_url( $args ) );
93 exit;
94 }
95
96 /**
97 * License key to activate after checkout when this site is not on the shop row yet.
98 *
99 * @param array<int, array<string, mixed>> $rows Exchange rows.
100 * @param int $license_id EDD SL license post ID from redirect.
101 * @return string License key or empty.
102 */
103 private function resolve_checkout_activating_key( array $rows, int $license_id ): string {
104 if ( $license_id < 1 ) {
105 return '';
106 }
107
108 $row = $this->resolve_checkout_row( $rows, $license_id );
109 if ( null === $row ) {
110 return '';
111 }
112
113 $key = (string) ( $row['licenseKey'] ?? '' );
114 if ( '' === $key || $this->is_site_active_on_row( $row ) ) {
115 return '';
116 }
117
118 return $key;
119 }
120
121 /**
122 * Pick license row for post-checkout activation.
123 *
124 * @param array<int, array<string, mixed>> $rows Exchange rows.
125 * @param int $license_id EDD SL license post ID.
126 * @return array<string, mixed>|null
127 */
128 private function resolve_checkout_row( array $rows, int $license_id ): ?array {
129 foreach ( $rows as $row ) {
130 if ( (int) ( $row['licenseId'] ?? 0 ) === $license_id ) {
131 return $row;
132 }
133 }
134
135 return $rows[0] ?? null;
136 }
137
138 /**
139 * Whether this site is already activated on the license row.
140 *
141 * @param array<string, mixed> $row License exchange row.
142 * @return bool
143 */
144 private function is_site_active_on_row( array $row ): bool {
145 $host = wp_parse_url( home_url(), PHP_URL_HOST );
146 $host = is_string( $host ) ? preg_replace( '/^www\./', '', strtolower( $host ) ) : '';
147 $sites = isset( $row['sitesActivated'] ) && is_array( $row['sitesActivated'] ) ? $row['sitesActivated'] : [];
148
149 foreach ( $sites as $site ) {
150 $domain = is_array( $site ) ? (string) ( $site['domain'] ?? '' ) : '';
151 $parsed = wp_parse_url( $domain, PHP_URL_HOST ) ?: $domain;
152 $parsed = preg_replace( '/^www\./', '', strtolower( (string) $parsed ) );
153 if ( $parsed === $host ) {
154 return true;
155 }
156 }
157
158 return false;
159 }
160
161 /**
162 * Map exchange WP_Error to redirect error code.
163 *
164 * @param WP_Error $error Exchange error.
165 * @return string
166 */
167 private function map_error_code( WP_Error $error ): string {
168 $error_code = $error->get_error_code();
169
170 if ( 'not_found' === $error_code ) {
171 return 'no_licenses';
172 }
173
174 if ( 'invalid_token' === $error_code ) {
175 return 'invalid_token';
176 }
177
178 $data = $error->get_error_data();
179 $status = is_array( $data ) ? (int) ( $data['status'] ?? 0 ) : 0;
180
181 if ( 403 === $status ) {
182 $message = strtolower( $error->get_error_message() );
183 if (
184 false !== strpos( $message, 'no license' )
185 || false !== strpos( $message, 'any licenses' )
186 ) {
187 return 'no_licenses';
188 }
189
190 return 'invalid_token';
191 }
192
193 return 'network';
194 }
195
196 /**
197 * Redirect to license screen with exchange error query arg.
198 *
199 * @param string $code Error code slug.
200 * @return void
201 */
202 private function redirect_with_error( string $code ): void {
203 wp_safe_redirect(
204 $this->license_admin_url( [ 'advads_exchange_error' => $code ] )
205 );
206 exit;
207 }
208
209 /**
210 * Redirect to license screen when shop activation failed during save.
211 *
212 * @param WP_Error $error Save or sync activation error.
213 * @return void
214 */
215 private function redirect_with_activation_error( WP_Error $error ): void {
216 $data = $error->get_error_data();
217 $status = is_array( $data ) ? (int) ( $data['status'] ?? 0 ) : 0;
218 $code = 'activate_failed';
219
220 if ( 0 === $status && in_array( $error->get_error_code(), [ 'http_request_failed' ], true ) ) {
221 $code = 'network';
222 }
223
224 $args = [ 'advads_activation_error' => $code ];
225 $message = sanitize_text_field( $error->get_error_message() );
226 if ( '' !== $message ) {
227 $args['advads_activation_message'] = substr( $message, 0, 200 );
228 }
229
230 wp_safe_redirect( $this->license_admin_url( $args ) );
231 exit;
232 }
233
234 /**
235 * License admin screen URL with optional query args.
236 *
237 * @param array<string, int|string> $query_args Query arguments.
238 * @return string
239 */
240 private function license_admin_url( array $query_args = [] ): string {
241 return License_Utils::admin_screen_url( $query_args );
242 }
243 }
244