PluginProbe
Polylang / 3.2.2
Polylang v3.2.2
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / include / license.php

license.php in Polylang 3.2.2, at include/license.php

356 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * A class to easily manage licenses for Polylang Pro and addons
8 *
9 * @since 1.9
10 */
11 class PLL_License {
12 /**
13 * Sanitized plugin name.
14 *
15 * @var string
16 */
17 public $id;
18
19 /**
20 * Plugin name.
21 *
22 * @var string
23 */
24 public $name;
25
26 /**
27 * License key.
28 *
29 * @var string
30 */
31 public $license_key;
32
33 /**
34 * License data, obtained from the API request.
35 *
36 * @var stdClass
37 */
38 public $license_data;
39
40 /**
41 * Main plugin file.
42 *
43 * @var string
44 */
45 private $file;
46
47 /**
48 * Current plugin version.
49 *
50 * @var string
51 */
52 private $version;
53
54 /**
55 * Plugin author.
56 *
57 * @var string
58 */
59 private $author;
60
61 /**
62 * API url.
63 *
64 * @var string.
65 */
66 private $api_url = 'https://polylang.pro';
67
68 /**
69 * Constructor
70 *
71 * @since 1.9
72 *
73 * @param string $file
74 * @param string $item_name
75 * @param string $version
76 * @param string $author
77 * @param string $api_url optional
78 */
79 public function __construct( $file, $item_name, $version, $author, $api_url = null ) {
80 $this->id = sanitize_title( $item_name );
81 $this->file = $file;
82 $this->name = $item_name;
83 $this->version = $version;
84 $this->author = $author;
85 $this->api_url = empty( $api_url ) ? $this->api_url : $api_url;
86
87 $licenses = get_option( 'polylang_licenses' );
88 $this->license_key = empty( $licenses[ $this->id ]['key'] ) ? '' : $licenses[ $this->id ]['key'];
89 if ( ! empty( $licenses[ $this->id ]['data'] ) ) {
90 $this->license_data = $licenses[ $this->id ]['data'];
91 }
92
93 // Updater
94 add_action( 'admin_init', array( $this, 'auto_updater' ), 0 );
95 add_action( 'cli_init', array( $this, 'auto_updater' ), 0 ); // For WP CLI.
96
97 // Register settings
98 add_filter( 'pll_settings_licenses', array( $this, 'settings' ) );
99
100 // Weekly schedule
101 if ( ! wp_next_scheduled( 'polylang_check_licenses' ) ) {
102 wp_schedule_event( time(), 'weekly', 'polylang_check_licenses' );
103 }
104
105 add_action( 'polylang_check_licenses', array( $this, 'check_license' ) );
106 }
107
108 /**
109 * Auto updater
110 *
111 * @since 1.9
112 *
113 * @return void
114 */
115 public function auto_updater() {
116 $args = array(
117 'version' => $this->version,
118 'license' => $this->license_key,
119 'author' => $this->author,
120 'item_name' => $this->name,
121 );
122
123 // Setup the updater
124 new PLL_Plugin_Updater( $this->api_url, $this->file, $args );
125 }
126
127 /**
128 * Registers the licence in the Settings
129 *
130 * @since 1.9
131 *
132 * @param array $items
133 * @return array
134 */
135 public function settings( $items ) {
136 $items[ $this->id ] = $this;
137 return $items;
138 }
139
140 /**
141 * Activates the license key.
142 *
143 * @since 1.9
144 *
145 * @param string $license_key Activation key.
146 * @return PLL_License Updated PLL_License object.
147 */
148 public function activate_license( $license_key ) {
149 $this->license_key = $license_key;
150 $this->api_request( 'activate_license' );
151
152 // Tell WordPress to look for updates
153 set_site_transient( 'update_plugins', null );
154 return $this;
155 }
156
157
158 /**
159 * Deactivates the license key.
160 *
161 * @since 1.9
162 *
163 * @return PLL_License Updated PLL_License object.
164 */
165 public function deactivate_license() {
166 $this->api_request( 'deactivate_license' );
167 return $this;
168 }
169
170 /**
171 * Checks if the license key is valid.
172 *
173 * @since 1.9
174 *
175 * @return PLL_License Updated PLL_License object.
176 */
177 public function check_license() {
178 $this->api_request( 'check_license' );
179 return $this;
180 }
181
182 /**
183 * Sends an api request to check, activate or deactivate the license
184 * Updates the licenses option according to the status
185 *
186 * @since 1.9
187 *
188 * @param string $request check_license | activate_license | deactivate_license
189 * @return void
190 */
191 private function api_request( $request ) {
192 $licenses = get_option( 'polylang_licenses' );
193
194 if ( is_array( $licenses ) ) {
195 unset( $licenses[ $this->id ] );
196 } else {
197 $licenses = array();
198 }
199 unset( $this->license_data );
200
201 if ( ! empty( $this->license_key ) ) {
202 // Data to send in our API request
203 $api_params = array(
204 'edd_action' => $request,
205 'license' => $this->license_key,
206 'item_name' => urlencode( $this->name ),
207 'url' => home_url(),
208 );
209
210 // Call the API
211 $response = wp_remote_post(
212 $this->api_url,
213 array(
214 'timeout' => 3,
215 'sslverify' => false,
216 'body' => $api_params,
217 )
218 );
219
220 // Update the option only if we got a response
221 if ( is_wp_error( $response ) ) {
222 return;
223 }
224
225 // Save new license info
226 $licenses[ $this->id ] = array( 'key' => $this->license_key );
227 $data = json_decode( wp_remote_retrieve_body( $response ) );
228
229 if ( 'deactivated' !== $data->license ) {
230 $licenses[ $this->id ]['data'] = $this->license_data = $data;
231 }
232 }
233
234 update_option( 'polylang_licenses', $licenses ); // FIXME called multiple times when saving all licenses
235 }
236
237 /**
238 * Get the html form field in a table row (one per license key) for display
239 *
240 * @since 2.7
241 *
242 * @return string
243 */
244 public function get_form_field() {
245 if ( ! empty( $this->license_data ) ) {
246 $license = $this->license_data;
247 }
248
249 $class = 'license-null';
250 $message = '';
251
252 $out = sprintf(
253 '<td><label for="pll-licenses[%1$s]">%2$s</label></td>' .
254 '<td><input name="licenses[%1$s]" id="pll-licenses[%1$s]" type="password" value="%3$s" class="regular-text code" />',
255 esc_attr( $this->id ),
256 esc_attr( $this->name ),
257 esc_html( $this->license_key )
258 );
259
260 if ( ! empty( $license ) && is_object( $license ) ) {
261 $now = time();
262 $expiration = isset( $license->expires ) ? strtotime( $license->expires ) : false;
263
264 // Special case: the license expired after the last check
265 if ( $license->success && $expiration && $expiration < $now ) {
266 $license->success = false;
267 $license->error = 'expired';
268 }
269
270 if ( false === $license->success ) {
271 $class = 'notice-error notice-alt';
272
273 switch ( $license->error ) {
274 case 'expired':
275 $message = sprintf(
276 /* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
277 esc_html__( 'Your license key expired on %1$s. Please %2$srenew your license key%3$s.', 'polylang' ),
278 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) ),
279 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
280 '</a>'
281 );
282 break;
283
284 case 'disabled':
285 case 'revoked':
286 $message = esc_html__( 'Your license key has been disabled.', 'polylang' );
287 break;
288
289 case 'missing':
290 $message = sprintf(
291 /* translators: %1$s is link start tag, %2$s is link end tag. */
292 esc_html__( 'Invalid license. Please %1$svisit your account page%2$s and verify it.', 'polylang' ),
293 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
294 '</a>'
295 );
296 break;
297
298 case 'invalid':
299 case 'site_inactive':
300 $message = sprintf(
301 /* translators: %1$s is a product name, %2$s is link start tag, %3$s is link end tag. */
302 esc_html__( 'Your %1$s license key is not active for this URL. Please %2$svisit your account page%3$s to manage your license key URLs.', 'polylang' ),
303 esc_html( $this->name ),
304 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
305 '</a>'
306 );
307 break;
308
309 case 'item_name_mismatch':
310 /* translators: %s is a product name */
311 $message = sprintf( esc_html__( 'This is not a %s license key.', 'polylang' ), esc_html( $this->name ) );
312 break;
313
314 case 'no_activations_left':
315 $message = sprintf(
316 /* translators: %1$s is link start tag, %2$s is link end tag */
317 esc_html__( 'Your license key has reached its activation limit. %1$sView possible upgrades%2$s now.', 'polylang' ),
318 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
319 '</a>'
320 );
321 break;
322 }
323 } else {
324 $class = 'license-valid';
325
326 $out .= sprintf( '<button id="deactivate_%s" type="button" class="button button-secondary pll-deactivate-license">%s</button>', esc_attr( $this->id ), esc_html__( 'Deactivate', 'polylang' ) );
327
328 if ( 'lifetime' === $license->expires ) {
329 $message = esc_html__( 'The license key never expires.', 'polylang' );
330 } elseif ( $expiration > $now && $expiration - $now < ( DAY_IN_SECONDS * 30 ) ) {
331 $class = 'notice-warning notice-alt';
332 $message = sprintf(
333 /* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
334 esc_html__( 'Your license key will expire soon! Precisely, it will expire on %1$s. %2$sRenew your license key today!%3$s', 'polylang' ),
335 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) ),
336 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
337 '</a>'
338 );
339 } else {
340 $message = sprintf(
341 /* translators: %s is a date */
342 esc_html__( 'Your license key expires on %s.', 'polylang' ),
343 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) )
344 );
345 }
346 }
347 }
348
349 if ( ! empty( $message ) ) {
350 $out .= '<p>' . $message . '</p>';
351 }
352
353 return sprintf( '<tr id="pll-license-%s" class="%s">%s</tr>', esc_attr( $this->id ), $class, $out );
354 }
355 }
356