PluginProbe
Polylang / 3.4
Polylang v3.4
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.4, at include/license.php

354 lines 8.9 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|null
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 $this->auto_updater();
95
96 // Register settings
97 add_filter( 'pll_settings_licenses', array( $this, 'settings' ) );
98
99 // Weekly schedule
100 if ( ! wp_next_scheduled( 'polylang_check_licenses' ) ) {
101 wp_schedule_event( time(), 'weekly', 'polylang_check_licenses' );
102 }
103
104 add_action( 'polylang_check_licenses', array( $this, 'check_license' ) );
105 }
106
107 /**
108 * Auto updater
109 *
110 * @since 1.9
111 *
112 * @return void
113 */
114 public function auto_updater() {
115 $args = array(
116 'version' => $this->version,
117 'license' => $this->license_key,
118 'author' => $this->author,
119 'item_name' => $this->name,
120 );
121
122 // Setup the updater
123 new PLL_Plugin_Updater( $this->api_url, $this->file, $args );
124 }
125
126 /**
127 * Registers the licence in the Settings
128 *
129 * @since 1.9
130 *
131 * @param array $items
132 * @return array
133 */
134 public function settings( $items ) {
135 $items[ $this->id ] = $this;
136 return $items;
137 }
138
139 /**
140 * Activates the license key.
141 *
142 * @since 1.9
143 *
144 * @param string $license_key Activation key.
145 * @return PLL_License Updated PLL_License object.
146 */
147 public function activate_license( $license_key ) {
148 $this->license_key = $license_key;
149 $this->api_request( 'activate_license' );
150
151 // Tell WordPress to look for updates.
152 delete_site_transient( 'update_plugins' );
153 return $this;
154 }
155
156
157 /**
158 * Deactivates the license key.
159 *
160 * @since 1.9
161 *
162 * @return PLL_License Updated PLL_License object.
163 */
164 public function deactivate_license() {
165 $this->api_request( 'deactivate_license' );
166 return $this;
167 }
168
169 /**
170 * Checks if the license key is valid.
171 *
172 * @since 1.9
173 *
174 * @return void
175 */
176 public function check_license() {
177 $this->api_request( 'check_license' );
178 }
179
180 /**
181 * Sends an api request to check, activate or deactivate the license
182 * Updates the licenses option according to the status
183 *
184 * @since 1.9
185 *
186 * @param string $request check_license | activate_license | deactivate_license
187 * @return void
188 */
189 private function api_request( $request ) {
190 $licenses = get_option( 'polylang_licenses' );
191
192 if ( is_array( $licenses ) ) {
193 unset( $licenses[ $this->id ] );
194 } else {
195 $licenses = array();
196 }
197 unset( $this->license_data );
198
199 if ( ! empty( $this->license_key ) ) {
200 // Data to send in our API request
201 $api_params = array(
202 'edd_action' => $request,
203 'license' => $this->license_key,
204 'item_name' => urlencode( $this->name ),
205 'url' => home_url(),
206 );
207
208 // Call the API
209 $response = wp_remote_post(
210 $this->api_url,
211 array(
212 'timeout' => 3,
213 'sslverify' => false,
214 'body' => $api_params,
215 )
216 );
217
218 // Update the option only if we got a response
219 if ( is_wp_error( $response ) ) {
220 return;
221 }
222
223 // Save new license info
224 $licenses[ $this->id ] = array( 'key' => $this->license_key );
225 $data = json_decode( wp_remote_retrieve_body( $response ) );
226
227 if ( 'deactivated' !== $data->license ) {
228 $licenses[ $this->id ]['data'] = $this->license_data = $data;
229 }
230 }
231
232 update_option( 'polylang_licenses', $licenses ); // FIXME called multiple times when saving all licenses
233 }
234
235 /**
236 * Get the html form field in a table row (one per license key) for display
237 *
238 * @since 2.7
239 *
240 * @return string
241 */
242 public function get_form_field() {
243 if ( ! empty( $this->license_data ) ) {
244 $license = $this->license_data;
245 }
246
247 $class = 'license-null';
248 $message = '';
249
250 $out = sprintf(
251 '<td><label for="pll-licenses[%1$s]">%2$s</label></td>' .
252 '<td><input name="licenses[%1$s]" id="pll-licenses[%1$s]" type="password" value="%3$s" class="regular-text code" />',
253 esc_attr( $this->id ),
254 esc_attr( $this->name ),
255 esc_html( $this->license_key )
256 );
257
258 if ( ! empty( $license ) && is_object( $license ) ) {
259 $now = time();
260 $expiration = isset( $license->expires ) ? strtotime( $license->expires ) : false;
261
262 // Special case: the license expired after the last check
263 if ( $license->success && $expiration && $expiration < $now ) {
264 $license->success = false;
265 $license->error = 'expired';
266 }
267
268 if ( false === $license->success ) {
269 $class = 'notice-error notice-alt';
270
271 switch ( $license->error ) {
272 case 'expired':
273 $message = sprintf(
274 /* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
275 esc_html__( 'Your license key expired on %1$s. Please %2$srenew your license key%3$s.', 'polylang' ),
276 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) ),
277 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
278 '</a>'
279 );
280 break;
281
282 case 'disabled':
283 case 'revoked':
284 $message = esc_html__( 'Your license key has been disabled.', 'polylang' );
285 break;
286
287 case 'missing':
288 $message = sprintf(
289 /* translators: %1$s is link start tag, %2$s is link end tag. */
290 esc_html__( 'Invalid license. Please %1$svisit your account page%2$s and verify it.', 'polylang' ),
291 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
292 '</a>'
293 );
294 break;
295
296 case 'invalid':
297 case 'site_inactive':
298 $message = sprintf(
299 /* translators: %1$s is a product name, %2$s is link start tag, %3$s is link end tag. */
300 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' ),
301 esc_html( $this->name ),
302 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
303 '</a>'
304 );
305 break;
306
307 case 'item_name_mismatch':
308 /* translators: %s is a product name */
309 $message = sprintf( esc_html__( 'This is not a %s license key.', 'polylang' ), esc_html( $this->name ) );
310 break;
311
312 case 'no_activations_left':
313 $message = sprintf(
314 /* translators: %1$s is link start tag, %2$s is link end tag */
315 esc_html__( 'Your license key has reached its activation limit. %1$sView possible upgrades%2$s now.', 'polylang' ),
316 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
317 '</a>'
318 );
319 break;
320 }
321 } else {
322 $class = 'license-valid';
323
324 $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' ) );
325
326 if ( 'lifetime' === $license->expires ) {
327 $message = esc_html__( 'The license key never expires.', 'polylang' );
328 } elseif ( $expiration > $now && $expiration - $now < ( DAY_IN_SECONDS * 30 ) ) {
329 $class = 'notice-warning notice-alt';
330 $message = sprintf(
331 /* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
332 esc_html__( 'Your license key will expire soon! Precisely, it will expire on %1$s. %2$sRenew your license key today!%3$s', 'polylang' ),
333 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) ),
334 sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/account/' ),
335 '</a>'
336 );
337 } else {
338 $message = sprintf(
339 /* translators: %s is a date */
340 esc_html__( 'Your license key expires on %s.', 'polylang' ),
341 esc_html( date_i18n( get_option( 'date_format' ), $expiration ) )
342 );
343 }
344 }
345 }
346
347 if ( ! empty( $message ) ) {
348 $out .= '<p>' . $message . '</p>';
349 }
350
351 return sprintf( '<tr id="pll-license-%s" class="%s">%s</tr>', esc_attr( $this->id ), $class, $out );
352 }
353 }
354