PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.26
Advanced Ads – Ad Manager & AdSense v2.0.26
2.0.26 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 3 weeks ago groups 3 weeks ago metaboxes 3 weeks ago pages 3 weeks ago placements 3 weeks ago class-action-links.php 3 weeks ago class-addon-box.php 3 weeks ago class-addon-updater.php 3 weeks ago class-admin-menu.php 3 weeks ago class-admin-notices.php 1 year ago class-ajax.php 3 weeks ago class-app.php 1 month ago class-assets.php 3 weeks ago class-authors.php 3 weeks ago class-edd-updater.php 3 weeks ago class-license-admin-post.php 3 weeks ago class-list-filters.php 3 weeks ago class-marketing.php 3 weeks ago class-metabox-ad-settings.php 1 year ago class-metabox-ad.php 3 weeks ago class-misc.php 3 weeks ago class-page-quick-edit.php 1 month ago class-plugin-auto-update.php 1 month ago class-plugin-installer.php 3 weeks ago class-post-list.php 3 weeks ago class-post-types.php 3 weeks ago class-screen-options.php 3 weeks ago class-settings.php 3 weeks ago class-shortcode-creator.php 3 weeks ago class-system-info.php 1 year ago class-tinymce.php 2 years ago class-translation-promo.php 3 weeks ago class-upgrades.php 3 weeks ago class-version-control.php 3 weeks ago class-welcome.php 1 year ago class-wordpress-dashboard.php 1 year ago index.php 2 years ago
class-license-admin-post.php
247 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_Shop_Client;
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_Shop_Client::exchange(
57 [
58 'token' => $token,
59 'site' => License::get_site_hostname(),
60 ]
61 );
62 if ( is_wp_error( $rows ) ) {
63 $this->redirect_with_error( $this->map_error_code( $rows ) );
64 }
65 if ( empty( $rows ) ) {
66 $this->redirect_with_error( 'no_licenses' );
67 }
68
69 $activating_key = $this->resolve_checkout_activating_key( $rows, $license_id );
70
71 $saved = License::save_licenses(
72 $rows,
73 [
74 'activate_new' => '' !== $activating_key,
75 'activating_license_key' => $activating_key,
76 'preserve_legacy_map' => true,
77 ]
78 );
79
80 if ( is_wp_error( $saved ) ) {
81 $this->redirect_with_activation_error( $saved );
82 }
83
84 $args = [];
85 if ( $purchase_id > 0 ) {
86 $args['purchase_id'] = $purchase_id;
87 }
88 if ( in_array( $checkout_intent, [ 'buy', 'upgrade', 'renew' ], true ) ) {
89 $args['checkout_intent'] = $checkout_intent;
90 }
91 if ( $license_id > 0 ) {
92 $args['license_id'] = $license_id;
93 }
94
95 wp_safe_redirect( $this->license_admin_url( $args ) );
96 exit;
97 }
98
99 /**
100 * License key to activate after checkout when this site is not on the shop row yet.
101 *
102 * @param array<int, array<string, mixed>> $rows Exchange rows.
103 * @param int $license_id EDD SL license post ID from redirect.
104 * @return string License key or empty.
105 */
106 private function resolve_checkout_activating_key( array $rows, int $license_id ): string {
107 if ( $license_id < 1 ) {
108 return '';
109 }
110
111 $row = $this->resolve_checkout_row( $rows, $license_id );
112 if ( null === $row ) {
113 return '';
114 }
115
116 $key = (string) ( $row['licenseKey'] ?? '' );
117 if ( '' === $key || $this->is_site_active_on_row( $row ) ) {
118 return '';
119 }
120
121 return $key;
122 }
123
124 /**
125 * Pick license row for post-checkout activation.
126 *
127 * @param array<int, array<string, mixed>> $rows Exchange rows.
128 * @param int $license_id EDD SL license post ID.
129 * @return array<string, mixed>|null
130 */
131 private function resolve_checkout_row( array $rows, int $license_id ): ?array {
132 foreach ( $rows as $row ) {
133 if ( (int) ( $row['licenseId'] ?? 0 ) === $license_id ) {
134 return $row;
135 }
136 }
137
138 return $rows[0] ?? null;
139 }
140
141 /**
142 * Whether this site is already activated on the license row.
143 *
144 * @param array<string, mixed> $row License exchange row.
145 * @return bool
146 */
147 private function is_site_active_on_row( array $row ): bool {
148 $host = wp_parse_url( home_url(), PHP_URL_HOST );
149 $host = is_string( $host ) ? preg_replace( '/^www\./', '', strtolower( $host ) ) : '';
150 $sites = isset( $row['sitesActivated'] ) && is_array( $row['sitesActivated'] ) ? $row['sitesActivated'] : [];
151
152 foreach ( $sites as $site ) {
153 $domain = is_array( $site ) ? (string) ( $site['domain'] ?? '' ) : '';
154 $parsed = wp_parse_url( $domain, PHP_URL_HOST ) ?? $domain;
155 $parsed = preg_replace( '/^www\./', '', strtolower( (string) $parsed ) );
156 if ( $parsed === $host ) {
157 return true;
158 }
159 }
160
161 return false;
162 }
163
164 /**
165 * Map exchange WP_Error to redirect error code.
166 *
167 * @param WP_Error $error Exchange error.
168 * @return string
169 */
170 private function map_error_code( WP_Error $error ): string {
171 $error_code = $error->get_error_code();
172
173 if ( 'not_found' === $error_code ) {
174 return 'no_licenses';
175 }
176
177 if ( 'invalid_token' === $error_code ) {
178 return 'invalid_token';
179 }
180
181 $data = $error->get_error_data();
182 $status = is_array( $data ) ? (int) ( $data['status'] ?? 0 ) : 0;
183
184 if ( 403 === $status ) {
185 $message = strtolower( $error->get_error_message() );
186 if (
187 false !== strpos( $message, 'no license' )
188 || false !== strpos( $message, 'any licenses' )
189 ) {
190 return 'no_licenses';
191 }
192
193 return 'invalid_token';
194 }
195
196 return 'network';
197 }
198
199 /**
200 * Redirect to license screen with exchange error query arg.
201 *
202 * @param string $code Error code slug.
203 * @return void
204 */
205 private function redirect_with_error( string $code ): void {
206 wp_safe_redirect(
207 $this->license_admin_url( [ 'advads_exchange_error' => $code ] )
208 );
209 exit;
210 }
211
212 /**
213 * Redirect to license screen when shop activation failed during save.
214 *
215 * @param WP_Error $error Save or sync activation error.
216 * @return void
217 */
218 private function redirect_with_activation_error( WP_Error $error ): void {
219 $data = $error->get_error_data();
220 $status = is_array( $data ) ? (int) ( $data['status'] ?? 0 ) : 0;
221 $code = 'activate_failed';
222
223 if ( 0 === $status && in_array( $error->get_error_code(), [ 'http_request_failed' ], true ) ) {
224 $code = 'network';
225 }
226
227 $args = [ 'advads_activation_error' => $code ];
228 $message = sanitize_text_field( $error->get_error_message() );
229 if ( '' !== $message ) {
230 $args['advads_activation_message'] = substr( $message, 0, 200 );
231 }
232
233 wp_safe_redirect( $this->license_admin_url( $args ) );
234 exit;
235 }
236
237 /**
238 * License admin screen URL with optional query args.
239 *
240 * @param array<string, int|string> $query_args Query arguments.
241 * @return string
242 */
243 private function license_admin_url( array $query_args = [] ): string {
244 return License_Utils::admin_screen_url( $query_args );
245 }
246 }
247