Google Analytics for WordPress by MonsterInsights - Version 5.5.2

Version Description

Release Date: July 7th, 2016

  • Bugfixes:

    • Fixes compatibiltiy with upcoming Shiny Updates v2 in WP core
  • Enhancements:

    • Updates license manager to have more reliable update information including better compatibility with Yoast SEO products.
Download this release

Release Info

Developer chriscct7
Plugin Icon 128x128 Google Analytics for WordPress by MonsterInsights
Version 5.5.2
Comparing to
See all releases

Code changes from version 5.5 to 5.5.2

Files changed (26) hide show
  1. admin/class-admin.php +620 -620
  2. googleanalytics.php +2 -2
  3. includes/ecommerce-addon-license-fix.php +6 -2
  4. readme.txt +12 -2
  5. vendor/yoast/license-manager-2/.gitigore +2 -2
  6. vendor/yoast/license-manager-2/class-api-request.php +138 -140
  7. vendor/yoast/license-manager-2/class-license-manager.php +613 -619
  8. vendor/yoast/license-manager-2/class-plugin-license-manager.php +90 -90
  9. vendor/yoast/license-manager-2/class-plugin-update-manager.php +93 -102
  10. vendor/yoast/license-manager-2/class-product.php +292 -228
  11. vendor/yoast/license-manager-2/class-theme-license-manager.php +51 -53
  12. vendor/yoast/license-manager-2/class-theme-update-manager.php +141 -149
  13. vendor/yoast/license-manager-2/class-update-manager.php +216 -211
  14. vendor/yoast/license-manager/.gitigore +2 -2
  15. vendor/yoast/license-manager/README.md +21 -21
  16. vendor/yoast/license-manager/class-api-request.php +140 -140
  17. vendor/yoast/license-manager/class-license-manager.php +613 -619
  18. vendor/yoast/license-manager/class-plugin-license-manager.php +90 -90
  19. vendor/yoast/license-manager/class-plugin-update-manager.php +93 -102
  20. vendor/yoast/license-manager/class-product.php +292 -228
  21. vendor/yoast/license-manager/class-theme-license-manager.php +51 -53
  22. vendor/yoast/license-manager/class-theme-update-manager.php +141 -149
  23. vendor/yoast/license-manager/class-update-manager.php +216 -211
  24. vendor/yoast/license-manager/composer.json +28 -28
  25. vendor/yoast/license-manager/samples/sample-plugin.php +74 -74
  26. vendor/yoast/license-manager/samples/sample-product.php +22 -22
admin/class-admin.php CHANGED
@@ -1,620 +1,620 @@
1
- <?php
2
- /**
3
- * @package GoogleAnalytics\Admin
4
- */
5
-
6
- /**
7
- * This class is for the backend, extendable for all child classes
8
- */
9
- class Yoast_GA_Admin extends Yoast_GA_Options {
10
-
11
- /**
12
- * Constructor
13
- */
14
- public function __construct() {
15
- parent::__construct();
16
-
17
- add_action( 'plugins_loaded', array( $this, 'init_ga' ) );
18
-
19
- // Only run admin_init when there is a cron jon executed.
20
- $current_page = filter_input( INPUT_GET, 'page' );
21
-
22
- // Only when current page is not 'wpseo'.
23
- if ( strpos( $current_page, 'wpseo' ) !== 0 ) {
24
- if ( ( $this->is_running_cron() || $this->is_running_ajax() ) || strpos( $current_page, 'yst_ga' ) === 0 ) {
25
- add_action( 'admin_init', array( $this, 'init_settings' ) );
26
- }
27
- }
28
-
29
- add_action( 'admin_init', array( $this, 'system_info' ) );
30
-
31
- }
32
-
33
- /**
34
- * Init function when the plugin is loaded
35
- */
36
- public function init_ga() {
37
-
38
- new Yoast_GA_Admin_Menu( $this );
39
-
40
- add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ) );
41
-
42
- }
43
-
44
- /**
45
- * Init function for the settings of GA
46
- */
47
- public function init_settings() {
48
- $this->options = $this->get_options();
49
-
50
- try {
51
- // Loading Google Api Libs with minimal version 2.0.
52
- new MI_Api_Libs( '2.0' );
53
- }
54
- catch( Exception $exception ) {
55
- if ( $exception->getMessage() === 'required_version' ) {
56
- add_action( 'admin_notices', array( $this, 'set_api_libs_error' ) );
57
- }
58
- }
59
-
60
- $dashboards = Yoast_GA_Dashboards::get_instance();
61
-
62
- // Listener for reconnecting with google analytics
63
- $this->google_analytics_listener();
64
-
65
- if ( is_null( $this->get_tracking_code() ) && $this->show_admin_warning() ) {
66
- add_action( 'admin_notices', array( 'Yoast_Google_Analytics_Notice', 'config_warning' ) );
67
- }
68
-
69
- // Check if something has went wrong with GA-api calls
70
- $has_tracking_code = ( ! is_null( $this->get_tracking_code() ) && empty( $this->options['manual_ua_code_field'] ) );
71
- if ( $has_tracking_code && $this->show_admin_dashboard_warning() ) {
72
- Yoast_Google_Analytics::get_instance()->check_for_ga_issues();
73
- }
74
-
75
-
76
- if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
77
- $this->handle_ga_post_request( $dashboards );
78
- }
79
-
80
- /**
81
- * Show the notifications if we have one
82
- */
83
- $this->show_notification( 'ga_notifications' );
84
-
85
- // Load the Google Analytics Dashboards functionality
86
- $dashboards->init_dashboards( $this->get_current_profile() );
87
- }
88
-
89
- /**
90
- * There is an error with the API libs. So show a notice.
91
- */
92
- public function set_api_libs_error() {
93
- echo '<div class="error notice"><p>' . __( 'MonsterInsights plugins share some code between them to make your site faster. As a result of that, we need all MonsterInsights plugins to be up to date. We\'ve detected this isn\'t the case, so please update the MonsterInsights plugins that aren\'t up to date yet.', 'google-analytics-for-wordpress' ) . '</p></div>';
94
- }
95
-
96
- /**
97
- * This function saves the settings in the option field and returns a wp success message on success
98
- *
99
- * @param array $data
100
- */
101
- public function save_settings( $data ) {
102
-
103
- unset( $data['google_auth_code'] );
104
-
105
- foreach ( $data as $key => $value ) {
106
- if ( $key != 'return_tab' ) {
107
- if ( is_string( $value ) ) {
108
- if ( $key === 'custom_code' && ! current_user_can( 'unfiltered_html' ) ) {
109
- continue;
110
- }
111
- else {
112
- $value = strip_tags( $value );
113
- }
114
- }
115
-
116
- $this->options[ $key ] = $value;
117
- }
118
- }
119
-
120
- // Check checkboxes, on a uncheck they won't be posted to this function
121
- $defaults = $this->default_ga_values();
122
- foreach ( $defaults[ $this->option_prefix ] as $option_name => $value ) {
123
- $this->handle_default_setting( $data, $option_name, $value );
124
- }
125
-
126
- if ( ! empty( $this->options['analytics_profile'] ) ) {
127
- $this->options['analytics_profile_code'] = $this->get_ua_code_from_profile( $this->options['analytics_profile'] );
128
- }
129
-
130
- $this->do_validation( $data['return_tab'] );
131
-
132
- if ( $this->update_option( $this->options ) ) {
133
- // Success, add a new notification
134
- $this->add_notification( 'ga_notifications', array(
135
- 'type' => 'success',
136
- 'description' => __( 'Settings saved.', 'google-analytics-for-wordpress' ),
137
- ) );
138
- }
139
- else {
140
- // Fail, add a new notification
141
- $this->add_notification( 'ga_notifications', array(
142
- 'type' => 'error',
143
- 'description' => __( 'There were no changes to save, please try again.', 'google-analytics-for-wordpress' ),
144
- ) );
145
- }
146
-
147
- // redirect
148
- wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $data['return_tab'], 301 );
149
- exit;
150
- }
151
-
152
- /**
153
- * Redirect to settings with a validation error if there are validation errors
154
- *
155
- * @param string $return_tab The tab to return to when there is a validation error.
156
- */
157
- protected function do_validation( $return_tab ) {
158
- $validation = $this->validate_settings();
159
- if ( is_wp_error( $validation ) ) {
160
- $this->add_notification( 'ga_notifications', array(
161
- 'type' => 'error',
162
- 'description' => $validation->get_error_message(),
163
- ) );
164
-
165
- wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $return_tab, 301 );
166
- exit;
167
- }
168
- }
169
-
170
- /**
171
- * Validates the settings in the `options` attribute, returns an WP_Error object on error
172
- *
173
- * @return true|WP_Error true or an error object.
174
- */
175
- protected function validate_settings() {
176
-
177
- if ( ! empty( $this->options['manual_ua_code_field'] ) ) {
178
- $this->options['manual_ua_code_field'] = trim( $this->options['manual_ua_code_field'] );
179
- // en dash to minus, prevents issue with code copied from web with "fancy" dash
180
- $this->options['manual_ua_code_field'] = str_replace( '–', '-', $this->options['manual_ua_code_field'] );
181
-
182
- // Regex to tests if a valid UA code has been set. Valid codes follow: "UA-[4 digits]-[at least 1 digit]".
183
- if ( ! preg_match( '|^UA-\d{4,}-\d+$|', $this->options['manual_ua_code_field'] ) ) {
184
-
185
- return new WP_Error(
186
- 'ua-code-format',
187
- __( 'The UA code needs to follow UA-XXXXXXXX-X format.', 'google-analytics-for-wordpress' )
188
- );
189
- }
190
- }
191
-
192
- /**
193
- * Filters the validation for the admin options
194
- *
195
- * @param true|WP_Error true if the validation is successful, WP_Error on error.
196
- * @param array $this->options The options that are being saved.
197
- */
198
- return apply_filters( 'yst_ga_admin_validate_settings', true, $this->options );
199
- }
200
-
201
- /**
202
- * Run a this deactivation hook on deactivation of GA. When this happens we'll
203
- * remove the options for the profiles and the refresh token.
204
- */
205
- public static function ga_deactivation_hook() {
206
- // Remove the refresh token and other API settings
207
- self::analytics_api_clean_up();
208
- }
209
-
210
- /**
211
- * Handle a default setting in GA
212
- *
213
- * @param array $data
214
- * @param string $option_name
215
- * @param mixed $value
216
- */
217
- private function handle_default_setting( $data, $option_name, $value ) {
218
- if ( ! isset( $data[ $option_name ] ) ) {
219
- // If no data was passed in, set it to the default.
220
- if ( $value === 1 ) {
221
- // Disable the checkbox for now, use value 0
222
- $this->options[ $option_name ] = 0;
223
- }
224
- else {
225
- $this->options[ $option_name ] = $value;
226
- }
227
- }
228
- }
229
-
230
- /**
231
- * Handle the post requests in the admin form of the GA plugin
232
- *
233
- * @param Yoast_GA_Dashboards $dashboards
234
- */
235
- private function handle_ga_post_request( $dashboards ) {
236
- if ( ! function_exists( 'wp_verify_nonce' ) ) {
237
- require_once( ABSPATH . 'wp-includes/pluggable.php' );
238
- }
239
-
240
- if ( isset( $_POST['ga-form-settings'] ) && wp_verify_nonce( $_POST['yoast_ga_nonce'], 'save_settings' ) ) {
241
- if ( ! isset ( $_POST['ignore_users'] ) ) {
242
- $_POST['ignore_users'] = array();
243
- }
244
-
245
- $dashboards_disabled = Yoast_GA_Settings::get_instance()->dashboards_disabled();
246
-
247
- if ( ( $dashboards_disabled == false && isset( $_POST['dashboards_disabled'] ) ) || $this->ga_profile_changed( $_POST ) ) {
248
- $dashboards->reset_dashboards_data();
249
- }
250
-
251
- // Post submitted and verified with our nonce
252
- $this->save_settings( $_POST );
253
- }
254
- }
255
-
256
- /**
257
- * Is there selected an other property in the settings post? Returns true or false.
258
- *
259
- * @param array $post
260
- *
261
- * @return bool
262
- */
263
- private function ga_profile_changed( $post ) {
264
- if ( isset( $post['analytics_profile'] ) && isset( $this->options['analytics_profile'] ) ) {
265
- if ( $post['analytics_profile'] != $this->options['analytics_profile'] ) {
266
- return true;
267
- }
268
- }
269
-
270
- return false;
271
- }
272
-
273
- /**
274
- * Are we allowed to show a warning message? returns true if it's allowed
275
- *
276
- * @return bool
277
- */
278
- private function show_admin_warning() {
279
- return ( current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || ( isset( $_GET['page'] ) && $_GET['page'] !== 'yst_ga_settings' ) ) );
280
- }
281
-
282
- /**
283
- * Are we allowed to show a warning message? returns true if it's allowed ( this is meant to be only for dashboard )
284
- *
285
- * @return bool
286
- */
287
- private function show_admin_dashboard_warning() {
288
- return ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && $_GET['page'] === 'yst_ga_dashboard' );
289
- }
290
-
291
- /**
292
- * Transform the Profile ID into an helpful UA code
293
- *
294
- * @param integer $profile_id
295
- *
296
- * @return null
297
- */
298
- private function get_ua_code_from_profile( $profile_id ) {
299
- $profiles = $this->get_profiles();
300
- $ua_code = null;
301
-
302
- foreach ( $profiles as $account ) {
303
- foreach ( $account['items'] as $profile ) {
304
- foreach ( $profile['items'] as $subprofile ) {
305
- if ( isset( $subprofile['id'] ) && $subprofile['id'] === $profile_id ) {
306
- return $subprofile['ua_code'];
307
- }
308
- }
309
- }
310
- }
311
-
312
- return $ua_code;
313
- }
314
-
315
- /**
316
- * Add a link to the settings page to the plugins list
317
- *
318
- * @param array $links array of links for the plugins, adapted when the current plugin is found.
319
- *
320
- * @return array $links
321
- */
322
- public function add_action_links( $links ) {
323
- // add link to knowledgebase
324
- // @todo UTM link fix
325
- $faq_link = '<a title="MonsterInsights Knowledge Base" href="http://www.monsterinsights.com/docs/">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>';
326
- array_unshift( $links, $faq_link );
327
-
328
- $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=yst_ga_settings' ) ) . '">' . __( 'Settings', 'google-analytics-for-wordpress' ) . '</a>';
329
- array_unshift( $links, $settings_link );
330
-
331
- return $links;
332
- }
333
-
334
- /**
335
- * Adds some promo text for the premium plugin on the custom dimensions tab.
336
- */
337
- public function premium_promo() {
338
- echo '<div class="ga-promote">';
339
- echo '<p>';
340
- printf( __( 'If you want to track custom dimensions like page views per author or post type, you should upgrade to the %1$spremium version of Google Analytics by MonsterInsights%2$s.', 'google-analytics-for-wordpress' ), '<a href="https://www.monsterinsights.com/pricing/#utm_medium=text-link&utm_source=gawp-config&utm_campaign=wpgaplugin&utm_content=custom_dimensions_tab">', '</a>' );
341
- echo ' ';
342
- _e( 'This will also give you access to the support team at MonsterInsights, who will provide support on the plugin 24/7.', 'google-analytics-for-wordpress' );
343
- echo '</p>';
344
- echo '</div>';
345
- }
346
-
347
- /**
348
- * Load the page of a menu item in the GA plugin
349
- */
350
- public function load_page() {
351
-
352
- if ( ! has_action( 'yst_ga_custom_dimensions_tab-content' ) ) {
353
- add_action( 'yst_ga_custom_dimensions_tab-content', array( $this, 'premium_promo' ) );
354
- }
355
-
356
- if ( ! has_action( 'yst_ga_custom_dimension_add-dashboards-tab' ) ) {
357
- add_action( 'yst_ga_custom_dimension_add-dashboards-tab', array( $this, 'premium_promo' ) );
358
- }
359
-
360
- switch ( filter_input( INPUT_GET, 'page' ) ) {
361
- case 'yst_ga_settings':
362
- require_once( $this->plugin_path . 'admin/pages/settings.php' );
363
- break;
364
- case 'yst_ga_extensions':
365
- require_once( $this->plugin_path . 'admin/pages/extensions.php' );
366
- break;
367
- case 'yst_ga_dashboard':
368
- default:
369
- require_once( $this->plugin_path . 'admin/pages/dashboard.php' );
370
- break;
371
- }
372
- }
373
-
374
-
375
- /**
376
- * Get the Google Analytics profiles which are in this google account
377
- *
378
- * @return array
379
- */
380
- public function get_profiles() {
381
- $return = Yoast_Google_Analytics::get_instance()->get_profiles();
382
-
383
- return $return;
384
- }
385
-
386
- /**
387
- * Checks if there is a callback to get token from Google Analytics API
388
- */
389
- private function google_analytics_listener() {
390
- $google_auth_code = filter_input( INPUT_POST, 'google_auth_code' );
391
- if ( $google_auth_code && current_user_can( 'manage_options' ) && wp_verify_nonce( filter_input( INPUT_POST, 'yoast_ga_nonce' ), 'save_settings' ) ) {
392
- self::analytics_api_clean_up();
393
-
394
- Yoast_Google_Analytics::get_instance()->authenticate( trim( $google_auth_code ) );
395
- }
396
- }
397
-
398
- /**
399
- * Clean up the Analytics API settings
400
- */
401
- public static function analytics_api_clean_up() {
402
- delete_option( 'yoast-ga-refresh_token' );
403
- delete_option( 'yst_ga_api_call_fail' );
404
- delete_option( 'yst_ga_last_wp_run' );
405
- delete_option( 'yst_ga_api' );
406
- }
407
-
408
- /**
409
- * Get the current GA profile
410
- *
411
- * @return null
412
- */
413
- private function get_current_profile() {
414
- if ( ! empty( $this->options['analytics_profile'] ) ) {
415
- return $this->options['analytics_profile'];
416
- }
417
-
418
- return null;
419
- }
420
-
421
- /**
422
- * Get the user roles of this WordPress blog
423
- *
424
- * @return array
425
- */
426
- public function get_userroles() {
427
- global $wp_roles;
428
-
429
- $all_roles = $wp_roles->roles;
430
- $roles = array();
431
-
432
- /**
433
- * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
434
- *
435
- * @api array $all_roles
436
- */
437
- $editable_roles = apply_filters( 'editable_roles', $all_roles );
438
-
439
- foreach ( $editable_roles as $id => $name ) {
440
- $roles[] = array(
441
- 'id' => $id,
442
- 'name' => translate_user_role( $name['name'] ),
443
- );
444
- }
445
-
446
- return $roles;
447
- }
448
-
449
- /**
450
- * Get types of how we can track downloads
451
- *
452
- * @return array
453
- */
454
- public function track_download_types() {
455
- return array(
456
- 0 => array( 'id' => 'event', 'name' => __( 'Event', 'google-analytics-for-wordpress' ) ),
457
- 1 => array( 'id' => 'pageview', 'name' => __( 'Pageview', 'google-analytics-for-wordpress' ) ),
458
- );
459
- }
460
-
461
- /**
462
- * Get options for the track full url or links setting
463
- *
464
- * @return array
465
- */
466
- public function get_track_full_url() {
467
- return array(
468
- 0 => array( 'id' => 'domain', 'name' => __( 'Just the domain', 'google-analytics-for-wordpress' ) ),
469
- 1 => array( 'id' => 'full_links', 'name' => __( 'Full links', 'google-analytics-for-wordpress' ) ),
470
- );
471
- }
472
-
473
- /**
474
- * Render the admin page head for the GA Plugin
475
- */
476
- public function content_head() {
477
- require 'views/content_head.php';
478
- }
479
-
480
- /**
481
- * Output System Info file
482
- */
483
- public function system_info() {
484
- if ( ! empty( $_REQUEST['monsterinsights-action'] ) && $_REQUEST['monsterinsights-action'] === 'download_sysinfo' ) {
485
- if ( ! current_user_can( 'manage_options' ) ) {
486
- return;
487
- }
488
- nocache_headers();
489
- header( 'Content-Type: text/plain' );
490
- header( 'Content-Disposition: attachment; filename="monsterinsights-system-info.txt"' );
491
- echo wp_strip_all_tags( $_POST['monsterinsights-sysinfo'] );
492
- die();
493
- }
494
- }
495
-
496
- /**
497
- * Render the admin page footer with sidebar for the GA Plugin
498
- */
499
- public function content_footer() {
500
-
501
- do_action( 'yoast_ga_admin_footer' );
502
-
503
- if ( class_exists( 'MI_Product_GA_Premium' ) ) {
504
- $license_manager = new MI_Plugin_License_Manager( new MI_Product_GA_Premium() );
505
- if ( $license_manager->license_is_valid() ) {
506
- return;
507
- }
508
- }
509
-
510
- $banners = array();
511
- $banners[] = array(
512
- 'url' => 'https://www.optinmonster.com/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
513
- 'banner' => $this->plugin_url . 'assets/img/omupsell.png',
514
- 'title' => 'Convert Visitors into Subscribers',
515
- );
516
- $banners[] = array(
517
- 'url' => 'https://www.monsterinsights.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
518
- 'banner' => $this->plugin_url . 'assets/img/upgradetopro.png',
519
- 'title' => 'Get the premium version of Google Analytics by MonsterInsights!',
520
- );
521
- $banners[] = array(
522
- 'url' => 'http://www.wpbeginner.net/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
523
- 'banner' => $this->plugin_url . 'assets/img/wpbeginnerupsell.png',
524
- 'title' => 'The best collection of free beginner WordPress resources!',
525
- );
526
- $banners[] = array(
527
- 'url' => 'https://wpforms.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
528
- 'banner' => $this->plugin_url . 'assets/img/wpformsupsell.png',
529
- 'title' => 'Get the most beginner friendly WordPress contact form plugin in the market!',
530
- );
531
-
532
- shuffle( $banners );
533
-
534
- require 'views/content-footer.php';
535
-
536
- }
537
-
538
- /**
539
- * Returns a list of all available extensions
540
- *
541
- * @return array
542
- */
543
- public function get_extensions() {
544
- $extensions = array(
545
- 'ga_premium' => (object) array(
546
- 'url' => 'https://www.monsterinsights.com/pricing/',
547
- 'title' => __( 'Google Analytics by MonsterInsights Pro', 'google-analytics-for-wordpress' ),
548
- 'desc' => __( 'The premium version of Google Analytics by MonsterInsights with more features and support.', 'google-analytics-for-wordpress' ),
549
- 'status' => 'uninstalled',
550
- ),
551
- 'ecommerce' => (object) array(
552
- 'url' => 'https://www.monsterinsights.com/pricing/',
553
- 'title' => __( 'Google Analytics by MonsterInsights', 'google-analytics-for-wordpress' ) . '<br />' . __( 'eCommerce tracking', 'google-analytics-for-wordpress' ),
554
- 'desc' => __( 'Track your eCommerce data and transactions with this eCommerce extension for Google Analytics.', 'google-analytics-for-wordpress' ),
555
- 'status' => 'uninstalled',
556
- ),
557
- );
558
-
559
- $extensions = apply_filters( 'yst_ga_extension_status', $extensions );
560
-
561
- return $extensions;
562
- }
563
-
564
- /**
565
- * Add a notification to the notification transient
566
- *
567
- * @param string $transient_name
568
- * @param array $settings
569
- */
570
- private function add_notification( $transient_name, $settings ) {
571
- set_transient( $transient_name, $settings, MINUTE_IN_SECONDS );
572
- }
573
-
574
- /**
575
- * Show the notification that should be set, after showing the notification this function unset the transient
576
- *
577
- * @param string $transient_name The name of the transient which contains the notification
578
- */
579
- public function show_notification( $transient_name ) {
580
- $transient = get_transient( $transient_name );
581
-
582
- if ( isset( $transient['type'] ) && isset( $transient['description'] ) ) {
583
- if ( $transient['type'] == 'success' ) {
584
- add_settings_error(
585
- 'yoast_google_analytics',
586
- 'yoast_google_analytics',
587
- $transient['description'],
588
- 'updated'
589
- );
590
- }
591
- else {
592
- add_settings_error(
593
- 'yoast_google_analytics',
594
- 'yoast_google_analytics',
595
- $transient['description'],
596
- 'error'
597
- );
598
- }
599
-
600
- delete_transient( $transient_name );
601
- }
602
- }
603
-
604
- /**
605
- * Check if there the aggregate data cron is executed
606
- * @return bool
607
- */
608
- private function is_running_cron() {
609
- return doing_action( 'yst_ga_aggregate_data' ) && defined( 'DOING_CRON' ) && DOING_CRON;
610
- }
611
-
612
- /**
613
- * Check if there the aggregate data cron is executed
614
- * @return bool
615
- */
616
- private function is_running_ajax() {
617
- return defined( 'DOING_AJAX' ) && DOING_AJAX && strpos( filter_input( INPUT_GET, 'action' ), 'yoast_dashboard' ) === 0;
618
- }
619
-
620
- }
1
+ <?php
2
+ /**
3
+ * @package GoogleAnalytics\Admin
4
+ */
5
+
6
+ /**
7
+ * This class is for the backend, extendable for all child classes
8
+ */
9
+ class Yoast_GA_Admin extends Yoast_GA_Options {
10
+
11
+ /**
12
+ * Constructor
13
+ */
14
+ public function __construct() {
15
+ parent::__construct();
16
+
17
+ add_action( 'plugins_loaded', array( $this, 'init_ga' ) );
18
+
19
+ // Only run admin_init when there is a cron jon executed.
20
+ $current_page = filter_input( INPUT_GET, 'page' );
21
+
22
+ // Only when current page is not 'wpseo'.
23
+ if ( strpos( $current_page, 'wpseo' ) !== 0 ) {
24
+ if ( ( $this->is_running_cron() || $this->is_running_ajax() ) || strpos( $current_page, 'yst_ga' ) === 0 ) {
25
+ add_action( 'admin_init', array( $this, 'init_settings' ) );
26
+ }
27
+ }
28
+
29
+ add_action( 'admin_init', array( $this, 'system_info' ) );
30
+
31
+ }
32
+
33
+ /**
34
+ * Init function when the plugin is loaded
35
+ */
36
+ public function init_ga() {
37
+
38
+ new Yoast_GA_Admin_Menu( $this );
39
+
40
+ add_filter( 'plugin_action_links_' . plugin_basename( GAWP_FILE ), array( $this, 'add_action_links' ) );
41
+
42
+ }
43
+
44
+ /**
45
+ * Init function for the settings of GA
46
+ */
47
+ public function init_settings() {
48
+ $this->options = $this->get_options();
49
+
50
+ try {
51
+ // Loading Google Api Libs with minimal version 2.0.
52
+ new MI_Api_Libs( '2.0' );
53
+ }
54
+ catch( Exception $exception ) {
55
+ if ( $exception->getMessage() === 'required_version' ) {
56
+ add_action( 'admin_notices', array( $this, 'set_api_libs_error' ) );
57
+ }
58
+ }
59
+
60
+ $dashboards = Yoast_GA_Dashboards::get_instance();
61
+
62
+ // Listener for reconnecting with google analytics
63
+ $this->google_analytics_listener();
64
+
65
+ if ( is_null( $this->get_tracking_code() ) && $this->show_admin_warning() ) {
66
+ add_action( 'admin_notices', array( 'Yoast_Google_Analytics_Notice', 'config_warning' ) );
67
+ }
68
+
69
+ // Check if something has went wrong with GA-api calls
70
+ $has_tracking_code = ( ! is_null( $this->get_tracking_code() ) && empty( $this->options['manual_ua_code_field'] ) );
71
+ if ( $has_tracking_code && $this->show_admin_dashboard_warning() ) {
72
+ Yoast_Google_Analytics::get_instance()->check_for_ga_issues();
73
+ }
74
+
75
+
76
+ if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
77
+ $this->handle_ga_post_request( $dashboards );
78
+ }
79
+
80
+ /**
81
+ * Show the notifications if we have one
82
+ */
83
+ $this->show_notification( 'ga_notifications' );
84
+
85
+ // Load the Google Analytics Dashboards functionality
86
+ $dashboards->init_dashboards( $this->get_current_profile() );
87
+ }
88
+
89
+ /**
90
+ * There is an error with the API libs. So show a notice.
91
+ */
92
+ public function set_api_libs_error() {
93
+ echo '<div class="error notice"><p>' . __( 'MonsterInsights plugins share some code between them to make your site faster. As a result of that, we need all MonsterInsights plugins to be up to date. We\'ve detected this isn\'t the case, so please update the MonsterInsights plugins that aren\'t up to date yet.', 'google-analytics-for-wordpress' ) . '</p></div>';
94
+ }
95
+
96
+ /**
97
+ * This function saves the settings in the option field and returns a wp success message on success
98
+ *
99
+ * @param array $data
100
+ */
101
+ public function save_settings( $data ) {
102
+
103
+ unset( $data['google_auth_code'] );
104
+
105
+ foreach ( $data as $key => $value ) {
106
+ if ( $key != 'return_tab' ) {
107
+ if ( is_string( $value ) ) {
108
+ if ( $key === 'custom_code' && ! current_user_can( 'unfiltered_html' ) ) {
109
+ continue;
110
+ }
111
+ else {
112
+ $value = strip_tags( $value );
113
+ }
114
+ }
115
+
116
+ $this->options[ $key ] = $value;
117
+ }
118
+ }
119
+
120
+ // Check checkboxes, on a uncheck they won't be posted to this function
121
+ $defaults = $this->default_ga_values();
122
+ foreach ( $defaults[ $this->option_prefix ] as $option_name => $value ) {
123
+ $this->handle_default_setting( $data, $option_name, $value );
124
+ }
125
+
126
+ if ( ! empty( $this->options['analytics_profile'] ) ) {
127
+ $this->options['analytics_profile_code'] = $this->get_ua_code_from_profile( $this->options['analytics_profile'] );
128
+ }
129
+
130
+ $this->do_validation( $data['return_tab'] );
131
+
132
+ if ( $this->update_option( $this->options ) ) {
133
+ // Success, add a new notification
134
+ $this->add_notification( 'ga_notifications', array(
135
+ 'type' => 'success',
136
+ 'description' => __( 'Settings saved.', 'google-analytics-for-wordpress' ),
137
+ ) );
138
+ }
139
+ else {
140
+ // Fail, add a new notification
141
+ $this->add_notification( 'ga_notifications', array(
142
+ 'type' => 'error',
143
+ 'description' => __( 'There were no changes to save, please try again.', 'google-analytics-for-wordpress' ),
144
+ ) );
145
+ }
146
+
147
+ // redirect
148
+ wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $data['return_tab'], 301 );
149
+ exit;
150
+ }
151
+
152
+ /**
153
+ * Redirect to settings with a validation error if there are validation errors
154
+ *
155
+ * @param string $return_tab The tab to return to when there is a validation error.
156
+ */
157
+ protected function do_validation( $return_tab ) {
158
+ $validation = $this->validate_settings();
159
+ if ( is_wp_error( $validation ) ) {
160
+ $this->add_notification( 'ga_notifications', array(
161
+ 'type' => 'error',
162
+ 'description' => $validation->get_error_message(),
163
+ ) );
164
+
165
+ wp_redirect( admin_url( 'admin.php' ) . '?page=yst_ga_settings#top#' . $return_tab, 301 );
166
+ exit;
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Validates the settings in the `options` attribute, returns an WP_Error object on error
172
+ *
173
+ * @return true|WP_Error true or an error object.
174
+ */
175
+ protected function validate_settings() {
176
+
177
+ if ( ! empty( $this->options['manual_ua_code_field'] ) ) {
178
+ $this->options['manual_ua_code_field'] = trim( $this->options['manual_ua_code_field'] );
179
+ // en dash to minus, prevents issue with code copied from web with "fancy" dash
180
+ $this->options['manual_ua_code_field'] = str_replace( '–', '-', $this->options['manual_ua_code_field'] );
181
+
182
+ // Regex to tests if a valid UA code has been set. Valid codes follow: "UA-[4 digits]-[at least 1 digit]".
183
+ if ( ! preg_match( '|^UA-\d{4,}-\d+$|', $this->options['manual_ua_code_field'] ) ) {
184
+
185
+ return new WP_Error(
186
+ 'ua-code-format',
187
+ __( 'The UA code needs to follow UA-XXXXXXXX-X format.', 'google-analytics-for-wordpress' )
188
+ );
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Filters the validation for the admin options
194
+ *
195
+ * @param true|WP_Error true if the validation is successful, WP_Error on error.
196
+ * @param array $this->options The options that are being saved.
197
+ */
198
+ return apply_filters( 'yst_ga_admin_validate_settings', true, $this->options );
199
+ }
200
+
201
+ /**
202
+ * Run a this deactivation hook on deactivation of GA. When this happens we'll
203
+ * remove the options for the profiles and the refresh token.
204
+ */
205
+ public static function ga_deactivation_hook() {
206
+ // Remove the refresh token and other API settings
207
+ self::analytics_api_clean_up();
208
+ }
209
+
210
+ /**
211
+ * Handle a default setting in GA
212
+ *
213
+ * @param array $data
214
+ * @param string $option_name
215
+ * @param mixed $value
216
+ */
217
+ private function handle_default_setting( $data, $option_name, $value ) {
218
+ if ( ! isset( $data[ $option_name ] ) ) {
219
+ // If no data was passed in, set it to the default.
220
+ if ( $value === 1 ) {
221
+ // Disable the checkbox for now, use value 0
222
+ $this->options[ $option_name ] = 0;
223
+ }
224
+ else {
225
+ $this->options[ $option_name ] = $value;
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Handle the post requests in the admin form of the GA plugin
232
+ *
233
+ * @param Yoast_GA_Dashboards $dashboards
234
+ */
235
+ private function handle_ga_post_request( $dashboards ) {
236
+ if ( ! function_exists( 'wp_verify_nonce' ) ) {
237
+ require_once( ABSPATH . 'wp-includes/pluggable.php' );
238
+ }
239
+
240
+ if ( isset( $_POST['ga-form-settings'] ) && wp_verify_nonce( $_POST['yoast_ga_nonce'], 'save_settings' ) ) {
241
+ if ( ! isset ( $_POST['ignore_users'] ) ) {
242
+ $_POST['ignore_users'] = array();
243
+ }
244
+
245
+ $dashboards_disabled = Yoast_GA_Settings::get_instance()->dashboards_disabled();
246
+
247
+ if ( ( $dashboards_disabled == false && isset( $_POST['dashboards_disabled'] ) ) || $this->ga_profile_changed( $_POST ) ) {
248
+ $dashboards->reset_dashboards_data();
249
+ }
250
+
251
+ // Post submitted and verified with our nonce
252
+ $this->save_settings( $_POST );
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Is there selected an other property in the settings post? Returns true or false.
258
+ *
259
+ * @param array $post
260
+ *
261
+ * @return bool
262
+ */
263
+ private function ga_profile_changed( $post ) {
264
+ if ( isset( $post['analytics_profile'] ) && isset( $this->options['analytics_profile'] ) ) {
265
+ if ( $post['analytics_profile'] != $this->options['analytics_profile'] ) {
266
+ return true;
267
+ }
268
+ }
269
+
270
+ return false;
271
+ }
272
+
273
+ /**
274
+ * Are we allowed to show a warning message? returns true if it's allowed
275
+ *
276
+ * @return bool
277
+ */
278
+ private function show_admin_warning() {
279
+ return ( current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || ( isset( $_GET['page'] ) && $_GET['page'] !== 'yst_ga_settings' ) ) );
280
+ }
281
+
282
+ /**
283
+ * Are we allowed to show a warning message? returns true if it's allowed ( this is meant to be only for dashboard )
284
+ *
285
+ * @return bool
286
+ */
287
+ private function show_admin_dashboard_warning() {
288
+ return ( current_user_can( 'manage_options' ) && isset( $_GET['page'] ) && $_GET['page'] === 'yst_ga_dashboard' );
289
+ }
290
+
291
+ /**
292
+ * Transform the Profile ID into an helpful UA code
293
+ *
294
+ * @param integer $profile_id
295
+ *
296
+ * @return null
297
+ */
298
+ private function get_ua_code_from_profile( $profile_id ) {
299
+ $profiles = $this->get_profiles();
300
+ $ua_code = null;
301
+
302
+ foreach ( $profiles as $account ) {
303
+ foreach ( $account['items'] as $profile ) {
304
+ foreach ( $profile['items'] as $subprofile ) {
305
+ if ( isset( $subprofile['id'] ) && $subprofile['id'] === $profile_id ) {
306
+ return $subprofile['ua_code'];
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ return $ua_code;
313
+ }
314
+
315
+ /**
316
+ * Add a link to the settings page to the plugins list
317
+ *
318
+ * @param array $links array of links for the plugins, adapted when the current plugin is found.
319
+ *
320
+ * @return array $links
321
+ */
322
+ public function add_action_links( $links ) {
323
+ // add link to knowledgebase
324
+ // @todo UTM link fix
325
+ $faq_link = '<a title="MonsterInsights Knowledge Base" href="http://www.monsterinsights.com/docs/">' . __( 'FAQ', 'google-analytics-for-wordpress' ) . '</a>';
326
+ array_unshift( $links, $faq_link );
327
+
328
+ $settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=yst_ga_settings' ) ) . '">' . __( 'Settings', 'google-analytics-for-wordpress' ) . '</a>';
329
+ array_unshift( $links, $settings_link );
330
+
331
+ return $links;
332
+ }
333
+
334
+ /**
335
+ * Adds some promo text for the premium plugin on the custom dimensions tab.
336
+ */
337
+ public function premium_promo() {
338
+ echo '<div class="ga-promote">';
339
+ echo '<p>';
340
+ printf( __( 'If you want to track custom dimensions like page views per author or post type, you should upgrade to the %1$spremium version of Google Analytics by MonsterInsights%2$s.', 'google-analytics-for-wordpress' ), '<a href="https://www.monsterinsights.com/pricing/#utm_medium=text-link&utm_source=gawp-config&utm_campaign=wpgaplugin&utm_content=custom_dimensions_tab">', '</a>' );
341
+ echo ' ';
342
+ _e( 'This will also give you access to the support team at MonsterInsights, who will provide support on the plugin 24/7.', 'google-analytics-for-wordpress' );
343
+ echo '</p>';
344
+ echo '</div>';
345
+ }
346
+
347
+ /**
348
+ * Load the page of a menu item in the GA plugin
349
+ */
350
+ public function load_page() {
351
+
352
+ if ( ! has_action( 'yst_ga_custom_dimensions_tab-content' ) ) {
353
+ add_action( 'yst_ga_custom_dimensions_tab-content', array( $this, 'premium_promo' ) );
354
+ }
355
+
356
+ if ( ! has_action( 'yst_ga_custom_dimension_add-dashboards-tab' ) ) {
357
+ add_action( 'yst_ga_custom_dimension_add-dashboards-tab', array( $this, 'premium_promo' ) );
358
+ }
359
+
360
+ switch ( filter_input( INPUT_GET, 'page' ) ) {
361
+ case 'yst_ga_settings':
362
+ require_once( $this->plugin_path . 'admin/pages/settings.php' );
363
+ break;
364
+ case 'yst_ga_extensions':
365
+ require_once( $this->plugin_path . 'admin/pages/extensions.php' );
366
+ break;
367
+ case 'yst_ga_dashboard':
368
+ default:
369
+ require_once( $this->plugin_path . 'admin/pages/dashboard.php' );
370
+ break;
371
+ }
372
+ }
373
+
374
+
375
+ /**
376
+ * Get the Google Analytics profiles which are in this google account
377
+ *
378
+ * @return array
379
+ */
380
+ public function get_profiles() {
381
+ $return = Yoast_Google_Analytics::get_instance()->get_profiles();
382
+
383
+ return $return;
384
+ }
385
+
386
+ /**
387
+ * Checks if there is a callback to get token from Google Analytics API
388
+ */
389
+ private function google_analytics_listener() {
390
+ $google_auth_code = filter_input( INPUT_POST, 'google_auth_code' );
391
+ if ( $google_auth_code && current_user_can( 'manage_options' ) && wp_verify_nonce( filter_input( INPUT_POST, 'yoast_ga_nonce' ), 'save_settings' ) ) {
392
+ self::analytics_api_clean_up();
393
+
394
+ Yoast_Google_Analytics::get_instance()->authenticate( trim( $google_auth_code ) );
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Clean up the Analytics API settings
400
+ */
401
+ public static function analytics_api_clean_up() {
402
+ delete_option( 'yoast-ga-refresh_token' );
403
+ delete_option( 'yst_ga_api_call_fail' );
404
+ delete_option( 'yst_ga_last_wp_run' );
405
+ delete_option( 'yst_ga_api' );
406
+ }
407
+
408
+ /**
409
+ * Get the current GA profile
410
+ *
411
+ * @return null
412
+ */
413
+ private function get_current_profile() {
414
+ if ( ! empty( $this->options['analytics_profile'] ) ) {
415
+ return $this->options['analytics_profile'];
416
+ }
417
+
418
+ return null;
419
+ }
420
+
421
+ /**
422
+ * Get the user roles of this WordPress blog
423
+ *
424
+ * @return array
425
+ */
426
+ public function get_userroles() {
427
+ global $wp_roles;
428
+
429
+ $all_roles = $wp_roles->roles;
430
+ $roles = array();
431
+
432
+ /**
433
+ * Filter: 'editable_roles' - Allows filtering of the roles shown within the plugin (and elsewhere in WP as it's a WP filter)
434
+ *
435
+ * @api array $all_roles
436
+ */
437
+ $editable_roles = apply_filters( 'editable_roles', $all_roles );
438
+
439
+ foreach ( $editable_roles as $id => $name ) {
440
+ $roles[] = array(
441
+ 'id' => $id,
442
+ 'name' => translate_user_role( $name['name'] ),
443
+ );
444
+ }
445
+
446
+ return $roles;
447
+ }
448
+
449
+ /**
450
+ * Get types of how we can track downloads
451
+ *
452
+ * @return array
453
+ */
454
+ public function track_download_types() {
455
+ return array(
456
+ 0 => array( 'id' => 'event', 'name' => __( 'Event', 'google-analytics-for-wordpress' ) ),
457
+ 1 => array( 'id' => 'pageview', 'name' => __( 'Pageview', 'google-analytics-for-wordpress' ) ),
458
+ );
459
+ }
460
+
461
+ /**
462
+ * Get options for the track full url or links setting
463
+ *
464
+ * @return array
465
+ */
466
+ public function get_track_full_url() {
467
+ return array(
468
+ 0 => array( 'id' => 'domain', 'name' => __( 'Just the domain', 'google-analytics-for-wordpress' ) ),
469
+ 1 => array( 'id' => 'full_links', 'name' => __( 'Full links', 'google-analytics-for-wordpress' ) ),
470
+ );
471
+ }
472
+
473
+ /**
474
+ * Render the admin page head for the GA Plugin
475
+ */
476
+ public function content_head() {
477
+ require 'views/content_head.php';
478
+ }
479
+
480
+ /**
481
+ * Output System Info file
482
+ */
483
+ public function system_info() {
484
+ if ( ! empty( $_REQUEST['monsterinsights-action'] ) && $_REQUEST['monsterinsights-action'] === 'download_sysinfo' ) {
485
+ if ( ! current_user_can( 'manage_options' ) ) {
486
+ return;
487
+ }
488
+ nocache_headers();
489
+ header( 'Content-Type: text/plain' );
490
+ header( 'Content-Disposition: attachment; filename="monsterinsights-system-info.txt"' );
491
+ echo wp_strip_all_tags( $_POST['monsterinsights-sysinfo'] );
492
+ die();
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Render the admin page footer with sidebar for the GA Plugin
498
+ */
499
+ public function content_footer() {
500
+
501
+ do_action( 'yoast_ga_admin_footer' );
502
+
503
+ if ( class_exists( 'MI_Product_GA_Premium' ) ) {
504
+ $license_manager = new MI_Plugin_License_Manager( new MI_Product_GA_Premium() );
505
+ if ( $license_manager->license_is_valid() ) {
506
+ return;
507
+ }
508
+ }
509
+
510
+ $banners = array();
511
+ $banners[] = array(
512
+ 'url' => 'https://optinmonster.com/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
513
+ 'banner' => $this->plugin_url . 'assets/img/omupsell.png',
514
+ 'title' => 'Convert Visitors into Subscribers',
515
+ );
516
+ $banners[] = array(
517
+ 'url' => 'https://www.monsterinsights.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
518
+ 'banner' => $this->plugin_url . 'assets/img/upgradetopro.png',
519
+ 'title' => 'Get the premium version of Google Analytics by MonsterInsights!',
520
+ );
521
+ $banners[] = array(
522
+ 'url' => 'http://www.wpbeginner.net/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
523
+ 'banner' => $this->plugin_url . 'assets/img/wpbeginnerupsell.png',
524
+ 'title' => 'The best collection of free beginner WordPress resources!',
525
+ );
526
+ $banners[] = array(
527
+ 'url' => 'https://wpforms.com/pricing/?utm_source=monsterinsights-config&utm_medium=banner&utm_campaign=gaplugin',
528
+ 'banner' => $this->plugin_url . 'assets/img/wpformsupsell.png',
529
+ 'title' => 'Get the most beginner friendly WordPress contact form plugin in the market!',
530
+ );
531
+
532
+ shuffle( $banners );
533
+
534
+ require 'views/content-footer.php';
535
+
536
+ }
537
+
538
+ /**
539
+ * Returns a list of all available extensions
540
+ *
541
+ * @return array
542
+ */
543
+ public function get_extensions() {
544
+ $extensions = array(
545
+ 'ga_premium' => (object) array(
546
+ 'url' => 'https://www.monsterinsights.com/pricing/',
547
+ 'title' => __( 'Google Analytics by MonsterInsights Pro', 'google-analytics-for-wordpress' ),
548
+ 'desc' => __( 'The premium version of Google Analytics by MonsterInsights with more features and support.', 'google-analytics-for-wordpress' ),
549
+ 'status' => 'uninstalled',
550
+ ),
551
+ 'ecommerce' => (object) array(
552
+ 'url' => 'https://www.monsterinsights.com/pricing/',
553
+ 'title' => __( 'Google Analytics by MonsterInsights', 'google-analytics-for-wordpress' ) . '<br />' . __( 'eCommerce tracking', 'google-analytics-for-wordpress' ),
554
+ 'desc' => __( 'Track your eCommerce data and transactions with this eCommerce extension for Google Analytics.', 'google-analytics-for-wordpress' ),
555
+ 'status' => 'uninstalled',
556
+ ),
557
+ );
558
+
559
+ $extensions = apply_filters( 'yst_ga_extension_status', $extensions );
560
+
561
+ return $extensions;
562
+ }
563
+
564
+ /**
565
+ * Add a notification to the notification transient
566
+ *
567
+ * @param string $transient_name
568
+ * @param array $settings
569
+ */
570
+ private function add_notification( $transient_name, $settings ) {
571
+ set_transient( $transient_name, $settings, MINUTE_IN_SECONDS );
572
+ }
573
+
574
+ /**
575
+ * Show the notification that should be set, after showing the notification this function unset the transient
576
+ *
577
+ * @param string $transient_name The name of the transient which contains the notification
578
+ */
579
+ public function show_notification( $transient_name ) {
580
+ $transient = get_transient( $transient_name );
581
+
582
+ if ( isset( $transient['type'] ) && isset( $transient['description'] ) ) {
583
+ if ( $transient['type'] == 'success' ) {
584
+ add_settings_error(
585
+ 'yoast_google_analytics',
586
+ 'yoast_google_analytics',
587
+ $transient['description'],
588
+ 'updated'
589
+ );
590
+ }
591
+ else {
592
+ add_settings_error(
593
+ 'yoast_google_analytics',
594
+ 'yoast_google_analytics',
595
+ $transient['description'],
596
+ 'error'
597
+ );
598
+ }
599
+
600
+ delete_transient( $transient_name );
601
+ }
602
+ }
603
+
604
+ /**
605
+ * Check if there the aggregate data cron is executed
606
+ * @return bool
607
+ */
608
+ private function is_running_cron() {
609
+ return doing_action( 'yst_ga_aggregate_data' ) && defined( 'DOING_CRON' ) && DOING_CRON;
610
+ }
611
+
612
+ /**
613
+ * Check if there the aggregate data cron is executed
614
+ * @return bool
615
+ */
616
+ private function is_running_ajax() {
617
+ return defined( 'DOING_AJAX' ) && DOING_AJAX && strpos( filter_input( INPUT_GET, 'action' ), 'yoast_dashboard' ) === 0;
618
+ }
619
+
620
+ }
googleanalytics.php CHANGED
@@ -9,7 +9,7 @@
9
  * Plugin URI: https://www.monsterinsights.com/pricing/#utm_source=wordpress&utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v504
10
  * Description: This plugin makes it simple to add Google Analytics to your WordPress site, adding lots of features, e.g. error page, search result and automatic outgoing links and download tracking.
11
  * Author: MonsterInsights
12
- * Version: 5.5
13
  * Requires at least: 3.9
14
  * Author URI: https://www.monsterinsights.com/
15
  * License: GPL v3
@@ -35,7 +35,7 @@
35
 
36
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
37
 
38
- define( 'GAWP_VERSION', '5.5' );
39
 
40
  define( 'GAWP_FILE', __FILE__ );
41
 
9
  * Plugin URI: https://www.monsterinsights.com/pricing/#utm_source=wordpress&utm_medium=plugin&utm_campaign=wpgaplugin&utm_content=v504
10
  * Description: This plugin makes it simple to add Google Analytics to your WordPress site, adding lots of features, e.g. error page, search result and automatic outgoing links and download tracking.
11
  * Author: MonsterInsights
12
+ * Version: 5.5.2
13
  * Requires at least: 3.9
14
  * Author URI: https://www.monsterinsights.com/
15
  * License: GPL v3
35
 
36
  // This plugin was originally based on Rich Boakes' Analytics plugin: http://boakes.org/analytics, but has since been rewritten and refactored multiple times.
37
 
38
+ define( 'GAWP_VERSION', '5.5.2' );
39
 
40
  define( 'GAWP_FILE', __FILE__ );
41
 
includes/ecommerce-addon-license-fix.php CHANGED
@@ -17,15 +17,19 @@ if ( ! class_exists( 'MI_Product_GA_eCommerce', false ) && class_exists( 'MI_Pro
17
 
18
 
19
  public function __construct() {
 
 
 
20
  parent::__construct(
21
  'https://www.monsterinsights.com',
22
  'eCommerce Addon',
23
- plugin_basename( Yoast_GA_eCommerce_Tracking::PLUGIN_FILE ),
24
  Yoast_GA_eCommerce_Tracking::VERSION,
25
  'https://www.monsterinsights.com/pricing/',
26
  'admin.php?page=yst_ga_extensions#top#licenses',
27
  'yoast-ga-ecommerce',
28
- 'MonsterInsights'
 
29
  );
30
 
31
  $this->setup_license_manager();
17
 
18
 
19
  public function __construct() {
20
+ $file = plugin_basename( Yoast_GA_eCommerce_Tracking::PLUGIN_FILE );
21
+ $slug = dirname( $file );
22
+
23
  parent::__construct(
24
  'https://www.monsterinsights.com',
25
  'eCommerce Addon',
26
+ $slug,
27
  Yoast_GA_eCommerce_Tracking::VERSION,
28
  'https://www.monsterinsights.com/pricing/',
29
  'admin.php?page=yst_ga_extensions#top#licenses',
30
  'yoast-ga-ecommerce',
31
+ 'MonsterInsights',
32
+ $file
33
  );
34
 
35
  $this->setup_license_manager();
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: chriscct7, smub
3
  Donate link: http://www.wpbeginner.com/wpbeginner-needs-your-help/
4
  Tags: analytics, analytics dashboard, google analytics, google analytics dashboard, google analytics widget, universal google analytics, statistics, tracking, stats, google, yoast, google analytics by yoast, ga, monster insights, monsterinsights, universal analytics, web stats, ecommerce, ecommerce tracking
5
  Requires at least: 3.9
6
- Tested up to: 4.5
7
- Stable tag: 5.5
8
  License: GPL v3
9
 
10
  Connect Google Analytics with WordPress by adding your Google Analytics tracking code. Get the stats that matter.
@@ -70,6 +70,16 @@ You can also learn about other <a href="http://www.wpbeginner.com/category/plugi
70
 
71
  == Changelog ==
72
 
 
 
 
 
 
 
 
 
 
 
73
  = 5.5 =
74
 
75
  Release Date: May 1st, 2016
3
  Donate link: http://www.wpbeginner.com/wpbeginner-needs-your-help/
4
  Tags: analytics, analytics dashboard, google analytics, google analytics dashboard, google analytics widget, universal google analytics, statistics, tracking, stats, google, yoast, google analytics by yoast, ga, monster insights, monsterinsights, universal analytics, web stats, ecommerce, ecommerce tracking
5
  Requires at least: 3.9
6
+ Tested up to: 4.6
7
+ Stable tag: 5.5.2
8
  License: GPL v3
9
 
10
  Connect Google Analytics with WordPress by adding your Google Analytics tracking code. Get the stats that matter.
70
 
71
  == Changelog ==
72
 
73
+ = 5.5.2 =
74
+
75
+ Release Date: July 7th, 2016
76
+
77
+ * Bugfixes:
78
+ * Fixes compatibiltiy with upcoming Shiny Updates v2 in WP core
79
+
80
+ * Enhancements:
81
+ * Updates license manager to have more reliable update information including better compatibility with Yoast SEO products.
82
+
83
  = 5.5 =
84
 
85
  Release Date: May 1st, 2016
vendor/yoast/license-manager-2/.gitigore CHANGED
@@ -1,2 +1,2 @@
1
- .idea/
2
- .idea/*
1
+ .idea/
2
+ .idea/*
vendor/yoast/license-manager-2/class-api-request.php CHANGED
@@ -1,140 +1,138 @@
1
- <?php
2
-
3
- if( ! class_exists( "Yoast_API_Request", false ) ) {
4
-
5
- /**
6
- * Handles requests to the Yoast EDD API
7
- */
8
- class Yoast_API_Request {
9
-
10
- /**
11
- * @var string Request URL
12
- */
13
- private $url = '';
14
-
15
- /**
16
- * @var array Request parameters
17
- */
18
- private $args = array(
19
- 'method' => 'GET',
20
- 'timeout' => 10,
21
- 'sslverify' => false,
22
- 'headers' => array(
23
- 'Accept-Encoding' => '*',
24
- 'X-Yoast-EDD' => '1'
25
- )
26
- );
27
-
28
- /**
29
- * @var boolean
30
- */
31
- private $success = false;
32
-
33
- /**
34
- * @var mixed
35
- */
36
- private $response;
37
-
38
- /**
39
- * @var string
40
- */
41
- private $error_message = '';
42
-
43
- /**
44
- * Constructor
45
- *
46
- * @param string url
47
- * @param array $args
48
- */
49
- public function __construct( $url, array $args = array() ) {
50
-
51
- // set api url
52
- $this->url = $url;
53
-
54
- // set request args (merge with defaults)
55
- $this->args = wp_parse_args( $args, $this->args );
56
-
57
- // fire the request
58
- $this->success = $this->fire();
59
- }
60
-
61
- /**
62
- * Fires the request, automatically called from constructor
63
- *
64
- * @return boolean
65
- */
66
- private function fire() {
67
-
68
- // fire request to shop
69
- $response = wp_remote_request( $this->url, $this->args );
70
-
71
- // validate raw response
72
- if( $this->validate_raw_response( $response ) === false ) {
73
- return false;
74
- }
75
-
76
- // decode the response
77
- $this->response = json_decode( wp_remote_retrieve_body( $response ) );
78
-
79
- // response should be an object
80
- if( ! is_object( $this->response ) ) {
81
- $this->error_message = 'No JSON object was returned.';
82
- return false;
83
- }
84
-
85
- return true;
86
- }
87
-
88
- /**
89
- * @param object $response
90
- * @return boolean
91
- */
92
- private function validate_raw_response( $response ) {
93
-
94
- // make sure response came back okay
95
- if( is_wp_error( $response ) ) {
96
- $this->error_message = $response->get_error_message();
97
- return false;
98
- }
99
-
100
- // check response code, should be 200
101
- $response_code = wp_remote_retrieve_response_code( $response );
102
-
103
- if( false === strstr( $response_code, '200' ) ) {
104
-
105
- $response_message = wp_remote_retrieve_response_message( $response );
106
- $this->error_message = "{$response_code} {$response_message}";
107
-
108
- return false;
109
- }
110
-
111
- return true;
112
- }
113
-
114
- /**
115
- * Was a valid response returned?
116
- *
117
- * @return boolean
118
- */
119
- public function is_valid() {
120
- return ( $this->success === true );
121
- }
122
-
123
- /**
124
- * @return string
125
- */
126
- public function get_error_message() {
127
- return $this->error_message;
128
- }
129
-
130
- /**
131
- * @return object
132
- */
133
- public function get_response() {
134
- return $this->response;
135
- }
136
-
137
- }
138
-
139
- }
140
-
1
+ <?php
2
+
3
+ if ( ! class_exists( "Yoast_API_Request", false ) ) {
4
+
5
+ /**
6
+ * Handles requests to the Yoast EDD API
7
+ */
8
+ class Yoast_API_Request {
9
+
10
+ /**
11
+ * @var string Request URL
12
+ */
13
+ private $url = '';
14
+
15
+ /**
16
+ * @var array Request parameters
17
+ */
18
+ private $args = array(
19
+ 'method' => 'GET',
20
+ 'timeout' => 10,
21
+ 'sslverify' => false,
22
+ 'headers' => array(
23
+ 'Accept-Encoding' => '*',
24
+ 'X-Yoast-EDD' => '1'
25
+ )
26
+ );
27
+
28
+ /**
29
+ * @var boolean
30
+ */
31
+ private $success = false;
32
+
33
+ /**
34
+ * @var mixed
35
+ */
36
+ private $response;
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ private $error_message = '';
42
+
43
+ /**
44
+ * Constructor
45
+ *
46
+ * @param string url
47
+ * @param array $args
48
+ */
49
+ public function __construct( $url, array $args = array() ) {
50
+
51
+ // set api url
52
+ $this->url = $url;
53
+
54
+ // set request args (merge with defaults)
55
+ $this->args = wp_parse_args( $args, $this->args );
56
+
57
+ // fire the request
58
+ $this->success = $this->fire();
59
+ }
60
+
61
+ /**
62
+ * Fires the request, automatically called from constructor
63
+ *
64
+ * @return boolean
65
+ */
66
+ private function fire() {
67
+
68
+ // fire request to shop
69
+ $response = wp_remote_request( $this->url, $this->args );
70
+
71
+ // validate raw response
72
+ if( $this->validate_raw_response( $response ) === false ) {
73
+ return false;
74
+ }
75
+
76
+ // decode the response
77
+ $this->response = json_decode( wp_remote_retrieve_body( $response ) );
78
+
79
+ // response should be an object
80
+ if( ! is_object( $this->response ) ) {
81
+ $this->error_message = 'No JSON object was returned.';
82
+ return false;
83
+ }
84
+
85
+ return true;
86
+ }
87
+
88
+ /**
89
+ * @param object $response
90
+ * @return boolean
91
+ */
92
+ private function validate_raw_response( $response ) {
93
+
94
+ // make sure response came back okay
95
+ if( is_wp_error( $response ) ) {
96
+ $this->error_message = $response->get_error_message();
97
+ return false;
98
+ }
99
+
100
+ // check response code, should be 200
101
+ $response_code = wp_remote_retrieve_response_code( $response );
102
+
103
+ if( false === strstr( $response_code, '200' ) ) {
104
+
105
+ $response_message = wp_remote_retrieve_response_message( $response );
106
+ $this->error_message = "{$response_code} {$response_message}";
107
+
108
+ return false;
109
+ }
110
+
111
+ return true;
112
+ }
113
+
114
+ /**
115
+ * Was a valid response returned?
116
+ *
117
+ * @return boolean
118
+ */
119
+ public function is_valid() {
120
+ return ( $this->success === true );
121
+ }
122
+
123
+ /**
124
+ * @return string
125
+ */
126
+ public function get_error_message() {
127
+ return $this->error_message;
128
+ }
129
+
130
+ /**
131
+ * @return object
132
+ */
133
+ public function get_response() {
134
+ return $this->response;
135
+ }
136
+ }
137
+
138
+ }
 
 
vendor/yoast/license-manager-2/class-license-manager.php CHANGED
@@ -1,619 +1,613 @@
1
- <?php
2
-
3
- if ( ! interface_exists( 'iYoast_License_Manager', false ) ) {
4
-
5
- interface iYoast_License_Manager {
6
-
7
- public function specific_hooks();
8
-
9
- public function setup_auto_updater();
10
-
11
- }
12
-
13
- }
14
-
15
-
16
- if ( ! class_exists( 'Yoast_License_Manager', false ) ) {
17
-
18
- /**
19
- * Class Yoast_License_Manager
20
- *
21
- * @todo Maybe create a license class that contains key and option
22
- * @todo Not sure if Yoast_License_Manager is a good name for this class, it's more managing the product (plugin or theme)
23
- */
24
- abstract class Yoast_License_Manager implements iYoast_License_Manager {
25
-
26
- /**
27
- * @const VERSION The version number of the License_Manager class
28
- */
29
- const VERSION = 1;
30
-
31
- /**
32
- * @var Yoast_License The license
33
- */
34
- protected $product;
35
-
36
- /**
37
- * @var string
38
- */
39
- private $license_constant_name = '';
40
-
41
- /**
42
- * @var boolean True if license is defined with a constant
43
- */
44
- private $license_constant_is_defined = false;
45
-
46
- /**
47
- * @var boolean True if remote license activation just failed
48
- */
49
- private $remote_license_activation_failed = false;
50
-
51
- /**
52
- * @var array Array of license related options
53
- */
54
- private $options = array();
55
-
56
- /**
57
- * @var string Used to prefix ID's, option names, etc..
58
- */
59
- protected $prefix;
60
-
61
- /**
62
- * @var bool Boolean indicating whether this plugin is network activated
63
- */
64
- protected $is_network_activated = false;
65
-
66
- /**
67
- * Constructor
68
- *
69
- * @param Yoast_Product $product
70
- */
71
- public function __construct( Yoast_Product $product ) {
72
-
73
- // Set the license
74
- $this->product = $product;
75
-
76
- // set prefix
77
- $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' );
78
-
79
- // maybe set license key from constant
80
- $this->maybe_set_license_key_from_constant();
81
- }
82
-
83
- /**
84
- * Setup hooks
85
- *
86
- */
87
- public function setup_hooks() {
88
-
89
- // show admin notice if license is not active
90
- add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
91
-
92
- // catch POST requests from license form
93
- add_action( 'admin_init', array( $this, 'catch_post_request' ) );
94
-
95
- // setup item type (plugin|theme) specific hooks
96
- $this->specific_hooks();
97
-
98
- // setup the auto updater
99
- $this->setup_auto_updater();
100
-
101
- }
102
-
103
- /**
104
- * Display license specific admin notices, namely:
105
- *
106
- * - License for the product isn't activated
107
- * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL
108
- */
109
- public function display_admin_notices() {
110
-
111
- if ( ! current_user_can( 'manage_options' ) ) {
112
- return;
113
- }
114
-
115
- // show notice if license is invalid
116
- if ( ! $this->license_is_valid() ) {
117
- if ( $this->get_license_key() == '' ) {
118
- $message = '<b>Warning!</b> You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! <a href="%s">Enter your license key</a> or <a href="%s" target="_blank">get a license here</a>.';
119
- } else {
120
- $message = '<b>Warning!</b> Your %s license is inactive which means you\'re missing out on updates and support! <a href="%s">Activate your license</a> or <a href="%s" target="_blank">get a license here</a>.';
121
- }
122
- ?>
123
- <div class="error">
124
- <p><?php printf( __( $message, $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?></p>
125
- </div>
126
- <?php
127
- }
128
-
129
- // show notice if external requests are blocked through the WP_HTTP_BLOCK_EXTERNAL constant
130
- if ( defined( "WP_HTTP_BLOCK_EXTERNAL" ) && WP_HTTP_BLOCK_EXTERNAL === true ) {
131
-
132
- // check if our API endpoint is in the allowed hosts
133
- $host = parse_url( $this->product->get_api_url(), PHP_URL_HOST );
134
-
135
- if ( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) {
136
- ?>
137
- <div class="error">
138
- <p><?php printf( __( '<b>Warning!</b> You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '<strong>' . $host . '</strong>', '<code>WP_ACCESSIBLE_HOSTS</code>' ); ?></p>
139
- </div>
140
- <?php
141
- }
142
-
143
- }
144
- }
145
-
146
- /**
147
- * Set a notice to display in the admin area
148
- *
149
- * @param string $type error|updated
150
- * @param string $message The message to display
151
- */
152
- protected function set_notice( $message, $success = true ) {
153
- $css_class = ( $success ) ? 'updated' : 'error';
154
- add_settings_error( $this->prefix . 'license', 'license-notice', $message, $css_class );
155
- }
156
-
157
- /**
158
- * Remotely activate License
159
- * @return boolean True if the license is now activated, false if not
160
- */
161
- public function activate_license() {
162
-
163
- $result = $this->call_license_api( 'activate' );
164
-
165
-
166
- if ( $result ) {
167
-
168
- // story expiry date
169
- if ( isset( $result->expires ) ) {
170
- $this->set_license_expiry_date( $result->expires );
171
- $expiry_date = strtotime( $result->expires );
172
- } else {
173
- $expiry_date = false;
174
- }
175
-
176
- // show success notice if license is valid
177
- if ( $result->license === 'valid' ) {
178
-
179
- $message = sprintf( __( "Your %s license has been activated. ", $this->product->get_text_domain() ), $this->product->get_item_name() );
180
-
181
- // show a custom notice if users have an unlimited license
182
- if ( $result->license_limit == 0 ) {
183
- $message .= __( "You have an unlimited license. ", $this->product->get_text_domain() );
184
- } else {
185
- $message .= sprintf( __( "You have used %d/%d activations. ", $this->product->get_text_domain() ), $result->site_count, $result->license_limit );
186
- }
187
-
188
- // add upgrade notice if user has less than 3 activations left
189
- if ( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) {
190
- $message .= sprintf( __( '<a href="%s">Did you know you can upgrade your license?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-nearing-limit-notice' ) );
191
- // add extend notice if license is expiring in less than 1 month
192
- } elseif ( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) {
193
- $days_left = round( ( $expiry_date - strtotime( "now" ) ) / 86400 );
194
- $message .= sprintf( __( '<a href="%s">Your license is expiring in %d days, would you like to extend it?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expiring-notice' ), $days_left );
195
- }
196
-
197
- $this->set_notice( $message, true );
198
-
199
- } else {
200
-
201
- if ( isset( $result->error ) && $result->error === 'no_activations_left' ) {
202
- // show notice if user is at their activation limit
203
- $this->set_notice( sprintf( __( 'You\'ve reached your activation limit. You must <a href="%s">upgrade your license</a> to use it on this site.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-at-limit-notice' ) ), false );
204
- } elseif ( isset( $result->error ) && $result->error == "expired" ) {
205
- // show notice if the license is expired
206
- $this->set_notice( sprintf( __( 'Your license has expired. You must <a href="%s">extend your license</a> in order to use it again.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expired-notice' ) ), false );
207
- } else {
208
- // show a general notice if it's any other error
209
- $this->set_notice( __( "Failed to activate your license, your license key seems to be invalid.", $this->product->get_text_domain() ), false );
210
- }
211
-
212
- $this->remote_license_activation_failed = true;
213
- }
214
-
215
- $this->set_license_status( $result->license );
216
- }
217
-
218
- return ( $this->license_is_valid() );
219
- }
220
-
221
- /**
222
- * Remotely deactivate License
223
- * @return boolean True if the license is now deactivated, false if not
224
- */
225
- public function deactivate_license() {
226
-
227
- $result = $this->call_license_api( 'deactivate' );
228
-
229
- if ( $result ) {
230
-
231
- // show notice if license is deactivated
232
- if ( $result->license === 'deactivated' ) {
233
- $this->set_notice( sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ) );
234
- } else {
235
- $this->set_notice( sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ), false );
236
- }
237
-
238
- $this->set_license_status( $result->license );
239
- }
240
-
241
- return ( $this->get_license_status() === 'deactivated' );
242
- }
243
-
244
- /**
245
- * @param string $action activate|deactivate
246
- *
247
- * @return mixed
248
- */
249
- protected function call_license_api( $action ) {
250
-
251
- // don't make a request if license key is empty
252
- if ( $this->get_license_key() === '' ) {
253
- return false;
254
- }
255
-
256
- // data to send in our API request
257
- $api_params = array(
258
- 'edd_action' => $action . '_license',
259
- 'license' => $this->get_license_key(),
260
- 'item_name' => urlencode( trim( $this->product->get_item_name() ) ),
261
- 'url' => get_option( 'home' ) // grab the URL straight from the option to prevent filters from breaking it.
262
- );
263
-
264
- // create api request url
265
- $url = add_query_arg( $api_params, $this->product->get_api_url() );
266
-
267
- require_once dirname( __FILE__ ) . '/class-api-request.php';
268
- $request = new Yoast_API_Request( $url );
269
-
270
- if ( $request->is_valid() !== true ) {
271
- $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '<a href="http://kb.yoast.com/article/13-license-activation-notices">', '</a>' ), false );
272
- }
273
-
274
- // get response
275
- $response = $request->get_response();
276
-
277
- // update license status
278
- $license_data = $response;
279
-
280
- return $license_data;
281
- }
282
-
283
-
284
- /**
285
- * Set the license status
286
- *
287
- * @param string $license_status
288
- */
289
- public function set_license_status( $license_status ) {
290
- $this->set_option( 'status', $license_status );
291
- }
292
-
293
- /**
294
- * Get the license status
295
- *
296
- * @return string $license_status;
297
- */
298
- public function get_license_status() {
299
- $license_status = $this->get_option( 'status' );
300
-
301
- return trim( $license_status );
302
- }
303
-
304
- /**
305
- * Set the license key
306
- *
307
- * @param string $license_key
308
- */
309
- public function set_license_key( $license_key ) {
310
- $this->set_option( 'key', $license_key );
311
- }
312
-
313
- /**
314
- * Gets the license key from constant or option
315
- *
316
- * @return string $license_key
317
- */
318
- public function get_license_key() {
319
- $license_key = $this->get_option( 'key' );
320
-
321
- return trim( $license_key );
322
- }
323
-
324
- /**
325
- * Gets the license expiry date
326
- *
327
- * @return string
328
- */
329
- public function get_license_expiry_date() {
330
- return $this->get_option( 'expiry_date' );
331
- }
332
-
333
- /**
334
- * Stores the license expiry date
335
- */
336
- public function set_license_expiry_date( $expiry_date ) {
337
- $this->set_option( 'expiry_date', $expiry_date );
338
- }
339
-
340
- /**
341
- * Checks whether the license status is active
342
- *
343
- * @return boolean True if license is active
344
- */
345
- public function license_is_valid() {
346
- return ( $this->get_license_status() === 'valid' );
347
- }
348
-
349
- /**
350
- * Get all license related options
351
- *
352
- * @return array Array of license options
353
- */
354
- protected function get_options() {
355
-
356
- // create option name
357
- $option_name = $this->prefix . 'license';
358
-
359
- // get array of options from db
360
- if ( $this->is_network_activated ) {
361
- $options = get_site_option( $option_name, array() );
362
- } else {
363
- $options = get_option( $option_name, array() );
364
- }
365
-
366
- // setup array of defaults
367
- $defaults = array(
368
- 'key' => '',
369
- 'status' => '',
370
- 'expiry_date' => ''
371
- );
372
-
373
- // merge options with defaults
374
- $this->options = wp_parse_args( $options, $defaults );
375
-
376
- return $this->options;
377
- }
378
-
379
- /**
380
- * Set license related options
381
- *
382
- * @param array $options Array of new license options
383
- */
384
- protected function set_options( array $options ) {
385
- // create option name
386
- $option_name = $this->prefix . 'license';
387
-
388
- // update db
389
- if ( $this->is_network_activated ) {
390
- update_site_option( $option_name, $options );
391
- } else {
392
- update_option( $option_name, $options );
393
- }
394
-
395
- }
396
-
397
- /**
398
- * Gets a license related option
399
- *
400
- * @param string $name The option name
401
- *
402
- * @return mixed The option value
403
- */
404
- protected function get_option( $name ) {
405
- $options = $this->get_options();
406
-
407
- return $options[$name];
408
- }
409
-
410
- /**
411
- * Set a license related option
412
- *
413
- * @param string $name The option name
414
- * @param mixed $value The option value
415
- */
416
- protected function set_option( $name, $value ) {
417
- // get options
418
- $options = $this->get_options();
419
-
420
- // update option
421
- $options[$name] = $value;
422
-
423
- // save options
424
- $this->set_options( $options );
425
- }
426
-
427
- public function show_license_form_heading() {
428
- ?>
429
- <h3>
430
- <?php printf( __( "%s: License Settings", $this->product->get_text_domain() ), $this->product->get_item_name() ); ?>&nbsp; &nbsp;
431
- </h3>
432
- <?php
433
- }
434
-
435
- /**
436
- * Show a form where users can enter their license key
437
- *
438
- * @param boolean $embedded Boolean indicating whether this form is embedded in another form?
439
- */
440
- public function show_license_form( $embedded = true ) {
441
- $key_name = $this->prefix . 'license_key';
442
- $nonce_name = $this->prefix . 'license_nonce';
443
- $action_name = $this->prefix . 'license_action';
444
-
445
- $api_host_available = $this->get_api_availability();
446
-
447
- $visible_license_key = $this->get_license_key();
448
-
449
- // obfuscate license key
450
- $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) );
451
-
452
- if ( $obfuscate ) {
453
- $visible_license_key = str_repeat( '*', strlen( $this->get_license_key() ) - 4 ) . substr( $this->get_license_key(), - 4 );
454
- }
455
-
456
- // make license key readonly when license key is valid or license is defined with a constant
457
- $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined );
458
-
459
- require dirname( __FILE__ ) . '/views/form.php';
460
-
461
- // enqueue script in the footer
462
- add_action( 'admin_footer', array( $this, 'output_script' ), 99 );
463
- }
464
-
465
- /**
466
- * Check if the license form has been submitted
467
- */
468
- public function catch_post_request() {
469
-
470
- $name = $this->prefix . 'license_key';
471
-
472
- // check if license key was posted and not empty
473
- if ( ! isset( $_POST[$name] ) ) {
474
- return;
475
- }
476
-
477
- // run a quick security check
478
- $nonce_name = $this->prefix . 'license_nonce';
479
-
480
- if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) {
481
- return;
482
- }
483
-
484
- // @TODO: check for user cap?
485
-
486
- // get key from posted value
487
- $license_key = $_POST[$name];
488
-
489
- // check if license key doesn't accidentally contain asterisks
490
- if ( strstr( $license_key, '*' ) === false ) {
491
-
492
- // sanitize key
493
- $license_key = trim( sanitize_key( $_POST[$name] ) );
494
-
495
- // save license key
496
- $this->set_license_key( $license_key );
497
- }
498
-
499
- // does user have an activated valid license
500
- if ( ! $this->license_is_valid() ) {
501
-
502
- // try to auto-activate license
503
- return $this->activate_license();
504
-
505
- }
506
-
507
- $action_name = $this->prefix . 'license_action';
508
-
509
- // was one of the action buttons clicked?
510
- if ( isset( $_POST[$action_name] ) ) {
511
-
512
- $action = trim( $_POST[$action_name] );
513
-
514
- switch ( $action ) {
515
-
516
- case 'activate':
517
- return $this->activate_license();
518
- break;
519
-
520
- case 'deactivate':
521
- return $this->deactivate_license();
522
- break;
523
- }
524
-
525
- }
526
-
527
- }
528
-
529
- /**
530
- * Output the script containing the YoastLicenseManager JS Object
531
- *
532
- * This takes care of disabling the 'activate' and 'deactivate' buttons
533
- */
534
- public function output_script() {
535
- require_once dirname( __FILE__ ) . '/views/script.php';
536
- }
537
-
538
- /**
539
- * Set the constant used to define the license
540
- *
541
- * @param string $license_constant_name The license constant name
542
- */
543
- public function set_license_constant_name( $license_constant_name ) {
544
- $this->license_constant_name = trim( $license_constant_name );
545
- $this->maybe_set_license_key_from_constant();
546
- }
547
-
548
- /**
549
- * Get the API availability information
550
- *
551
- * @return array
552
- */
553
- protected function get_api_availability(){
554
- return array(
555
- 'url' => $this->product->get_api_url(),
556
- 'availability' => $this->check_api_host_availability(),
557
- 'curl_version' => $this->get_curl_version(),
558
- );
559
- }
560
-
561
- /**
562
- * Check if the API host address is available from this server
563
- *
564
- * @return bool
565
- */
566
- private function check_api_host_availability() {
567
- $wp_http = new WP_Http();
568
- if ( $wp_http->block_request( $this->product->get_api_url() ) === false ) {
569
- return true;
570
- }
571
-
572
- return false;
573
- }
574
-
575
- /**
576
- * Get the current curl version, or false
577
- *
578
- * @return mixed
579
- */
580
- protected function get_curl_version() {
581
- if ( function_exists( 'curl_version' ) ) {
582
- $curl_version = curl_version();
583
-
584
- if ( isset( $curl_version['version'] ) ) {
585
- return $curl_version['version'];
586
- }
587
- }
588
-
589
- return false;
590
- }
591
-
592
- /**
593
- * Maybe set license key from a defined constant
594
- */
595
- private function maybe_set_license_key_from_constant() {
596
-
597
- if ( empty( $this->license_constant_name ) ) {
598
- // generate license constant name
599
- $this->set_license_constant_name( strtoupper( str_replace( array( ' ', '-' ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE' );
600
- }
601
-
602
- // set license key from constant
603
- if ( defined( $this->license_constant_name ) ) {
604
-
605
- $license_constant_value = constant( $this->license_constant_name );
606
-
607
- // update license key value with value of constant
608
- if ( $this->get_license_key() !== $license_constant_value ) {
609
- $this->set_license_key( $license_constant_value );
610
- }
611
-
612
- $this->license_constant_is_defined = true;
613
- }
614
- }
615
-
616
-
617
- }
618
-
619
- }
1
+ <?php
2
+
3
+ if ( ! interface_exists( 'iYoast_License_Manager', false ) ) {
4
+
5
+ interface iYoast_License_Manager {
6
+ public function specific_hooks();
7
+ public function setup_auto_updater();
8
+ }
9
+
10
+ }
11
+
12
+ if ( ! class_exists( 'Yoast_License_Manager', false ) ) {
13
+
14
+ /**
15
+ * Class Yoast_License_Manager
16
+ *
17
+ * @todo Maybe create a license class that contains key and option
18
+ * @todo Not sure if Yoast_License_Manager is a good name for this class, it's more managing the product (plugin or theme)
19
+ */
20
+ abstract class Yoast_License_Manager implements iYoast_License_Manager {
21
+
22
+ /**
23
+ * @const VERSION The version number of the License_Manager class
24
+ */
25
+ const VERSION = 1;
26
+
27
+ /**
28
+ * @var Yoast_License The license
29
+ */
30
+ protected $product;
31
+
32
+ /**
33
+ * @var string
34
+ */
35
+ private $license_constant_name = '';
36
+
37
+ /**
38
+ * @var boolean True if license is defined with a constant
39
+ */
40
+ private $license_constant_is_defined = false;
41
+
42
+ /**
43
+ * @var boolean True if remote license activation just failed
44
+ */
45
+ private $remote_license_activation_failed = false;
46
+
47
+ /**
48
+ * @var array Array of license related options
49
+ */
50
+ private $options = array();
51
+
52
+ /**
53
+ * @var string Used to prefix ID's, option names, etc..
54
+ */
55
+ protected $prefix;
56
+
57
+ /**
58
+ * @var bool Boolean indicating whether this plugin is network activated
59
+ */
60
+ protected $is_network_activated = false;
61
+
62
+ /**
63
+ * Constructor
64
+ *
65
+ * @param Yoast_Product $product
66
+ */
67
+ public function __construct( Yoast_Product $product ) {
68
+
69
+ // Set the license
70
+ $this->product = $product;
71
+
72
+ // set prefix
73
+ $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' );
74
+
75
+ // maybe set license key from constant
76
+ $this->maybe_set_license_key_from_constant();
77
+ }
78
+
79
+ /**
80
+ * Setup hooks
81
+ *
82
+ */
83
+ public function setup_hooks() {
84
+
85
+ // show admin notice if license is not active
86
+ add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
87
+
88
+ // catch POST requests from license form
89
+ add_action( 'admin_init', array( $this, 'catch_post_request' ) );
90
+
91
+ // setup item type (plugin|theme) specific hooks
92
+ $this->specific_hooks();
93
+
94
+ // setup the auto updater
95
+ $this->setup_auto_updater();
96
+
97
+ }
98
+
99
+ /**
100
+ * Display license specific admin notices, namely:
101
+ *
102
+ * - License for the product isn't activated
103
+ * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL
104
+ */
105
+ public function display_admin_notices() {
106
+
107
+ if ( ! current_user_can( 'manage_options' ) ) {
108
+ return;
109
+ }
110
+
111
+ // show notice if license is invalid
112
+ if ( ! $this->license_is_valid() ) {
113
+ if ( $this->get_license_key() == '' ) {
114
+ $message = '<b>Warning!</b> You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! <a href="%s">Enter your license key</a> or <a href="%s" target="_blank">get a license here</a>.';
115
+ } else {
116
+ $message = '<b>Warning!</b> Your %s license is inactive which means you\'re missing out on updates and support! <a href="%s">Activate your license</a> or <a href="%s" target="_blank">get a license here</a>.';
117
+ }
118
+ ?>
119
+ <div class="error">
120
+ <p><?php printf( __( $message, $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?></p>
121
+ </div>
122
+ <?php
123
+ }
124
+
125
+ // show notice if external requests are blocked through the WP_HTTP_BLOCK_EXTERNAL constant
126
+ if ( defined( "WP_HTTP_BLOCK_EXTERNAL" ) && WP_HTTP_BLOCK_EXTERNAL === true ) {
127
+
128
+ // check if our API endpoint is in the allowed hosts
129
+ $host = parse_url( $this->product->get_api_url(), PHP_URL_HOST );
130
+
131
+ if ( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) {
132
+ ?>
133
+ <div class="error">
134
+ <p><?php printf( __( '<b>Warning!</b> You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '<strong>' . $host . '</strong>', '<code>WP_ACCESSIBLE_HOSTS</code>' ); ?></p>
135
+ </div>
136
+ <?php
137
+ }
138
+
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Set a notice to display in the admin area
144
+ *
145
+ * @param string $type error|updated
146
+ * @param string $message The message to display
147
+ */
148
+ protected function set_notice( $message, $success = true ) {
149
+ $css_class = ( $success ) ? 'updated' : 'error';
150
+ add_settings_error( $this->prefix . 'license', 'license-notice', $message, $css_class );
151
+ }
152
+
153
+ /**
154
+ * Remotely activate License
155
+ * @return boolean True if the license is now activated, false if not
156
+ */
157
+ public function activate_license() {
158
+
159
+ $result = $this->call_license_api( 'activate' );
160
+
161
+
162
+ if ( $result ) {
163
+
164
+ // story expiry date
165
+ if ( isset( $result->expires ) ) {
166
+ $this->set_license_expiry_date( $result->expires );
167
+ $expiry_date = strtotime( $result->expires );
168
+ } else {
169
+ $expiry_date = false;
170
+ }
171
+
172
+ // show success notice if license is valid
173
+ if ( $result->license === 'valid' ) {
174
+
175
+ $message = sprintf( __( "Your %s license has been activated. ", $this->product->get_text_domain() ), $this->product->get_item_name() );
176
+
177
+ // show a custom notice if users have an unlimited license
178
+ if ( $result->license_limit == 0 ) {
179
+ $message .= __( "You have an unlimited license. ", $this->product->get_text_domain() );
180
+ } else {
181
+ $message .= sprintf( __( "You have used %d/%d activations. ", $this->product->get_text_domain() ), $result->site_count, $result->license_limit );
182
+ }
183
+
184
+ // add upgrade notice if user has less than 3 activations left
185
+ if ( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) {
186
+ $message .= sprintf( __( '<a href="%s">Did you know you can upgrade your license?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-nearing-limit-notice' ) );
187
+ // add extend notice if license is expiring in less than 1 month
188
+ } elseif ( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) {
189
+ $days_left = round( ( $expiry_date - strtotime( "now" ) ) / 86400 );
190
+ $message .= sprintf( __( '<a href="%s">Your license is expiring in %d days, would you like to extend it?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expiring-notice' ), $days_left );
191
+ }
192
+
193
+ $this->set_notice( $message, true );
194
+
195
+ } else {
196
+
197
+ if ( isset( $result->error ) && $result->error === 'no_activations_left' ) {
198
+ // show notice if user is at their activation limit
199
+ $this->set_notice( sprintf( __( 'You\'ve reached your activation limit. You must <a href="%s">upgrade your license</a> to use it on this site.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-at-limit-notice' ) ), false );
200
+ } elseif ( isset( $result->error ) && $result->error == "expired" ) {
201
+ // show notice if the license is expired
202
+ $this->set_notice( sprintf( __( 'Your license has expired. You must <a href="%s">extend your license</a> in order to use it again.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expired-notice' ) ), false );
203
+ } else {
204
+ // show a general notice if it's any other error
205
+ $this->set_notice( __( "Failed to activate your license, your license key seems to be invalid.", $this->product->get_text_domain() ), false );
206
+ }
207
+
208
+ $this->remote_license_activation_failed = true;
209
+ }
210
+
211
+ $this->set_license_status( $result->license );
212
+ }
213
+
214
+ return ( $this->license_is_valid() );
215
+ }
216
+
217
+ /**
218
+ * Remotely deactivate License
219
+ * @return boolean True if the license is now deactivated, false if not
220
+ */
221
+ public function deactivate_license() {
222
+
223
+ $result = $this->call_license_api( 'deactivate' );
224
+
225
+ if ( $result ) {
226
+
227
+ // show notice if license is deactivated
228
+ if ( $result->license === 'deactivated' ) {
229
+ $this->set_notice( sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ) );
230
+ } else {
231
+ $this->set_notice( sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ), false );
232
+ }
233
+
234
+ $this->set_license_status( $result->license );
235
+ }
236
+
237
+ return ( $this->get_license_status() === 'deactivated' );
238
+ }
239
+
240
+ /**
241
+ * @param string $action activate|deactivate
242
+ *
243
+ * @return mixed
244
+ */
245
+ protected function call_license_api( $action ) {
246
+
247
+ // don't make a request if license key is empty
248
+ if ( $this->get_license_key() === '' ) {
249
+ return false;
250
+ }
251
+
252
+ // data to send in our API request
253
+ $api_params = array(
254
+ 'edd_action' => $action . '_license',
255
+ 'license' => $this->get_license_key(),
256
+ 'item_name' => urlencode( trim( $this->product->get_item_name() ) ),
257
+ 'url' => get_option( 'home' ) // grab the URL straight from the option to prevent filters from breaking it.
258
+ );
259
+
260
+ // create api request url
261
+ $url = add_query_arg( $api_params, $this->product->get_api_url() );
262
+
263
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
264
+ $request = new Yoast_API_Request( $url );
265
+
266
+ if ( $request->is_valid() !== true ) {
267
+ $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '<a href="http://kb.yoast.com/article/13-license-activation-notices">', '</a>' ), false );
268
+ }
269
+
270
+ // get response
271
+ $response = $request->get_response();
272
+
273
+ // update license status
274
+ $license_data = $response;
275
+
276
+ return $license_data;
277
+ }
278
+
279
+
280
+ /**
281
+ * Set the license status
282
+ *
283
+ * @param string $license_status
284
+ */
285
+ public function set_license_status( $license_status ) {
286
+ $this->set_option( 'status', $license_status );
287
+ }
288
+
289
+ /**
290
+ * Get the license status
291
+ *
292
+ * @return string $license_status;
293
+ */
294
+ public function get_license_status() {
295
+ $license_status = $this->get_option( 'status' );
296
+
297
+ return trim( $license_status );
298
+ }
299
+
300
+ /**
301
+ * Set the license key
302
+ *
303
+ * @param string $license_key
304
+ */
305
+ public function set_license_key( $license_key ) {
306
+ $this->set_option( 'key', $license_key );
307
+ }
308
+
309
+ /**
310
+ * Gets the license key from constant or option
311
+ *
312
+ * @return string $license_key
313
+ */
314
+ public function get_license_key() {
315
+ $license_key = $this->get_option( 'key' );
316
+
317
+ return trim( $license_key );
318
+ }
319
+
320
+ /**
321
+ * Gets the license expiry date
322
+ *
323
+ * @return string
324
+ */
325
+ public function get_license_expiry_date() {
326
+ return $this->get_option( 'expiry_date' );
327
+ }
328
+
329
+ /**
330
+ * Stores the license expiry date
331
+ */
332
+ public function set_license_expiry_date( $expiry_date ) {
333
+ $this->set_option( 'expiry_date', $expiry_date );
334
+ }
335
+
336
+ /**
337
+ * Checks whether the license status is active
338
+ *
339
+ * @return boolean True if license is active
340
+ */
341
+ public function license_is_valid() {
342
+ return ( $this->get_license_status() === 'valid' );
343
+ }
344
+
345
+ /**
346
+ * Get all license related options
347
+ *
348
+ * @return array Array of license options
349
+ */
350
+ protected function get_options() {
351
+
352
+ // create option name
353
+ $option_name = $this->prefix . 'license';
354
+
355
+ // get array of options from db
356
+ if ( $this->is_network_activated ) {
357
+ $options = get_site_option( $option_name, array() );
358
+ } else {
359
+ $options = get_option( $option_name, array() );
360
+ }
361
+
362
+ // setup array of defaults
363
+ $defaults = array(
364
+ 'key' => '',
365
+ 'status' => '',
366
+ 'expiry_date' => ''
367
+ );
368
+
369
+ // merge options with defaults
370
+ $this->options = wp_parse_args( $options, $defaults );
371
+
372
+ return $this->options;
373
+ }
374
+
375
+ /**
376
+ * Set license related options
377
+ *
378
+ * @param array $options Array of new license options
379
+ */
380
+ protected function set_options( array $options ) {
381
+ // create option name
382
+ $option_name = $this->prefix . 'license';
383
+
384
+ // update db
385
+ if ( $this->is_network_activated ) {
386
+ update_site_option( $option_name, $options );
387
+ } else {
388
+ update_option( $option_name, $options );
389
+ }
390
+
391
+ }
392
+
393
+ /**
394
+ * Gets a license related option
395
+ *
396
+ * @param string $name The option name
397
+ *
398
+ * @return mixed The option value
399
+ */
400
+ protected function get_option( $name ) {
401
+ $options = $this->get_options();
402
+
403
+ return $options[$name];
404
+ }
405
+
406
+ /**
407
+ * Set a license related option
408
+ *
409
+ * @param string $name The option name
410
+ * @param mixed $value The option value
411
+ */
412
+ protected function set_option( $name, $value ) {
413
+ // get options
414
+ $options = $this->get_options();
415
+
416
+ // update option
417
+ $options[$name] = $value;
418
+
419
+ // save options
420
+ $this->set_options( $options );
421
+ }
422
+
423
+ public function show_license_form_heading() {
424
+ ?>
425
+ <h3>
426
+ <?php printf( __( "%s: License Settings", $this->product->get_text_domain() ), $this->product->get_item_name() ); ?>&nbsp; &nbsp;
427
+ </h3>
428
+ <?php
429
+ }
430
+
431
+ /**
432
+ * Show a form where users can enter their license key
433
+ *
434
+ * @param boolean $embedded Boolean indicating whether this form is embedded in another form?
435
+ */
436
+ public function show_license_form( $embedded = true ) {
437
+ $key_name = $this->prefix . 'license_key';
438
+ $nonce_name = $this->prefix . 'license_nonce';
439
+ $action_name = $this->prefix . 'license_action';
440
+
441
+ $api_host_available = $this->get_api_availability();
442
+
443
+ $visible_license_key = $this->get_license_key();
444
+
445
+ // obfuscate license key
446
+ $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) );
447
+
448
+ if ( $obfuscate ) {
449
+ $visible_license_key = str_repeat( '*', strlen( $this->get_license_key() ) - 4 ) . substr( $this->get_license_key(), - 4 );
450
+ }
451
+
452
+ // make license key readonly when license key is valid or license is defined with a constant
453
+ $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined );
454
+
455
+ require dirname( __FILE__ ) . '/views/form.php';
456
+
457
+ // enqueue script in the footer
458
+ add_action( 'admin_footer', array( $this, 'output_script' ), 99 );
459
+ }
460
+
461
+ /**
462
+ * Check if the license form has been submitted
463
+ */
464
+ public function catch_post_request() {
465
+
466
+ $name = $this->prefix . 'license_key';
467
+
468
+ // check if license key was posted and not empty
469
+ if ( ! isset( $_POST[$name] ) ) {
470
+ return;
471
+ }
472
+
473
+ // run a quick security check
474
+ $nonce_name = $this->prefix . 'license_nonce';
475
+
476
+ if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) {
477
+ return;
478
+ }
479
+
480
+ // @TODO: check for user cap?
481
+
482
+ // get key from posted value
483
+ $license_key = $_POST[$name];
484
+
485
+ // check if license key doesn't accidentally contain asterisks
486
+ if ( strstr( $license_key, '*' ) === false ) {
487
+
488
+ // sanitize key
489
+ $license_key = trim( sanitize_key( $_POST[$name] ) );
490
+
491
+ // save license key
492
+ $this->set_license_key( $license_key );
493
+ }
494
+
495
+ // does user have an activated valid license
496
+ if ( ! $this->license_is_valid() ) {
497
+
498
+ // try to auto-activate license
499
+ return $this->activate_license();
500
+
501
+ }
502
+
503
+ $action_name = $this->prefix . 'license_action';
504
+
505
+ // was one of the action buttons clicked?
506
+ if ( isset( $_POST[$action_name] ) ) {
507
+
508
+ $action = trim( $_POST[$action_name] );
509
+
510
+ switch ( $action ) {
511
+
512
+ case 'activate':
513
+ return $this->activate_license();
514
+ break;
515
+
516
+ case 'deactivate':
517
+ return $this->deactivate_license();
518
+ break;
519
+ }
520
+
521
+ }
522
+
523
+ }
524
+
525
+ /**
526
+ * Output the script containing the YoastLicenseManager JS Object
527
+ *
528
+ * This takes care of disabling the 'activate' and 'deactivate' buttons
529
+ */
530
+ public function output_script() {
531
+ require_once dirname( __FILE__ ) . '/views/script.php';
532
+ }
533
+
534
+ /**
535
+ * Set the constant used to define the license
536
+ *
537
+ * @param string $license_constant_name The license constant name
538
+ */
539
+ public function set_license_constant_name( $license_constant_name ) {
540
+ $this->license_constant_name = trim( $license_constant_name );
541
+ $this->maybe_set_license_key_from_constant();
542
+ }
543
+
544
+ /**
545
+ * Get the API availability information
546
+ *
547
+ * @return array
548
+ */
549
+ protected function get_api_availability(){
550
+ return array(
551
+ 'url' => $this->product->get_api_url(),
552
+ 'availability' => $this->check_api_host_availability(),
553
+ 'curl_version' => $this->get_curl_version(),
554
+ );
555
+ }
556
+
557
+ /**
558
+ * Check if the API host address is available from this server
559
+ *
560
+ * @return bool
561
+ */
562
+ private function check_api_host_availability() {
563
+ $wp_http = new WP_Http();
564
+ if ( $wp_http->block_request( $this->product->get_api_url() ) === false ) {
565
+ return true;
566
+ }
567
+
568
+ return false;
569
+ }
570
+
571
+ /**
572
+ * Get the current curl version, or false
573
+ *
574
+ * @return mixed
575
+ */
576
+ protected function get_curl_version() {
577
+ if ( function_exists( 'curl_version' ) ) {
578
+ $curl_version = curl_version();
579
+
580
+ if ( isset( $curl_version['version'] ) ) {
581
+ return $curl_version['version'];
582
+ }
583
+ }
584
+
585
+ return false;
586
+ }
587
+
588
+ /**
589
+ * Maybe set license key from a defined constant
590
+ */
591
+ private function maybe_set_license_key_from_constant() {
592
+
593
+ if ( empty( $this->license_constant_name ) ) {
594
+ // generate license constant name
595
+ $this->set_license_constant_name( strtoupper( str_replace( array( ' ', '-' ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE' );
596
+ }
597
+
598
+ // set license key from constant
599
+ if ( defined( $this->license_constant_name ) ) {
600
+
601
+ $license_constant_value = constant( $this->license_constant_name );
602
+
603
+ // update license key value with value of constant
604
+ if ( $this->get_license_key() !== $license_constant_value ) {
605
+ $this->set_license_key( $license_constant_value );
606
+ }
607
+
608
+ $this->license_constant_is_defined = true;
609
+ }
610
+ }
611
+ }
612
+
613
+ }
 
 
 
 
 
 
vendor/yoast/license-manager-2/class-plugin-license-manager.php CHANGED
@@ -1,90 +1,90 @@
1
- <?php
2
-
3
- if ( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Plugin_License_Manager", false ) ) {
4
-
5
- class Yoast_Plugin_License_Manager extends Yoast_License_Manager {
6
-
7
- /**
8
- * Constructor
9
- *
10
- * @param Yoast_Product $product
11
- */
12
- public function __construct( Yoast_Product $product ) {
13
-
14
- parent::__construct( $product );
15
-
16
- // Check if plugin is network activated. We should use site(wide) options in that case.
17
- if( is_admin() && is_multisite() ) {
18
-
19
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
20
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
21
- }
22
-
23
- $this->is_network_activated = is_plugin_active_for_network( $product->get_slug() );
24
- }
25
- }
26
-
27
- /**
28
- * Setup auto updater for plugins
29
- */
30
- public function setup_auto_updater() {
31
- if ( $this->license_is_valid() ) {
32
- // setup auto updater
33
- require_once( dirname( __FILE__ ) . '/class-update-manager.php' );
34
- require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' );
35
- new Yoast_Plugin_Update_Manager( $this->product, $this );
36
- }
37
- }
38
-
39
- /**
40
- * Setup hooks
41
- */
42
- public function specific_hooks() {
43
-
44
- // deactivate the license remotely on plugin deactivation
45
- register_deactivation_hook( $this->product->get_slug(), array( $this, 'deactivate_license' ) );
46
- }
47
-
48
- /**
49
- * Show a form where users can enter their license key
50
- * Takes Multisites into account
51
- *
52
- * @param bool $embedded
53
- * @return null
54
- */
55
- public function show_license_form( $embedded = true ) {
56
-
57
- // For non-multisites, always show the license form
58
- if( ! is_multisite() ) {
59
- parent::show_license_form( $embedded );
60
- return;
61
- }
62
-
63
- // Plugin is network activated
64
- if( $this->is_network_activated ) {
65
-
66
- // We're on the network admin
67
- if( is_network_admin() ) {
68
- parent::show_license_form( $embedded );
69
- } else {
70
- // We're not in the network admin area, show a notice
71
- parent::show_license_form_heading();
72
- if ( is_super_admin() ) {
73
- echo "<p>" . sprintf( __( '%s is network activated, you can manage your license in the <a href="%s">network admin license page</a>.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "</p>";
74
- } else {
75
- echo "<p>" . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "</p>";
76
- }
77
-
78
- }
79
-
80
- } else {
81
-
82
- if( false == is_network_admin() ) {
83
- parent::show_license_form( $embedded );
84
- }
85
-
86
- }
87
- }
88
- }
89
- }
90
-
1
+ <?php
2
+
3
+ if ( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Plugin_License_Manager", false ) ) {
4
+
5
+ class Yoast_Plugin_License_Manager extends Yoast_License_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param Yoast_Product $product
11
+ */
12
+ public function __construct( Yoast_Product $product ) {
13
+
14
+ parent::__construct( $product );
15
+
16
+ // Check if plugin is network activated. We should use site(wide) options in that case.
17
+ if( is_admin() && is_multisite() ) {
18
+
19
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
20
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
21
+ }
22
+
23
+ $this->is_network_activated = is_plugin_active_for_network( $product->get_file() );
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Setup auto updater for plugins
29
+ */
30
+ public function setup_auto_updater() {
31
+ if ( $this->license_is_valid() ) {
32
+ // setup auto updater
33
+ require_once( dirname( __FILE__ ) . '/class-update-manager.php' );
34
+ require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' );
35
+ new Yoast_Plugin_Update_Manager( $this->product, $this );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Setup hooks
41
+ */
42
+ public function specific_hooks() {
43
+
44
+ // deactivate the license remotely on plugin deactivation
45
+ register_deactivation_hook( $this->product->get_file(), array( $this, 'deactivate_license' ) );
46
+ }
47
+
48
+ /**
49
+ * Show a form where users can enter their license key
50
+ * Takes Multisites into account
51
+ *
52
+ * @param bool $embedded
53
+ * @return null
54
+ */
55
+ public function show_license_form( $embedded = true ) {
56
+
57
+ // For non-multisites, always show the license form
58
+ if( ! is_multisite() ) {
59
+ parent::show_license_form( $embedded );
60
+ return;
61
+ }
62
+
63
+ // Plugin is network activated
64
+ if( $this->is_network_activated ) {
65
+
66
+ // We're on the network admin
67
+ if( is_network_admin() ) {
68
+ parent::show_license_form( $embedded );
69
+ } else {
70
+ // We're not in the network admin area, show a notice
71
+ parent::show_license_form_heading();
72
+ if ( is_super_admin() ) {
73
+ echo "<p>" . sprintf( __( '%s is network activated, you can manage your license in the <a href="%s">network admin license page</a>.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "</p>";
74
+ } else {
75
+ echo "<p>" . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "</p>";
76
+ }
77
+
78
+ }
79
+
80
+ } else {
81
+
82
+ if( false == is_network_admin() ) {
83
+ parent::show_license_form( $embedded );
84
+ }
85
+
86
+ }
87
+ }
88
+ }
89
+
90
+ }
vendor/yoast/license-manager-2/class-plugin-update-manager.php CHANGED
@@ -1,102 +1,93 @@
1
- <?php
2
-
3
- //set_site_transient( 'update_plugins', null );
4
-
5
- if( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( "Yoast_Plugin_Update_Manager", false ) ) {
6
-
7
- class Yoast_Plugin_Update_Manager extends Yoast_Update_Manager {
8
-
9
- /**
10
- * Constructor
11
- *
12
- * @param string $api_url
13
- * @param string $item_name
14
- * @param string $license_key
15
- * @param string $slug The path to the main plugin file, relative to plugins dir
16
- * @param string $version
17
- * @param string $author (optional)
18
- * @param string $text_domain
19
- */
20
- public function __construct( Yoast_Product $product, $license_key ) {
21
- parent::__construct( $product, $license_key );
22
-
23
- // setup hooks
24
- $this->setup_hooks();
25
-
26
- }
27
-
28
- /**
29
- * Setup hooks
30
- */
31
- private function setup_hooks() {
32
-
33
- // check for updates
34
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) );
35
-
36
- // get correct plugin information (when viewing details)
37
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
38
- }
39
-
40
- /**
41
- * Check for updates and if so, add to "updates available" data
42
- *
43
- * @param object $data
44
- * @return object $data
45
- */
46
- public function set_updates_available_data( $data ) {
47
-
48
- if ( empty( $data ) ) {
49
- return $data;
50
- }
51
-
52
- // send of API request to check for updates
53
- $remote_data = $this->get_remote_data();
54
-
55
- // did we get a response?
56
- if( $remote_data === false ) {
57
- return $data;
58
- }
59
-
60
- // compare local version with remote version
61
- if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) {
62
-
63
- // remote version is newer, add to data
64
- $data->response[ $this->product->get_slug() ] = $remote_data;
65
-
66
- }
67
-
68
- return $data;
69
- }
70
-
71
- /**
72
- * Gets new plugin version details (view version x.x.x details)
73
- *
74
- * @uses api_request()
75
- *
76
- * @param object $data
77
- * @param string $action
78
- * @param object $args (optional)
79
- *
80
- * @return object $data
81
- */
82
- public function plugins_api_filter( $data, $action = '', $args = null ) {
83
-
84
- // only do something if we're checking for our plugin
85
- if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) {
86
- return $data;
87
- }
88
-
89
- $api_response = $this->get_remote_data();
90
-
91
- // did we get a response?
92
- if ( $api_response === false ) {
93
- return $data;
94
- }
95
-
96
- // return api response
97
- return $api_response;
98
- }
99
-
100
- }
101
-
102
- }
1
+ <?php
2
+
3
+ if( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( "Yoast_Plugin_Update_Manager", false ) ) {
4
+
5
+ class Yoast_Plugin_Update_Manager extends Yoast_Update_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param Yoast_Product $product The Product.
11
+ * @param string $license_key The License entered.
12
+ */
13
+ public function __construct( Yoast_Product $product, $license_key ) {
14
+ parent::__construct( $product, $license_key );
15
+
16
+ // setup hooks
17
+ $this->setup_hooks();
18
+ }
19
+
20
+ /**
21
+ * Setup hooks
22
+ */
23
+ private function setup_hooks() {
24
+
25
+ // check for updates
26
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) );
27
+
28
+ // get correct plugin information (when viewing details)
29
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
30
+ }
31
+
32
+ /**
33
+ * Check for updates and if so, add to "updates available" data
34
+ *
35
+ * @param object $data
36
+ * @return object $data
37
+ */
38
+ public function set_updates_available_data( $data ) {
39
+
40
+ if ( empty( $data ) ) {
41
+ return $data;
42
+ }
43
+
44
+ // send of API request to check for updates
45
+ $remote_data = $this->get_remote_data();
46
+
47
+ // did we get a response?
48
+ if( $remote_data === false ) {
49
+ return $data;
50
+ }
51
+
52
+ // compare local version with remote version
53
+ if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) {
54
+
55
+ // remote version is newer, add to data
56
+ $data->response[ $this->product->get_file() ] = $remote_data;
57
+
58
+ }
59
+
60
+ return $data;
61
+ }
62
+
63
+ /**
64
+ * Gets new plugin version details (view version x.x.x details)
65
+ *
66
+ * @uses api_request()
67
+ *
68
+ * @param object $data
69
+ * @param string $action
70
+ * @param object $args (optional)
71
+ *
72
+ * @return object $data
73
+ */
74
+ public function plugins_api_filter( $data, $action = '', $args = null ) {
75
+
76
+ // only do something if we're checking for our plugin
77
+ if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) {
78
+ return $data;
79
+ }
80
+
81
+ $api_response = $this->get_remote_data();
82
+
83
+ // did we get a response?
84
+ if ( $api_response === false ) {
85
+ return $data;
86
+ }
87
+
88
+ // return api response
89
+ return $api_response;
90
+ }
91
+ }
92
+
93
+ }
 
 
 
 
 
 
 
 
 
vendor/yoast/license-manager-2/class-product.php CHANGED
@@ -1,228 +1,292 @@
1
- <?php
2
-
3
- if( ! class_exists( "Yoast_Product", false ) ) {
4
-
5
- /**
6
- * Class Yoast_Product
7
- *
8
- * @todo create a license class and store an object of it in this class
9
- */
10
- class Yoast_Product {
11
-
12
- /**
13
- * @var string The URL of the shop running the EDD API.
14
- */
15
- protected $api_url;
16
-
17
- /**
18
- * @var string The item name in the EDD shop.
19
- */
20
- protected $item_name;
21
-
22
- /**
23
- * @var string The theme slug or plugin file
24
- */
25
- protected $slug;
26
-
27
- /**
28
- * @var string The version number of the item
29
- */
30
- protected $version;
31
-
32
- /**
33
- * @var string The absolute url on which users can purchase a license
34
- */
35
- protected $item_url;
36
-
37
- /**
38
- * @var string Absolute admin URL on which users can enter their license key.
39
- */
40
- protected $license_page_url;
41
-
42
- /**
43
- * @var string The text domain used for translating strings
44
- */
45
- protected $text_domain;
46
-
47
- /**
48
- * @var string The item author
49
- */
50
- protected $author;
51
-
52
- public function __construct( $api_url, $item_name, $slug, $version, $item_url = '', $license_page_url = '#', $text_domain = 'yoast', $author = 'Yoast' ) {
53
- $this->api_url = $api_url;
54
- $this->item_name = $item_name;
55
- $this->slug = $slug;
56
- $this->version = $version;
57
- $this->item_url = $item_url;
58
- $this->license_page_url = admin_url( $license_page_url );
59
- $this->text_domain = $text_domain;
60
- $this->author = $author;
61
-
62
- // Fix possible empty item url
63
- if ( $this->item_url === '' ) {
64
- $this->item_url = $this->api_url;
65
- }
66
-
67
- if( is_admin() && is_multisite() ) {
68
-
69
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
70
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
71
- }
72
-
73
- if( is_plugin_active_for_network( $slug ) ) {
74
- $this->license_page_url = network_admin_url( $license_page_url );
75
- }
76
- }
77
- }
78
-
79
-
80
- /**
81
- * @param string $api_url
82
- */
83
- public function set_api_url( $api_url ) {
84
- $this->api_url = $api_url;
85
- }
86
-
87
- /**
88
- * @return string
89
- */
90
- public function get_api_url() {
91
- return $this->api_url;
92
- }
93
-
94
- /**
95
- * @param string $author
96
- */
97
- public function set_author( $author ) {
98
- $this->author = $author;
99
- }
100
-
101
- /**
102
- * @return string
103
- */
104
- public function get_author() {
105
- return $this->author;
106
- }
107
-
108
- /**
109
- * @param string $item_name
110
- */
111
- public function set_item_name( $item_name ) {
112
- $this->item_name = $item_name;
113
- }
114
-
115
- /**
116
- * @return string
117
- */
118
- public function get_item_name() {
119
- return $this->item_name;
120
- }
121
-
122
- /**
123
- * @param string $item_url
124
- */
125
- public function set_item_url( $item_url ) {
126
- $this->item_url = $item_url;
127
- }
128
-
129
- /**
130
- * @return string
131
- */
132
- public function get_item_url() {
133
- return $this->item_url;
134
- }
135
-
136
- /**
137
- * @param string $license_page_url
138
- */
139
- public function set_license_page_url( $license_page_url ) {
140
- $this->license_page_url = admin_page( $license_page_url );
141
- }
142
-
143
- /**
144
- * @return string
145
- */
146
- public function get_license_page_url() {
147
- return $this->license_page_url;
148
- }
149
-
150
- /**
151
- * @param string $slug
152
- */
153
- public function set_slug( $slug ) {
154
- $this->slug = $slug;
155
- }
156
-
157
- /**
158
- * @return string
159
- */
160
- public function get_slug() {
161
- return $this->slug;
162
- }
163
-
164
- /**
165
- * Returns the dirname of the slug and limits it to 15 chars
166
- *
167
- * @return string
168
- */
169
- public function get_transient_prefix() {
170
- return substr( dirname( $this->slug ), 0, 15 );
171
- }
172
-
173
- /**
174
- * @param string $text_domain
175
- */
176
- public function set_text_domain( $text_domain ) {
177
- $this->text_domain = $text_domain;
178
- }
179
-
180
- /**
181
- * @return string
182
- */
183
- public function get_text_domain() {
184
- return $this->text_domain;
185
- }
186
-
187
- /**
188
- * @param string $version
189
- */
190
- public function set_version( $version ) {
191
- $this->version = $version;
192
- }
193
-
194
- /**
195
- * @return string
196
- */
197
- public function get_version() {
198
- return $this->version;
199
- }
200
-
201
- /**
202
- * Gets a Google Analytics Campaign url for this product
203
- *
204
- * @param string $link_identifier
205
- * @return string The full URL
206
- */
207
- public function get_tracking_url( $link_identifier = '' ) {
208
-
209
- $tracking_vars = array(
210
- 'utm_campaign' => $this->get_item_name() . ' licensing',
211
- 'utm_medium' => 'link',
212
- 'utm_source' => $this->get_item_name(),
213
- 'utm_content' => $link_identifier
214
- );
215
-
216
- // url encode tracking vars
217
- $tracking_vars = urlencode_deep( $tracking_vars );
218
-
219
- $query_string = build_query( $tracking_vars );
220
-
221
-
222
- return $this->get_item_url() . '#' . $query_string;
223
- }
224
-
225
- }
226
-
227
- }
228
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( "Yoast_Product", false ) ) {
4
+
5
+ /**
6
+ * Class Yoast_Product
7
+ *
8
+ * @todo create a license class and store an object of it in this class
9
+ */
10
+ class Yoast_Product {
11
+
12
+ /**
13
+ * @var string The URL of the shop running the EDD API.
14
+ */
15
+ protected $api_url;
16
+
17
+ /**
18
+ * @var string The item name in the EDD shop.
19
+ */
20
+ protected $item_name;
21
+
22
+ /**
23
+ * @var string The theme slug or plugin file
24
+ */
25
+ protected $slug;
26
+
27
+ /**
28
+ * @var string The version number of the item
29
+ */
30
+ protected $version;
31
+
32
+ /**
33
+ * @var string The absolute url on which users can purchase a license
34
+ */
35
+ protected $item_url;
36
+
37
+ /**
38
+ * @var string Absolute admin URL on which users can enter their license key.
39
+ */
40
+ protected $license_page_url;
41
+
42
+ /**
43
+ * @var string The text domain used for translating strings
44
+ */
45
+ protected $text_domain;
46
+
47
+ /**
48
+ * @var string The item author
49
+ */
50
+ protected $author;
51
+
52
+ /**
53
+ * @var string Relative file path to the plugin.
54
+ */
55
+ protected $file;
56
+
57
+ /** @var int Product ID in backend system for quick lookup */
58
+ protected $product_id;
59
+
60
+ /**
61
+ * Yoast_Product constructor.
62
+ *
63
+ * @param string $api_url The URL of the shop running the EDD API.
64
+ * @param string $item_name The item name in the EDD shop.
65
+ * @param string $slug The slug of the plugin, for shiny updates this needs to be a valid HTML id.
66
+ * @param string $version The version number of the item.
67
+ * @param string $item_url The absolute url on which users can purchase a license.
68
+ * @param string $license_page_url Absolute admin URL on which users can enter their license key.
69
+ * @param string $text_domain The text domain used for translating strings.
70
+ * @param string $author The item author.
71
+ * @param string $file The relative file path to the plugin.
72
+ * @param int $product_id The ID of the product in the backend system.
73
+ */
74
+ public function __construct( $api_url, $item_name, $slug, $version, $item_url = '', $license_page_url = '#', $text_domain = 'yoast', $author = 'Yoast', $file = '', $product_id = 0 ) {
75
+ $this->set_api_url( $api_url );
76
+ $this->set_item_name( $item_name );
77
+ $this->set_slug( $slug );
78
+ $this->set_version( $version );
79
+ $this->set_item_url( $item_url );
80
+ $this->set_license_page_url( $license_page_url );
81
+ $this->set_text_domain( $text_domain );
82
+ $this->set_author( $author );
83
+ $this->set_file( $file );
84
+ $this->set_product_id( $product_id );
85
+ }
86
+
87
+ /**
88
+ * @param string $api_url
89
+ */
90
+ public function set_api_url( $api_url ) {
91
+ $this->api_url = $api_url;
92
+ }
93
+
94
+ /**
95
+ * @return string
96
+ */
97
+ public function get_api_url() {
98
+ return $this->api_url;
99
+ }
100
+
101
+ /**
102
+ * @param string $author
103
+ */
104
+ public function set_author( $author ) {
105
+ $this->author = $author;
106
+ }
107
+
108
+ /**
109
+ * @return string
110
+ */
111
+ public function get_author() {
112
+ return $this->author;
113
+ }
114
+
115
+ /**
116
+ * @param string $item_name
117
+ */
118
+ public function set_item_name( $item_name ) {
119
+ $this->item_name = $item_name;
120
+ }
121
+
122
+ /**
123
+ * @return string
124
+ */
125
+ public function get_item_name() {
126
+ return $this->item_name;
127
+ }
128
+
129
+ /**
130
+ * @param string $item_url
131
+ */
132
+ public function set_item_url( $item_url ) {
133
+ if ( empty( $item_url ) ) {
134
+ $item_url = $this->api_url;
135
+ }
136
+
137
+ $this->item_url = $item_url;
138
+ }
139
+
140
+ /**
141
+ * @return string
142
+ */
143
+ public function get_item_url() {
144
+ return $this->item_url;
145
+ }
146
+
147
+ /**
148
+ * @param string $license_page_url
149
+ */
150
+ public function set_license_page_url( $license_page_url ) {
151
+
152
+ if ( is_admin() && is_multisite() ) {
153
+
154
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
155
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
156
+ }
157
+
158
+ if ( is_plugin_active_for_network( $this->get_slug() ) ) {
159
+ $this->license_page_url = network_admin_url( $license_page_url );
160
+
161
+ return;
162
+ }
163
+ }
164
+
165
+ $this->license_page_url = admin_url( $license_page_url );
166
+ }
167
+
168
+ /**
169
+ * @return string
170
+ */
171
+ public function get_license_page_url() {
172
+ return $this->license_page_url;
173
+ }
174
+
175
+ /**
176
+ * @param string $slug
177
+ */
178
+ public function set_slug( $slug ) {
179
+ $this->slug = $slug;
180
+ }
181
+
182
+ /**
183
+ * @return string
184
+ */
185
+ public function get_slug() {
186
+ return $this->slug;
187
+ }
188
+
189
+ /**
190
+ * Returns the dirname of the slug and limits it to 15 chars
191
+ *
192
+ * @return string
193
+ */
194
+ public function get_transient_prefix() {
195
+ return substr( md5( $this->file ), 0, 15 );
196
+ }
197
+
198
+ /**
199
+ * @param string $text_domain
200
+ */
201
+ public function set_text_domain( $text_domain ) {
202
+ $this->text_domain = $text_domain;
203
+ }
204
+
205
+ /**
206
+ * @return string
207
+ */
208
+ public function get_text_domain() {
209
+ return $this->text_domain;
210
+ }
211
+
212
+ /**
213
+ * @param string $version
214
+ */
215
+ public function set_version( $version ) {
216
+ $this->version = $version;
217
+ }
218
+
219
+ /**
220
+ * @return string
221
+ */
222
+ public function get_version() {
223
+ return $this->version;
224
+ }
225
+
226
+ /**
227
+ * Returns the file path relative to the plugins folder
228
+ *
229
+ * @return string
230
+ */
231
+ public function get_file() {
232
+ /*
233
+ * Fall back to the slug for BC reasons.
234
+ *
235
+ * We used to pass the file to the slug field, but this isn't supported with the shiny updates in WordPress.
236
+ * WordPress uses the slug in the HTML as an ID and a slash isn't a valid
237
+ */
238
+ return empty( $this->file ) ? $this->slug : $this->file;
239
+ }
240
+
241
+ /**
242
+ * Sets the file path relative to the plugins folder
243
+ *
244
+ * @param string $file Relative file path to the plugin.
245
+ */
246
+ public function set_file( $file ) {
247
+ $this->file = $file;
248
+ }
249
+
250
+ /**
251
+ * Return the Product ID
252
+ *
253
+ * @return int
254
+ */
255
+ public function get_product_id() {
256
+ return $this->product_id;
257
+ }
258
+
259
+ /**
260
+ * Set the product ID
261
+ *
262
+ * @param int $product_id Product ID to set.
263
+ */
264
+ public function set_product_id( $product_id ) {
265
+ $this->product_id = (int) $product_id;
266
+ }
267
+
268
+ /**
269
+ * Gets a Google Analytics Campaign url for this product
270
+ *
271
+ * @param string $link_identifier
272
+ *
273
+ * @return string The full URL
274
+ */
275
+ public function get_tracking_url( $link_identifier = '' ) {
276
+
277
+ $tracking_vars = array(
278
+ 'utm_campaign' => $this->get_item_name() . ' licensing',
279
+ 'utm_medium' => 'link',
280
+ 'utm_source' => $this->get_item_name(),
281
+ 'utm_content' => $link_identifier
282
+ );
283
+
284
+ // URL encode tracking vars.
285
+ $tracking_vars = urlencode_deep( $tracking_vars );
286
+ $query_string = build_query( $tracking_vars );
287
+
288
+ return $this->get_item_url() . '#' . $query_string;
289
+ }
290
+ }
291
+
292
+ }
vendor/yoast/license-manager-2/class-theme-license-manager.php CHANGED
@@ -1,53 +1,51 @@
1
- <?php
2
-
3
- if( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Theme_License_Manager", false ) ) {
4
-
5
- class Yoast_Theme_License_Manager extends Yoast_License_Manager {
6
-
7
- /**
8
- * Setup auto updater for themes
9
- */
10
- public function setup_auto_updater() {
11
- if ( $this->license_is_valid() ) {
12
- // setup auto updater
13
- require_once dirname( __FILE__ ) . '/class-update-manager.php';
14
- require_once dirname( __FILE__ ) . '/class-theme-update-manager.php'; // @TODO: Autoload?
15
- new Yoast_Theme_Update_Manager( $this->product, $this );
16
- }
17
- }
18
-
19
- /**
20
- * Setup hooks
21
- */
22
- public function specific_hooks() {
23
- // remotely deactivate license upon switching away from this theme
24
- add_action( 'switch_theme', array( $this, 'deactivate_license' ) );
25
-
26
- // Add the license menu
27
- add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
28
- }
29
-
30
- /**
31
- * Add license page and add it to Themes menu
32
- */
33
- public function add_license_menu() {
34
- $theme_page = add_theme_page( sprintf( __( '%s License', $this->product->get_text_domain() ), $this->product->get_item_name() ), __( 'Theme License', $this->product->get_text_domain() ), 'manage_options', 'theme-license', array( $this, 'show_license_page' ) );
35
- }
36
-
37
- /**
38
- * Shows license page
39
- */
40
- public function show_license_page() {
41
- ?>
42
- <div class="wrap">
43
- <?php settings_errors(); ?>
44
-
45
- <?php $this->show_license_form( false ); ?>
46
- </div>
47
- <?php
48
- }
49
-
50
-
51
- }
52
-
53
- }
1
+ <?php
2
+
3
+ if ( class_exists( 'Yoast_License_Manager' ) && ! class_exists( "Yoast_Theme_License_Manager", false ) ) {
4
+
5
+ class Yoast_Theme_License_Manager extends Yoast_License_Manager {
6
+
7
+ /**
8
+ * Setup auto updater for themes
9
+ */
10
+ public function setup_auto_updater() {
11
+ if ( $this->license_is_valid() ) {
12
+ // setup auto updater
13
+ require_once dirname( __FILE__ ) . '/class-update-manager.php';
14
+ require_once dirname( __FILE__ ) . '/class-theme-update-manager.php'; // @TODO: Autoload?
15
+ new Yoast_Theme_Update_Manager( $this->product, $this );
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Setup hooks
21
+ */
22
+ public function specific_hooks() {
23
+ // remotely deactivate license upon switching away from this theme
24
+ add_action( 'switch_theme', array( $this, 'deactivate_license' ) );
25
+
26
+ // Add the license menu
27
+ add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
28
+ }
29
+
30
+ /**
31
+ * Add license page and add it to Themes menu
32
+ */
33
+ public function add_license_menu() {
34
+ add_theme_page( sprintf( __( '%s License', $this->product->get_text_domain() ), $this->product->get_item_name() ), __( 'Theme License', $this->product->get_text_domain() ), 'manage_options', 'theme-license', array( $this, 'show_license_page' ) );
35
+ }
36
+
37
+ /**
38
+ * Shows license page
39
+ */
40
+ public function show_license_page() {
41
+ ?>
42
+ <div class="wrap">
43
+ <?php settings_errors(); ?>
44
+
45
+ <?php $this->show_license_form( false ); ?>
46
+ </div>
47
+ <?php
48
+ }
49
+ }
50
+
51
+ }
 
 
vendor/yoast/license-manager-2/class-theme-update-manager.php CHANGED
@@ -1,149 +1,141 @@
1
- <?php
2
-
3
- if( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( "Yoast_Theme_Update_Manager", false ) ) {
4
-
5
- class Yoast_Theme_Update_Manager extends Yoast_Update_Manager {
6
-
7
- /**
8
- * Constructor
9
- *
10
- * @param string $api_url
11
- * @param string $item_name
12
- * @param string $license_key
13
- * @param string $slug
14
- * @param string $theme_version
15
- * @param string $author (optional)
16
- */
17
- public function __construct( Yoast_Product $product, $license_key ) {
18
-
19
- parent::__construct( $product, $license_key );
20
-
21
- // setup hooks
22
- $this->setup_hooks();
23
- }
24
-
25
- /**
26
- * Get the current theme version
27
- *
28
- * @return string The version number
29
- */
30
- private function get_theme_version() {
31
-
32
- // if version was not set, get it from the Theme stylesheet
33
- if( $this->product->get_version() === '' ) {
34
- $theme = wp_get_theme( $this->product->get_slug() );
35
- return $theme->get( 'Version' );
36
- }
37
-
38
- return $this->product->get_version();
39
- }
40
-
41
- /**
42
- * Setup hooks
43
- */
44
- private function setup_hooks() {
45
- add_filter( 'site_transient_update_themes', array( $this, 'set_theme_update_transient' ) );
46
- add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) );
47
- }
48
-
49
- /**
50
- * Set "updates available" transient
51
- */
52
- public function set_theme_update_transient( $value ) {
53
-
54
- $update_data = $this->get_update_data();
55
-
56
- if( $update_data === false ) {
57
- return $value;
58
- }
59
-
60
- // add update data to "updates available" array. convert object to array.
61
- $value->response[ $this->product->get_slug() ] = (array) $update_data;
62
-
63
- return $value;
64
- }
65
-
66
- /**
67
- * Add hooks and scripts to the Appearance > Themes screen
68
- */
69
- public function load_themes_screen() {
70
-
71
- $update_data = $this->get_update_data();
72
-
73
- // only do if an update is available
74
- if( $update_data === false ) {
75
- return;
76
- }
77
-
78
- add_thickbox();
79
- add_action( 'admin_notices', array( $this, 'show_update_details' ) );
80
- }
81
-
82
- /**
83
- * Show update link.
84
- * Opens Thickbox with Changelog.
85
- */
86
- public function show_update_details() {
87
-
88
- $update_data = $this->get_update_data();
89
-
90
- // only show if an update is available
91
- if( $update_data === false ) {
92
- return;
93
- }
94
-
95
- $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
96
- $update_onclick = ' onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update." ) ) . '\') ) {return true;}return false;"';
97
- ?>
98
- <div id="update-nag">
99
- <?php
100
- printf(
101
- __( '<strong>%s version %s</strong> is available. <a href="%s" class="thickbox" title="%s">Check out what\'s new</a> or <a href="%s" %s>update now</a>.' ),
102
- $this->product->get_item_name(),
103
- $update_data->new_version,
104
- '#TB_inline?width=640&amp;inlineId=' . $this->product->get_slug() . '_changelog',
105
- $this->get_item_name(),
106
- $update_url,
107
- $update_onclick
108
- );
109
- ?>
110
- </div>
111
- <div id="<?php echo $this->product->get_slug(); ?>_changelog" style="display: none;">
112
- <?php echo wpautop( $update_data->sections['changelog'] ); ?>
113
- </div>
114
- <?php
115
- }
116
-
117
-
118
- /**
119
- * Get update data
120
- *
121
- * This gets the update data from a transient (12 hours), if set.
122
- * If not, it will make a remote request and get the update data.
123
- *
124
- * @return object $update_data Object containing the update data
125
- */
126
- public function get_update_data() {
127
-
128
- $api_response = $this->get_remote_data();
129
-
130
- if( false === $api_response ) {
131
- return false;
132
- }
133
-
134
- $update_data = $api_response;
135
-
136
- // check if a new version is available.
137
- if ( version_compare( $this->get_theme_version(), $update_data->new_version, '>=' ) ) {
138
- return false;
139
- }
140
-
141
-
142
- // an update is available
143
- return $update_data;
144
- }
145
-
146
-
147
- }
148
-
149
- }
1
+ <?php
2
+
3
+ if ( class_exists( 'Yoast_Update_Manager' ) && ! class_exists( 'Yoast_Theme_Update_Manager', false ) ) {
4
+
5
+ class Yoast_Theme_Update_Manager extends Yoast_Update_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param Yoast_Product $product The Product.
11
+ * @param string $license_key The License key.
12
+ */
13
+ public function __construct( Yoast_Product $product, $license_key ) {
14
+ parent::__construct( $product, $license_key );
15
+
16
+ // setup hooks
17
+ $this->setup_hooks();
18
+ }
19
+
20
+ /**
21
+ * Get the current theme version
22
+ *
23
+ * @return string The version number
24
+ */
25
+ private function get_theme_version() {
26
+
27
+ // if version was not set, get it from the Theme stylesheet
28
+ if ( $this->product->get_version() === '' ) {
29
+ $theme = wp_get_theme( $this->product->get_slug() );
30
+
31
+ return $theme->get( 'Version' );
32
+ }
33
+
34
+ return $this->product->get_version();
35
+ }
36
+
37
+ /**
38
+ * Setup hooks
39
+ */
40
+ private function setup_hooks() {
41
+ add_filter( 'site_transient_update_themes', array( $this, 'set_theme_update_transient' ) );
42
+ add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) );
43
+ }
44
+
45
+ /**
46
+ * Set "updates available" transient
47
+ */
48
+ public function set_theme_update_transient( $value ) {
49
+
50
+ $update_data = $this->get_update_data();
51
+
52
+ if ( $update_data === false ) {
53
+ return $value;
54
+ }
55
+
56
+ // add update data to "updates available" array. convert object to array.
57
+ $value->response[ $this->product->get_slug() ] = (array) $update_data;
58
+
59
+ return $value;
60
+ }
61
+
62
+ /**
63
+ * Add hooks and scripts to the Appearance > Themes screen
64
+ */
65
+ public function load_themes_screen() {
66
+
67
+ $update_data = $this->get_update_data();
68
+
69
+ // only do if an update is available
70
+ if ( $update_data === false ) {
71
+ return;
72
+ }
73
+
74
+ add_thickbox();
75
+ add_action( 'admin_notices', array( $this, 'show_update_details' ) );
76
+ }
77
+
78
+ /**
79
+ * Show update link.
80
+ * Opens Thickbox with Changelog.
81
+ */
82
+ public function show_update_details() {
83
+
84
+ $update_data = $this->get_update_data();
85
+
86
+ // only show if an update is available
87
+ if ( $update_data === false ) {
88
+ return;
89
+ }
90
+
91
+ $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
92
+ $update_onclick = ' onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update." ) ) . '\') ) {return true;}return false;"';
93
+ ?>
94
+ <div id="update-nag">
95
+ <?php
96
+ printf(
97
+ __( '<strong>%s version %s</strong> is available. <a href="%s" class="thickbox" title="%s">Check out what\'s new</a> or <a href="%s" %s>update now</a>.' ),
98
+ $this->product->get_item_name(),
99
+ $update_data->new_version,
100
+ '#TB_inline?width=640&amp;inlineId=' . $this->product->get_slug() . '_changelog',
101
+ $this->get_item_name(),
102
+ $update_url,
103
+ $update_onclick
104
+ );
105
+ ?>
106
+ </div>
107
+ <div id="<?php echo $this->product->get_slug(); ?>_changelog" style="display: none;">
108
+ <?php echo wpautop( $update_data->sections['changelog'] ); ?>
109
+ </div>
110
+ <?php
111
+ }
112
+
113
+ /**
114
+ * Get update data
115
+ *
116
+ * This gets the update data from a transient (12 hours), if set.
117
+ * If not, it will make a remote request and get the update data.
118
+ *
119
+ * @return object $update_data Object containing the update data
120
+ */
121
+ public function get_update_data() {
122
+
123
+ $api_response = $this->get_remote_data();
124
+
125
+ if ( false === $api_response ) {
126
+ return false;
127
+ }
128
+
129
+ $update_data = $api_response;
130
+
131
+ // check if a new version is available.
132
+ if ( version_compare( $this->get_theme_version(), $update_data->new_version, '>=' ) ) {
133
+ return false;
134
+ }
135
+
136
+ // an update is available
137
+ return $update_data;
138
+ }
139
+ }
140
+
141
+ }
 
 
 
 
 
 
 
 
vendor/yoast/license-manager-2/class-update-manager.php CHANGED
@@ -1,211 +1,216 @@
1
- <?php
2
-
3
- if( ! class_exists( "Yoast_Update_Manager", false ) ) {
4
-
5
- class Yoast_Update_Manager {
6
-
7
- /**
8
- * @var Yoast_Product
9
- */
10
- protected $product;
11
-
12
- /**
13
- * @var Yoast_License_Manager
14
- */
15
- protected $license_manager;
16
-
17
- /**
18
- * @var string
19
- */
20
- protected $error_message = '';
21
-
22
- /**
23
- * @var object
24
- */
25
- protected $update_response = null;
26
-
27
- /**
28
- * @var string The transient name storing the API response
29
- */
30
- private $response_transient_key = '';
31
-
32
- /**
33
- * @var string The transient name that stores failed request tries
34
- */
35
- private $request_failed_transient_key = '';
36
-
37
- /**
38
- * Constructor
39
- *
40
- * @param string $api_url The url to the EDD shop
41
- * @param string $item_name The item name in the EDD shop
42
- * @param string $license_key The (valid) license key
43
- * @param string $slug The slug. This is either the plugin main file path or the theme slug.
44
- * @param string $version The current plugin or theme version
45
- * @param string $author (optional) The item author.
46
- */
47
- public function __construct( Yoast_Product $product, $license_manager ) {
48
- $this->product = $product;
49
- $this->license_manager = $license_manager;
50
-
51
- // generate transient names
52
- $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
53
- $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
54
-
55
- // maybe delete transient
56
- $this->maybe_delete_transients();
57
- }
58
-
59
- /**
60
- * Deletes the various transients
61
- * If we're on the update-core.php?force-check=1 page
62
- */
63
- private function maybe_delete_transients() {
64
- global $pagenow;
65
-
66
- if( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
67
- delete_transient( $this->response_transient_key );
68
- delete_transient( $this->request_failed_transient_key );
69
- }
70
- }
71
-
72
- /**
73
- * If the update check returned a WP_Error, show it to the user
74
- */
75
- public function show_update_error() {
76
-
77
- if ( $this->error_message === '' ) {
78
- return;
79
- }
80
-
81
- ?>
82
- <div class="error">
83
- <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
84
- </div>
85
- <?php
86
- }
87
-
88
- /**
89
- * Calls the API and, if successfull, returns the object delivered by the API.
90
- *
91
- * @uses get_bloginfo()
92
- * @uses wp_remote_post()
93
- * @uses is_wp_error()
94
- *
95
- * @return false||object
96
- */
97
- private function call_remote_api() {
98
-
99
- // only check if the failed transient is not set (or if it's expired)
100
- if( get_transient( $this->request_failed_transient_key ) !== false ) {
101
- return false;
102
- }
103
-
104
- // start request process
105
- global $wp_version;
106
-
107
- // set a transient to prevent failed update checks on every page load
108
- // this transient will be removed if a request succeeds
109
- set_transient( $this->request_failed_transient_key, 'failed', 10800 );
110
-
111
- // setup api parameters
112
- $api_params = array(
113
- 'edd_action' => 'get_version',
114
- 'license' => $this->license_manager->get_license_key(),
115
- 'item_name' => $this->product->get_item_name(),
116
- 'wp_version' => $wp_version,
117
- 'item_version' => $this->product->get_version(),
118
- 'url' => home_url(),
119
- 'slug' => $this->product->get_slug()
120
- );
121
-
122
- // setup request parameters
123
- $request_params = array(
124
- 'method' => 'POST',
125
- 'body' => $api_params
126
- );
127
-
128
- require_once dirname( __FILE__ ) . '/class-api-request.php';
129
- $request = new Yoast_API_Request( $this->product->get_api_url(), $request_params );
130
-
131
- if( $request->is_valid() !== true ) {
132
-
133
- // show error message
134
- $this->error_message = $request->get_error_message();
135
- add_action( 'admin_notices', array( $this, 'show_update_error' ) );
136
-
137
- return false;
138
- }
139
-
140
- // request succeeded, delete transient indicating a request failed
141
- delete_transient( $this->request_failed_transient_key );
142
-
143
- // decode response
144
- $response = $request->get_response();
145
-
146
- // check if response returned that a given site was inactive
147
- if( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
148
-
149
- // deactivate local license
150
- $this->license_manager->set_license_status( 'invalid' );
151
-
152
- // show notice to let the user know we deactivated his/her license
153
- $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
154
- add_action( 'admin_notices', array( $this, 'show_update_error' ) );
155
- }
156
-
157
- $response->sections = maybe_unserialize( $response->sections );
158
-
159
- // store response
160
- set_transient( $this->response_transient_key, $response, 10800 );
161
-
162
- return $response;
163
- }
164
-
165
- /**
166
- * Gets the remote product data (from the EDD API)
167
- *
168
- * - If it was previously fetched in the current requests, this gets it from the instance property
169
- * - Next, it tries the 3-hour transient
170
- * - Next, it calls the remote API and stores the result
171
- *
172
- * @return object
173
- */
174
- protected function get_remote_data() {
175
-
176
- // always use property if it's set
177
- if( null !== $this->update_response ) {
178
- return $this->update_response;
179
- }
180
-
181
- // get cached remote data
182
- $data = $this->get_cached_remote_data();
183
-
184
- // if cache is empty or expired, call remote api
185
- if( $data === false ) {
186
- $data = $this->call_remote_api();
187
- }
188
-
189
- $this->update_response = $data;
190
- return $data;
191
- }
192
-
193
- /**
194
- * Gets the remote product data from a 3-hour transient
195
- *
196
- * @return bool|mixed
197
- */
198
- private function get_cached_remote_data() {
199
-
200
- $data = get_transient( $this->response_transient_key );
201
-
202
- if( $data ) {
203
- return $data;
204
- }
205
-
206
- return false;
207
- }
208
-
209
- }
210
-
211
- }
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( "Yoast_Update_Manager", false ) ) {
4
+
5
+ class Yoast_Update_Manager {
6
+
7
+ /**
8
+ * @var Yoast_Product
9
+ */
10
+ protected $product;
11
+
12
+ /**
13
+ * @var Yoast_License_Manager
14
+ */
15
+ protected $license_manager;
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected $error_message = '';
21
+
22
+ /**
23
+ * @var object
24
+ */
25
+ protected $update_response = null;
26
+
27
+ /**
28
+ * @var string The transient name storing the API response
29
+ */
30
+ private $response_transient_key = '';
31
+
32
+ /**
33
+ * @var string The transient name that stores failed request tries
34
+ */
35
+ private $request_failed_transient_key = '';
36
+
37
+ /**
38
+ * Constructor
39
+ *
40
+ * @param Yoast_Product $product The product.
41
+ * @param Yoast_License_Manager $license_manager The License Manager.
42
+ */
43
+ public function __construct( Yoast_Product $product, $license_manager ) {
44
+ $this->product = $product;
45
+ $this->license_manager = $license_manager;
46
+
47
+ // generate transient names
48
+ $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
49
+ $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
50
+
51
+ // maybe delete transient
52
+ $this->maybe_delete_transients();
53
+ }
54
+
55
+ /**
56
+ * Deletes the various transients
57
+ * If we're on the update-core.php?force-check=1 page
58
+ */
59
+ private function maybe_delete_transients() {
60
+ global $pagenow;
61
+
62
+ if ( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
63
+ delete_transient( $this->response_transient_key );
64
+ delete_transient( $this->request_failed_transient_key );
65
+ }
66
+ }
67
+
68
+ /**
69
+ * If the update check returned a WP_Error, show it to the user
70
+ */
71
+ public function show_update_error() {
72
+
73
+ if ( $this->error_message === '' ) {
74
+ return;
75
+ }
76
+
77
+ ?>
78
+ <div class="error">
79
+ <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
80
+ </div>
81
+ <?php
82
+ }
83
+
84
+ /**
85
+ * Calls the API and, if successfull, returns the object delivered by the API.
86
+ *
87
+ * @uses get_bloginfo()
88
+ * @uses wp_remote_post()
89
+ * @uses is_wp_error()
90
+ *
91
+ * @return false||object
92
+ */
93
+ private function call_remote_api() {
94
+
95
+ // only check if the failed transient is not set (or if it's expired)
96
+ if ( get_transient( $this->request_failed_transient_key ) !== false ) {
97
+ return false;
98
+ }
99
+
100
+ // start request process
101
+ global $wp_version;
102
+
103
+ // set a transient to prevent failed update checks on every page load
104
+ // this transient will be removed if a request succeeds
105
+ set_transient( $this->request_failed_transient_key, 'failed', 10800 );
106
+
107
+ // setup api parameters
108
+ $api_params = array(
109
+ 'edd_action' => 'get_version',
110
+ 'license' => $this->license_manager->get_license_key(),
111
+ 'item_name' => $this->product->get_item_name(),
112
+ 'wp_version' => $wp_version,
113
+ 'item_version' => $this->product->get_version(),
114
+ 'url' => home_url(),
115
+ 'slug' => $this->product->get_slug(),
116
+ );
117
+
118
+ // Add product ID from product if it is implemented.
119
+ if ( method_exists( $this->product, 'get_product_id' ) ) {
120
+ $product_id = $this->product->get_product_id();
121
+ if ( $product_id > 0 ) {
122
+ $api_params['product_id'] = $this->product->get_product_id();
123
+ }
124
+ }
125
+
126
+ // setup request parameters
127
+ $request_params = array(
128
+ 'method' => 'POST',
129
+ 'body' => $api_params
130
+ );
131
+
132
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
133
+ $request = new Yoast_API_Request( $this->product->get_api_url(), $request_params );
134
+
135
+ if ( $request->is_valid() !== true ) {
136
+
137
+ // show error message
138
+ $this->error_message = $request->get_error_message();
139
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
140
+
141
+ return false;
142
+ }
143
+
144
+ // request succeeded, delete transient indicating a request failed
145
+ delete_transient( $this->request_failed_transient_key );
146
+
147
+ // decode response
148
+ $response = $request->get_response();
149
+
150
+ // check if response returned that a given site was inactive
151
+ if ( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
152
+
153
+ // deactivate local license
154
+ $this->license_manager->set_license_status( 'invalid' );
155
+
156
+ // show notice to let the user know we deactivated his/her license
157
+ $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
158
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
159
+ }
160
+
161
+ $response->sections = maybe_unserialize( $response->sections );
162
+
163
+ // store response
164
+ set_transient( $this->response_transient_key, $response, 10800 );
165
+
166
+ return $response;
167
+ }
168
+
169
+ /**
170
+ * Gets the remote product data (from the EDD API)
171
+ *
172
+ * - If it was previously fetched in the current requests, this gets it from the instance property
173
+ * - Next, it tries the 3-hour transient
174
+ * - Next, it calls the remote API and stores the result
175
+ *
176
+ * @return object
177
+ */
178
+ protected function get_remote_data() {
179
+
180
+ // always use property if it's set
181
+ if ( null !== $this->update_response ) {
182
+ return $this->update_response;
183
+ }
184
+
185
+ // get cached remote data
186
+ $data = $this->get_cached_remote_data();
187
+
188
+ // if cache is empty or expired, call remote api
189
+ if ( $data === false ) {
190
+ $data = $this->call_remote_api();
191
+ }
192
+
193
+ $this->update_response = $data;
194
+
195
+ return $data;
196
+ }
197
+
198
+ /**
199
+ * Gets the remote product data from a 3-hour transient
200
+ *
201
+ * @return bool|mixed
202
+ */
203
+ private function get_cached_remote_data() {
204
+
205
+ $data = get_transient( $this->response_transient_key );
206
+
207
+ if ( $data ) {
208
+ return $data;
209
+ }
210
+
211
+ return false;
212
+ }
213
+
214
+ }
215
+
216
+ }
vendor/yoast/license-manager/.gitigore CHANGED
@@ -1,2 +1,2 @@
1
- .idea/
2
- .idea/*
1
+ .idea/
2
+ .idea/*
vendor/yoast/license-manager/README.md CHANGED
@@ -1,21 +1,21 @@
1
- Yoast License Manager
2
- =====================
3
-
4
- This library will take care of the following.
5
-
6
- - Managing license related options
7
- - Setting license key from a constant
8
- - Obfuscasting (valid) license keys
9
- - Remote license activation / deactivation
10
- - Checking for plugin or theme updates
11
-
12
- ## Usage
13
-
14
- ### Inside Plugins
15
-
16
- A sample plugin is included, [have a look at its source](https://github.com/Yoast/License-Manager/blob/master/samples/sample-plugin.php).
17
-
18
- ### Inside Themes
19
-
20
- A sample theme `functions.php` file is included, [have a look here](https://github.com/Yoast/License-Manager/blob/master/samples/sample-theme-functions.php).
21
-
1
+ Yoast License Manager
2
+ =====================
3
+
4
+ This library will take care of the following.
5
+
6
+ - Managing license related options
7
+ - Setting license key from a constant
8
+ - Obfuscasting (valid) license keys
9
+ - Remote license activation / deactivation
10
+ - Checking for plugin or theme updates
11
+
12
+ ## Usage
13
+
14
+ ### Inside Plugins
15
+
16
+ A sample plugin is included, [have a look at its source](https://github.com/Yoast/License-Manager/blob/master/samples/sample-plugin.php).
17
+
18
+ ### Inside Themes
19
+
20
+ A sample theme `functions.php` file is included, [have a look here](https://github.com/Yoast/License-Manager/blob/master/samples/sample-theme-functions.php).
21
+
vendor/yoast/license-manager/class-api-request.php CHANGED
@@ -1,140 +1,140 @@
1
- <?php
2
-
3
- if( ! class_exists( "MI_API_Request", false ) ) {
4
-
5
- /**
6
- * Handles requests to the Yoast EDD API
7
- */
8
- class MI_API_Request {
9
-
10
- /**
11
- * @var string Request URL
12
- */
13
- private $url = '';
14
-
15
- /**
16
- * @var array Request parameters
17
- */
18
- private $args = array(
19
- 'method' => 'GET',
20
- 'timeout' => 10,
21
- 'sslverify' => false,
22
- 'headers' => array(
23
- 'Accept-Encoding' => '*',
24
- 'X-Yoast-EDD' => '1'
25
- )
26
- );
27
-
28
- /**
29
- * @var boolean
30
- */
31
- private $success = false;
32
-
33
- /**
34
- * @var mixed
35
- */
36
- private $response;
37
-
38
- /**
39
- * @var string
40
- */
41
- private $error_message = '';
42
-
43
- /**
44
- * Constructor
45
- *
46
- * @param string url
47
- * @param array $args
48
- */
49
- public function __construct( $url, array $args = array() ) {
50
-
51
- // set api url
52
- $this->url = $url;
53
-
54
- // set request args (merge with defaults)
55
- $this->args = wp_parse_args( $args, $this->args );
56
-
57
- // fire the request
58
- $this->success = $this->fire();
59
- }
60
-
61
- /**
62
- * Fires the request, automatically called from constructor
63
- *
64
- * @return boolean
65
- */
66
- private function fire() {
67
-
68
- // fire request to shop
69
- $response = wp_remote_request( $this->url, $this->args );
70
-
71
- // validate raw response
72
- if( $this->validate_raw_response( $response ) === false ) {
73
- return false;
74
- }
75
-
76
- // decode the response
77
- $this->response = json_decode( wp_remote_retrieve_body( $response ) );
78
-
79
- // response should be an object
80
- if( ! is_object( $this->response ) ) {
81
- $this->error_message = 'No JSON object was returned.';
82
- return false;
83
- }
84
-
85
- return true;
86
- }
87
-
88
- /**
89
- * @param object $response
90
- * @return boolean
91
- */
92
- private function validate_raw_response( $response ) {
93
-
94
- // make sure response came back okay
95
- if( is_wp_error( $response ) ) {
96
- $this->error_message = $response->get_error_message();
97
- return false;
98
- }
99
-
100
- // check response code, should be 200
101
- $response_code = wp_remote_retrieve_response_code( $response );
102
-
103
- if( false === strstr( $response_code, '200' ) ) {
104
-
105
- $response_message = wp_remote_retrieve_response_message( $response );
106
- $this->error_message = "{$response_code} {$response_message}";
107
-
108
- return false;
109
- }
110
-
111
- return true;
112
- }
113
-
114
- /**
115
- * Was a valid response returned?
116
- *
117
- * @return boolean
118
- */
119
- public function is_valid() {
120
- return ( $this->success === true );
121
- }
122
-
123
- /**
124
- * @return string
125
- */
126
- public function get_error_message() {
127
- return $this->error_message;
128
- }
129
-
130
- /**
131
- * @return object
132
- */
133
- public function get_response() {
134
- return $this->response;
135
- }
136
-
137
- }
138
-
139
- }
140
-
1
+ <?php
2
+
3
+ if( ! class_exists( "MI_API_Request", false ) ) {
4
+
5
+ /**
6
+ * Handles requests to the Yoast EDD API
7
+ */
8
+ class MI_API_Request {
9
+
10
+ /**
11
+ * @var string Request URL
12
+ */
13
+ private $url = '';
14
+
15
+ /**
16
+ * @var array Request parameters
17
+ */
18
+ private $args = array(
19
+ 'method' => 'GET',
20
+ 'timeout' => 10,
21
+ 'sslverify' => false,
22
+ 'headers' => array(
23
+ 'Accept-Encoding' => '*',
24
+ 'X-Yoast-EDD' => '1'
25
+ )
26
+ );
27
+
28
+ /**
29
+ * @var boolean
30
+ */
31
+ private $success = false;
32
+
33
+ /**
34
+ * @var mixed
35
+ */
36
+ private $response;
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ private $error_message = '';
42
+
43
+ /**
44
+ * Constructor
45
+ *
46
+ * @param string url
47
+ * @param array $args
48
+ */
49
+ public function __construct( $url, array $args = array() ) {
50
+
51
+ // set api url
52
+ $this->url = $url;
53
+
54
+ // set request args (merge with defaults)
55
+ $this->args = wp_parse_args( $args, $this->args );
56
+
57
+ // fire the request
58
+ $this->success = $this->fire();
59
+ }
60
+
61
+ /**
62
+ * Fires the request, automatically called from constructor
63
+ *
64
+ * @return boolean
65
+ */
66
+ private function fire() {
67
+
68
+ // fire request to shop
69
+ $response = wp_remote_request( $this->url, $this->args );
70
+
71
+ // validate raw response
72
+ if( $this->validate_raw_response( $response ) === false ) {
73
+ return false;
74
+ }
75
+
76
+ // decode the response
77
+ $this->response = json_decode( wp_remote_retrieve_body( $response ) );
78
+
79
+ // response should be an object
80
+ if( ! is_object( $this->response ) ) {
81
+ $this->error_message = 'No JSON object was returned.';
82
+ return false;
83
+ }
84
+
85
+ return true;
86
+ }
87
+
88
+ /**
89
+ * @param object $response
90
+ * @return boolean
91
+ */
92
+ private function validate_raw_response( $response ) {
93
+
94
+ // make sure response came back okay
95
+ if( is_wp_error( $response ) ) {
96
+ $this->error_message = $response->get_error_message();
97
+ return false;
98
+ }
99
+
100
+ // check response code, should be 200
101
+ $response_code = wp_remote_retrieve_response_code( $response );
102
+
103
+ if( false === strstr( $response_code, '200' ) ) {
104
+
105
+ $response_message = wp_remote_retrieve_response_message( $response );
106
+ $this->error_message = "{$response_code} {$response_message}";
107
+
108
+ return false;
109
+ }
110
+
111
+ return true;
112
+ }
113
+
114
+ /**
115
+ * Was a valid response returned?
116
+ *
117
+ * @return boolean
118
+ */
119
+ public function is_valid() {
120
+ return ( $this->success === true );
121
+ }
122
+
123
+ /**
124
+ * @return string
125
+ */
126
+ public function get_error_message() {
127
+ return $this->error_message;
128
+ }
129
+
130
+ /**
131
+ * @return object
132
+ */
133
+ public function get_response() {
134
+ return $this->response;
135
+ }
136
+
137
+ }
138
+
139
+ }
140
+
vendor/yoast/license-manager/class-license-manager.php CHANGED
@@ -1,619 +1,613 @@
1
- <?php
2
-
3
- if ( ! interface_exists( 'iMI_License_Manager', false ) ) {
4
-
5
- interface iMI_License_Manager {
6
-
7
- public function specific_hooks();
8
-
9
- public function setup_auto_updater();
10
-
11
- }
12
-
13
- }
14
-
15
-
16
- if ( ! class_exists( 'MI_License_Manager', false ) ) {
17
-
18
- /**
19
- * Class MI_License_Manager
20
- *
21
- * @todo Maybe create a license class that contains key and option
22
- * @todo Not sure if MI_License_Manager is a good name for this class, it's more managing the product (plugin or theme)
23
- */
24
- abstract class MI_License_Manager implements iMI_License_Manager {
25
-
26
- /**
27
- * @const VERSION The version number of the License_Manager class
28
- */
29
- const VERSION = 1;
30
-
31
- /**
32
- * @var Yoast_License The license
33
- */
34
- protected $product;
35
-
36
- /**
37
- * @var string
38
- */
39
- private $license_constant_name = '';
40
-
41
- /**
42
- * @var boolean True if license is defined with a constant
43
- */
44
- private $license_constant_is_defined = false;
45
-
46
- /**
47
- * @var boolean True if remote license activation just failed
48
- */
49
- private $remote_license_activation_failed = false;
50
-
51
- /**
52
- * @var array Array of license related options
53
- */
54
- private $options = array();
55
-
56
- /**
57
- * @var string Used to prefix ID's, option names, etc..
58
- */
59
- protected $prefix;
60
-
61
- /**
62
- * @var bool Boolean indicating whether this plugin is network activated
63
- */
64
- protected $is_network_activated = false;
65
-
66
- /**
67
- * Constructor
68
- *
69
- * @param MI_Product $product
70
- */
71
- public function __construct( MI_Product $product ) {
72
-
73
- // Set the license
74
- $this->product = $product;
75
-
76
- // set prefix
77
- $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' );
78
-
79
- // maybe set license key from constant
80
- $this->maybe_set_license_key_from_constant();
81
- }
82
-
83
- /**
84
- * Setup hooks
85
- *
86
- */
87
- public function setup_hooks() {
88
-
89
- // show admin notice if license is not active
90
- add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
91
-
92
- // catch POST requests from license form
93
- add_action( 'admin_init', array( $this, 'catch_post_request' ) );
94
-
95
- // setup item type (plugin|theme) specific hooks
96
- $this->specific_hooks();
97
-
98
- // setup the auto updater
99
- $this->setup_auto_updater();
100
-
101
- }
102
-
103
- /**
104
- * Display license specific admin notices, namely:
105
- *
106
- * - License for the product isn't activated
107
- * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL
108
- */
109
- public function display_admin_notices() {
110
-
111
- if ( ! current_user_can( 'manage_options' ) ) {
112
- return;
113
- }
114
-
115
- // show notice if license is invalid
116
- if ( ! $this->license_is_valid() ) {
117
- if ( $this->get_license_key() == '' ) {
118
- $message = '<b>Warning!</b> You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! <a href="%s">Enter your license key</a> or <a href="%s" target="_blank">get a license here</a>.';
119
- } else {
120
- $message = '<b>Warning!</b> Your %s license is inactive which means you\'re missing out on updates and support! <a href="%s">Activate your license</a> or <a href="%s" target="_blank">get a license here</a>.';
121
- }
122
- ?>
123
- <div class="error">
124
- <p><?php printf( __( $message, $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?></p>
125
- </div>
126
- <?php
127
- }
128
-
129
- // show notice if external requests are blocked through the WP_HTTP_BLOCK_EXTERNAL constant
130
- if ( defined( "WP_HTTP_BLOCK_EXTERNAL" ) && WP_HTTP_BLOCK_EXTERNAL === true ) {
131
-
132
- // check if our API endpoint is in the allowed hosts
133
- $host = parse_url( $this->product->get_api_url(), PHP_URL_HOST );
134
-
135
- if ( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) {
136
- ?>
137
- <div class="error">
138
- <p><?php printf( __( '<b>Warning!</b> You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '<strong>' . $host . '</strong>', '<code>WP_ACCESSIBLE_HOSTS</code>' ); ?></p>
139
- </div>
140
- <?php
141
- }
142
-
143
- }
144
- }
145
-
146
- /**
147
- * Set a notice to display in the admin area
148
- *
149
- * @param string $type error|updated
150
- * @param string $message The message to display
151
- */
152
- protected function set_notice( $message, $success = true ) {
153
- $css_class = ( $success ) ? 'updated' : 'error';
154
- add_settings_error( $this->prefix . 'license', 'license-notice', $message, $css_class );
155
- }
156
-
157
- /**
158
- * Remotely activate License
159
- * @return boolean True if the license is now activated, false if not
160
- */
161
- public function activate_license() {
162
-
163
- $result = $this->call_license_api( 'activate' );
164
-
165
-
166
- if ( $result ) {
167
-
168
- // story expiry date
169
- if ( isset( $result->expires ) ) {
170
- $this->set_license_expiry_date( $result->expires );
171
- $expiry_date = strtotime( $result->expires );
172
- } else {
173
- $expiry_date = false;
174
- }
175
-
176
- // show success notice if license is valid
177
- if ( $result->license === 'valid' ) {
178
-
179
- $message = sprintf( __( "Your %s license has been activated. ", $this->product->get_text_domain() ), $this->product->get_item_name() );
180
-
181
- // show a custom notice if users have an unlimited license
182
- if ( $result->license_limit == 0 ) {
183
- $message .= __( "You have an unlimited license. ", $this->product->get_text_domain() );
184
- } else {
185
- $message .= sprintf( __( "You have used %d/%d activations. ", $this->product->get_text_domain() ), $result->site_count, $result->license_limit );
186
- }
187
-
188
- // add upgrade notice if user has less than 3 activations left
189
- if ( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) {
190
- $message .= sprintf( __( '<a href="%s">Did you know you can upgrade your license?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-nearing-limit-notice' ) );
191
- // add extend notice if license is expiring in less than 1 month
192
- } elseif ( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) {
193
- $days_left = round( ( $expiry_date - strtotime( "now" ) ) / 86400 );
194
- $message .= sprintf( __( '<a href="%s">Your license is expiring in %d days, would you like to extend it?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expiring-notice' ), $days_left );
195
- }
196
-
197
- $this->set_notice( $message, true );
198
-
199
- } else {
200
-
201
- if ( isset( $result->error ) && $result->error === 'no_activations_left' ) {
202
- // show notice if user is at their activation limit
203
- $this->set_notice( sprintf( __( 'You\'ve reached your activation limit. You must <a href="%s">upgrade your license</a> to use it on this site.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-at-limit-notice' ) ), false );
204
- } elseif ( isset( $result->error ) && $result->error == "expired" ) {
205
- // show notice if the license is expired
206
- $this->set_notice( sprintf( __( 'Your license has expired. You must <a href="%s">extend your license</a> in order to use it again.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expired-notice' ) ), false );
207
- } else {
208
- // show a general notice if it's any other error
209
- $this->set_notice( __( "Failed to activate your license, your license key seems to be invalid.", $this->product->get_text_domain() ), false );
210
- }
211
-
212
- $this->remote_license_activation_failed = true;
213
- }
214
-
215
- $this->set_license_status( $result->license );
216
- }
217
-
218
- return ( $this->license_is_valid() );
219
- }
220
-
221
- /**
222
- * Remotely deactivate License
223
- * @return boolean True if the license is now deactivated, false if not
224
- */
225
- public function deactivate_license() {
226
-
227
- $result = $this->call_license_api( 'deactivate' );
228
-
229
- if ( $result ) {
230
-
231
- // show notice if license is deactivated
232
- if ( $result->license === 'deactivated' ) {
233
- $this->set_notice( sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ) );
234
- } else {
235
- $this->set_notice( sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ), false );
236
- }
237
-
238
- $this->set_license_status( $result->license );
239
- }
240
-
241
- return ( $this->get_license_status() === 'deactivated' );
242
- }
243
-
244
- /**
245
- * @param string $action activate|deactivate
246
- *
247
- * @return mixed
248
- */
249
- protected function call_license_api( $action ) {
250
-
251
- // don't make a request if license key is empty
252
- if ( $this->get_license_key() === '' ) {
253
- return false;
254
- }
255
-
256
- // data to send in our API request
257
- $api_params = array(
258
- 'edd_action' => $action . '_license',
259
- 'license' => $this->get_license_key(),
260
- 'item_name' => urlencode( trim( $this->product->get_item_name() ) ),
261
- 'url' => get_option( 'home' ) // grab the URL straight from the option to prevent filters from breaking it.
262
- );
263
-
264
- // create api request url
265
- $url = add_query_arg( $api_params, $this->product->get_api_url() );
266
-
267
- require_once dirname( __FILE__ ) . '/class-api-request.php';
268
- $request = new MI_API_Request( $url );
269
-
270
- if ( $request->is_valid() !== true ) {
271
- $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '<a href="http://kb.yoast.com/article/13-license-activation-notices">', '</a>' ), false );
272
- }
273
-
274
- // get response
275
- $response = $request->get_response();
276
-
277
- // update license status
278
- $license_data = $response;
279
-
280
- return $license_data;
281
- }
282
-
283
-
284
- /**
285
- * Set the license status
286
- *
287
- * @param string $license_status
288
- */
289
- public function set_license_status( $license_status ) {
290
- $this->set_option( 'status', $license_status );
291
- }
292
-
293
- /**
294
- * Get the license status
295
- *
296
- * @return string $license_status;
297
- */
298
- public function get_license_status() {
299
- $license_status = $this->get_option( 'status' );
300
-
301
- return trim( $license_status );
302
- }
303
-
304
- /**
305
- * Set the license key
306
- *
307
- * @param string $license_key
308
- */
309
- public function set_license_key( $license_key ) {
310
- $this->set_option( 'key', $license_key );
311
- }
312
-
313
- /**
314
- * Gets the license key from constant or option
315
- *
316
- * @return string $license_key
317
- */
318
- public function get_license_key() {
319
- $license_key = $this->get_option( 'key' );
320
-
321
- return trim( $license_key );
322
- }
323
-
324
- /**
325
- * Gets the license expiry date
326
- *
327
- * @return string
328
- */
329
- public function get_license_expiry_date() {
330
- return $this->get_option( 'expiry_date' );
331
- }
332
-
333
- /**
334
- * Stores the license expiry date
335
- */
336
- public function set_license_expiry_date( $expiry_date ) {
337
- $this->set_option( 'expiry_date', $expiry_date );
338
- }
339
-
340
- /**
341
- * Checks whether the license status is active
342
- *
343
- * @return boolean True if license is active
344
- */
345
- public function license_is_valid() {
346
- return ( $this->get_license_status() === 'valid' );
347
- }
348
-
349
- /**
350
- * Get all license related options
351
- *
352
- * @return array Array of license options
353
- */
354
- protected function get_options() {
355
-
356
- // create option name
357
- $option_name = $this->prefix . 'license';
358
-
359
- // get array of options from db
360
- if ( $this->is_network_activated ) {
361
- $options = get_site_option( $option_name, array() );
362
- } else {
363
- $options = get_option( $option_name, array() );
364
- }
365
-
366
- // setup array of defaults
367
- $defaults = array(
368
- 'key' => '',
369
- 'status' => '',
370
- 'expiry_date' => ''
371
- );
372
-
373
- // merge options with defaults
374
- $this->options = wp_parse_args( $options, $defaults );
375
-
376
- return $this->options;
377
- }
378
-
379
- /**
380
- * Set license related options
381
- *
382
- * @param array $options Array of new license options
383
- */
384
- protected function set_options( array $options ) {
385
- // create option name
386
- $option_name = $this->prefix . 'license';
387
-
388
- // update db
389
- if ( $this->is_network_activated ) {
390
- update_site_option( $option_name, $options );
391
- } else {
392
- update_option( $option_name, $options );
393
- }
394
-
395
- }
396
-
397
- /**
398
- * Gets a license related option
399
- *
400
- * @param string $name The option name
401
- *
402
- * @return mixed The option value
403
- */
404
- protected function get_option( $name ) {
405
- $options = $this->get_options();
406
-
407
- return $options[$name];
408
- }
409
-
410
- /**
411
- * Set a license related option
412
- *
413
- * @param string $name The option name
414
- * @param mixed $value The option value
415
- */
416
- protected function set_option( $name, $value ) {
417
- // get options
418
- $options = $this->get_options();
419
-
420
- // update option
421
- $options[$name] = $value;
422
-
423
- // save options
424
- $this->set_options( $options );
425
- }
426
-
427
- public function show_license_form_heading() {
428
- ?>
429
- <h3>
430
- <?php printf( __( "%s: License Settings", $this->product->get_text_domain() ), $this->product->get_item_name() ); ?>&nbsp; &nbsp;
431
- </h3>
432
- <?php
433
- }
434
-
435
- /**
436
- * Show a form where users can enter their license key
437
- *
438
- * @param boolean $embedded Boolean indicating whether this form is embedded in another form?
439
- */
440
- public function show_license_form( $embedded = true ) {
441
- $key_name = $this->prefix . 'license_key';
442
- $nonce_name = $this->prefix . 'license_nonce';
443
- $action_name = $this->prefix . 'license_action';
444
-
445
- $api_host_available = $this->get_api_availability();
446
-
447
- $visible_license_key = $this->get_license_key();
448
-
449
- // obfuscate license key
450
- $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) );
451
-
452
- if ( $obfuscate ) {
453
- $visible_license_key = str_repeat( '*', strlen( $this->get_license_key() ) - 4 ) . substr( $this->get_license_key(), - 4 );
454
- }
455
-
456
- // make license key readonly when license key is valid or license is defined with a constant
457
- $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined );
458
-
459
- require dirname( __FILE__ ) . '/views/form.php';
460
-
461
- // enqueue script in the footer
462
- add_action( 'admin_footer', array( $this, 'output_script' ), 99 );
463
- }
464
-
465
- /**
466
- * Check if the license form has been submitted
467
- */
468
- public function catch_post_request() {
469
-
470
- $name = $this->prefix . 'license_key';
471
-
472
- // check if license key was posted and not empty
473
- if ( ! isset( $_POST[$name] ) ) {
474
- return;
475
- }
476
-
477
- // run a quick security check
478
- $nonce_name = $this->prefix . 'license_nonce';
479
-
480
- if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) {
481
- return;
482
- }
483
-
484
- // @TODO: check for user cap?
485
-
486
- // get key from posted value
487
- $license_key = $_POST[$name];
488
-
489
- // check if license key doesn't accidentally contain asterisks
490
- if ( strstr( $license_key, '*' ) === false ) {
491
-
492
- // sanitize key
493
- $license_key = trim( sanitize_key( $_POST[$name] ) );
494
-
495
- // save license key
496
- $this->set_license_key( $license_key );
497
- }
498
-
499
- // does user have an activated valid license
500
- if ( ! $this->license_is_valid() ) {
501
-
502
- // try to auto-activate license
503
- return $this->activate_license();
504
-
505
- }
506
-
507
- $action_name = $this->prefix . 'license_action';
508
-
509
- // was one of the action buttons clicked?
510
- if ( isset( $_POST[$action_name] ) ) {
511
-
512
- $action = trim( $_POST[$action_name] );
513
-
514
- switch ( $action ) {
515
-
516
- case 'activate':
517
- return $this->activate_license();
518
- break;
519
-
520
- case 'deactivate':
521
- return $this->deactivate_license();
522
- break;
523
- }
524
-
525
- }
526
-
527
- }
528
-
529
- /**
530
- * Output the script containing the MILicenseManager JS Object
531
- *
532
- * This takes care of disabling the 'activate' and 'deactivate' buttons
533
- */
534
- public function output_script() {
535
- require_once dirname( __FILE__ ) . '/views/script.php';
536
- }
537
-
538
- /**
539
- * Set the constant used to define the license
540
- *
541
- * @param string $license_constant_name The license constant name
542
- */
543
- public function set_license_constant_name( $license_constant_name ) {
544
- $this->license_constant_name = trim( $license_constant_name );
545
- $this->maybe_set_license_key_from_constant();
546
- }
547
-
548
- /**
549
- * Get the API availability information
550
- *
551
- * @return array
552
- */
553
- protected function get_api_availability(){
554
- return array(
555
- 'url' => $this->product->get_api_url(),
556
- 'availability' => $this->check_api_host_availability(),
557
- 'curl_version' => $this->get_curl_version(),
558
- );
559
- }
560
-
561
- /**
562
- * Check if the API host address is available from this server
563
- *
564
- * @return bool
565
- */
566
- private function check_api_host_availability() {
567
- $wp_http = new WP_Http();
568
- if ( $wp_http->block_request( $this->product->get_api_url() ) === false ) {
569
- return true;
570
- }
571
-
572
- return false;
573
- }
574
-
575
- /**
576
- * Get the current curl version, or false
577
- *
578
- * @return mixed
579
- */
580
- protected function get_curl_version() {
581
- if ( function_exists( 'curl_version' ) ) {
582
- $curl_version = curl_version();
583
-
584
- if ( isset( $curl_version['version'] ) ) {
585
- return $curl_version['version'];
586
- }
587
- }
588
-
589
- return false;
590
- }
591
-
592
- /**
593
- * Maybe set license key from a defined constant
594
- */
595
- private function maybe_set_license_key_from_constant() {
596
-
597
- if ( empty( $this->license_constant_name ) ) {
598
- // generate license constant name
599
- $this->set_license_constant_name( strtoupper( str_replace( array( ' ', '-' ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE' );
600
- }
601
-
602
- // set license key from constant
603
- if ( defined( $this->license_constant_name ) ) {
604
-
605
- $license_constant_value = constant( $this->license_constant_name );
606
-
607
- // update license key value with value of constant
608
- if ( $this->get_license_key() !== $license_constant_value ) {
609
- $this->set_license_key( $license_constant_value );
610
- }
611
-
612
- $this->license_constant_is_defined = true;
613
- }
614
- }
615
-
616
-
617
- }
618
-
619
- }
1
+ <?php
2
+
3
+ if ( ! interface_exists( 'iMI_License_Manager', false ) ) {
4
+
5
+ interface iMI_License_Manager {
6
+ public function specific_hooks();
7
+ public function setup_auto_updater();
8
+ }
9
+
10
+ }
11
+
12
+ if ( ! class_exists( 'MI_License_Manager', false ) ) {
13
+
14
+ /**
15
+ * Class MI_License_Manager
16
+ *
17
+ * @todo Maybe create a license class that contains key and option
18
+ * @todo Not sure if MI_License_Manager is a good name for this class, it's more managing the product (plugin or theme)
19
+ */
20
+ abstract class MI_License_Manager implements iMI_License_Manager {
21
+
22
+ /**
23
+ * @const VERSION The version number of the License_Manager class
24
+ */
25
+ const VERSION = 1;
26
+
27
+ /**
28
+ * @var MI_License The license
29
+ */
30
+ protected $product;
31
+
32
+ /**
33
+ * @var string
34
+ */
35
+ private $license_constant_name = '';
36
+
37
+ /**
38
+ * @var boolean True if license is defined with a constant
39
+ */
40
+ private $license_constant_is_defined = false;
41
+
42
+ /**
43
+ * @var boolean True if remote license activation just failed
44
+ */
45
+ private $remote_license_activation_failed = false;
46
+
47
+ /**
48
+ * @var array Array of license related options
49
+ */
50
+ private $options = array();
51
+
52
+ /**
53
+ * @var string Used to prefix ID's, option names, etc..
54
+ */
55
+ protected $prefix;
56
+
57
+ /**
58
+ * @var bool Boolean indicating whether this plugin is network activated
59
+ */
60
+ protected $is_network_activated = false;
61
+
62
+ /**
63
+ * Constructor
64
+ *
65
+ * @param MI_Product $product
66
+ */
67
+ public function __construct( MI_Product $product ) {
68
+
69
+ // Set the license
70
+ $this->product = $product;
71
+
72
+ // set prefix
73
+ $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' );
74
+
75
+ // maybe set license key from constant
76
+ $this->maybe_set_license_key_from_constant();
77
+ }
78
+
79
+ /**
80
+ * Setup hooks
81
+ *
82
+ */
83
+ public function setup_hooks() {
84
+
85
+ // show admin notice if license is not active
86
+ add_action( 'admin_notices', array( $this, 'display_admin_notices' ) );
87
+
88
+ // catch POST requests from license form
89
+ add_action( 'admin_init', array( $this, 'catch_post_request' ) );
90
+
91
+ // setup item type (plugin|theme) specific hooks
92
+ $this->specific_hooks();
93
+
94
+ // setup the auto updater
95
+ $this->setup_auto_updater();
96
+
97
+ }
98
+
99
+ /**
100
+ * Display license specific admin notices, namely:
101
+ *
102
+ * - License for the product isn't activated
103
+ * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL
104
+ */
105
+ public function display_admin_notices() {
106
+
107
+ if ( ! current_user_can( 'manage_options' ) ) {
108
+ return;
109
+ }
110
+
111
+ // show notice if license is invalid
112
+ if ( ! $this->license_is_valid() ) {
113
+ if ( $this->get_license_key() == '' ) {
114
+ $message = '<b>Warning!</b> You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! <a href="%s">Enter your license key</a> or <a href="%s" target="_blank">get a license here</a>.';
115
+ } else {
116
+ $message = '<b>Warning!</b> Your %s license is inactive which means you\'re missing out on updates and support! <a href="%s">Activate your license</a> or <a href="%s" target="_blank">get a license here</a>.';
117
+ }
118
+ ?>
119
+ <div class="error">
120
+ <p><?php printf( __( $message, $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?></p>
121
+ </div>
122
+ <?php
123
+ }
124
+
125
+ // show notice if external requests are blocked through the WP_HTTP_BLOCK_EXTERNAL constant
126
+ if ( defined( "WP_HTTP_BLOCK_EXTERNAL" ) && WP_HTTP_BLOCK_EXTERNAL === true ) {
127
+
128
+ // check if our API endpoint is in the allowed hosts
129
+ $host = parse_url( $this->product->get_api_url(), PHP_URL_HOST );
130
+
131
+ if ( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) {
132
+ ?>
133
+ <div class="error">
134
+ <p><?php printf( __( '<b>Warning!</b> You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '<strong>' . $host . '</strong>', '<code>WP_ACCESSIBLE_HOSTS</code>' ); ?></p>
135
+ </div>
136
+ <?php
137
+ }
138
+
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Set a notice to display in the admin area
144
+ *
145
+ * @param string $type error|updated
146
+ * @param string $message The message to display
147
+ */
148
+ protected function set_notice( $message, $success = true ) {
149
+ $css_class = ( $success ) ? 'updated' : 'error';
150
+ add_settings_error( $this->prefix . 'license', 'license-notice', $message, $css_class );
151
+ }
152
+
153
+ /**
154
+ * Remotely activate License
155
+ * @return boolean True if the license is now activated, false if not
156
+ */
157
+ public function activate_license() {
158
+
159
+ $result = $this->call_license_api( 'activate' );
160
+
161
+
162
+ if ( $result ) {
163
+
164
+ // story expiry date
165
+ if ( isset( $result->expires ) ) {
166
+ $this->set_license_expiry_date( $result->expires );
167
+ $expiry_date = strtotime( $result->expires );
168
+ } else {
169
+ $expiry_date = false;
170
+ }
171
+
172
+ // show success notice if license is valid
173
+ if ( $result->license === 'valid' ) {
174
+
175
+ $message = sprintf( __( "Your %s license has been activated. ", $this->product->get_text_domain() ), $this->product->get_item_name() );
176
+
177
+ // show a custom notice if users have an unlimited license
178
+ if ( $result->license_limit == 0 ) {
179
+ $message .= __( "You have an unlimited license. ", $this->product->get_text_domain() );
180
+ } else {
181
+ $message .= sprintf( __( "You have used %d/%d activations. ", $this->product->get_text_domain() ), $result->site_count, $result->license_limit );
182
+ }
183
+
184
+ // add upgrade notice if user has less than 3 activations left
185
+ if ( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) {
186
+ $message .= sprintf( __( '<a href="%s">Did you know you can upgrade your license?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-nearing-limit-notice' ) );
187
+ // add extend notice if license is expiring in less than 1 month
188
+ } elseif ( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) {
189
+ $days_left = round( ( $expiry_date - strtotime( "now" ) ) / 86400 );
190
+ $message .= sprintf( __( '<a href="%s">Your license is expiring in %d days, would you like to extend it?</a>', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expiring-notice' ), $days_left );
191
+ }
192
+
193
+ $this->set_notice( $message, true );
194
+
195
+ } else {
196
+
197
+ if ( isset( $result->error ) && $result->error === 'no_activations_left' ) {
198
+ // show notice if user is at their activation limit
199
+ $this->set_notice( sprintf( __( 'You\'ve reached your activation limit. You must <a href="%s">upgrade your license</a> to use it on this site.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-at-limit-notice' ) ), false );
200
+ } elseif ( isset( $result->error ) && $result->error == "expired" ) {
201
+ // show notice if the license is expired
202
+ $this->set_notice( sprintf( __( 'Your license has expired. You must <a href="%s">extend your license</a> in order to use it again.', $this->product->get_text_domain() ), $this->product->get_tracking_url( 'license-expired-notice' ) ), false );
203
+ } else {
204
+ // show a general notice if it's any other error
205
+ $this->set_notice( __( "Failed to activate your license, your license key seems to be invalid.", $this->product->get_text_domain() ), false );
206
+ }
207
+
208
+ $this->remote_license_activation_failed = true;
209
+ }
210
+
211
+ $this->set_license_status( $result->license );
212
+ }
213
+
214
+ return ( $this->license_is_valid() );
215
+ }
216
+
217
+ /**
218
+ * Remotely deactivate License
219
+ * @return boolean True if the license is now deactivated, false if not
220
+ */
221
+ public function deactivate_license() {
222
+
223
+ $result = $this->call_license_api( 'deactivate' );
224
+
225
+ if ( $result ) {
226
+
227
+ // show notice if license is deactivated
228
+ if ( $result->license === 'deactivated' ) {
229
+ $this->set_notice( sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ) );
230
+ } else {
231
+ $this->set_notice( sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ), false );
232
+ }
233
+
234
+ $this->set_license_status( $result->license );
235
+ }
236
+
237
+ return ( $this->get_license_status() === 'deactivated' );
238
+ }
239
+
240
+ /**
241
+ * @param string $action activate|deactivate
242
+ *
243
+ * @return mixed
244
+ */
245
+ protected function call_license_api( $action ) {
246
+
247
+ // don't make a request if license key is empty
248
+ if ( $this->get_license_key() === '' ) {
249
+ return false;
250
+ }
251
+
252
+ // data to send in our API request
253
+ $api_params = array(
254
+ 'edd_action' => $action . '_license',
255
+ 'license' => $this->get_license_key(),
256
+ 'item_name' => urlencode( trim( $this->product->get_item_name() ) ),
257
+ 'url' => get_option( 'home' ) // grab the URL straight from the option to prevent filters from breaking it.
258
+ );
259
+
260
+ // create api request url
261
+ $url = add_query_arg( $api_params, $this->product->get_api_url() );
262
+
263
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
264
+ $request = new MI_API_Request( $url );
265
+
266
+ if ( $request->is_valid() !== true ) {
267
+ $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '<a href="http://kb.yoast.com/article/13-license-activation-notices">', '</a>' ), false );
268
+ }
269
+
270
+ // get response
271
+ $response = $request->get_response();
272
+
273
+ // update license status
274
+ $license_data = $response;
275
+
276
+ return $license_data;
277
+ }
278
+
279
+
280
+ /**
281
+ * Set the license status
282
+ *
283
+ * @param string $license_status
284
+ */
285
+ public function set_license_status( $license_status ) {
286
+ $this->set_option( 'status', $license_status );
287
+ }
288
+
289
+ /**
290
+ * Get the license status
291
+ *
292
+ * @return string $license_status;
293
+ */
294
+ public function get_license_status() {
295
+ $license_status = $this->get_option( 'status' );
296
+
297
+ return trim( $license_status );
298
+ }
299
+
300
+ /**
301
+ * Set the license key
302
+ *
303
+ * @param string $license_key
304
+ */
305
+ public function set_license_key( $license_key ) {
306
+ $this->set_option( 'key', $license_key );
307
+ }
308
+
309
+ /**
310
+ * Gets the license key from constant or option
311
+ *
312
+ * @return string $license_key
313
+ */
314
+ public function get_license_key() {
315
+ $license_key = $this->get_option( 'key' );
316
+
317
+ return trim( $license_key );
318
+ }
319
+
320
+ /**
321
+ * Gets the license expiry date
322
+ *
323
+ * @return string
324
+ */
325
+ public function get_license_expiry_date() {
326
+ return $this->get_option( 'expiry_date' );
327
+ }
328
+
329
+ /**
330
+ * Stores the license expiry date
331
+ */
332
+ public function set_license_expiry_date( $expiry_date ) {
333
+ $this->set_option( 'expiry_date', $expiry_date );
334
+ }
335
+
336
+ /**
337
+ * Checks whether the license status is active
338
+ *
339
+ * @return boolean True if license is active
340
+ */
341
+ public function license_is_valid() {
342
+ return ( $this->get_license_status() === 'valid' );
343
+ }
344
+
345
+ /**
346
+ * Get all license related options
347
+ *
348
+ * @return array Array of license options
349
+ */
350
+ protected function get_options() {
351
+
352
+ // create option name
353
+ $option_name = $this->prefix . 'license';
354
+
355
+ // get array of options from db
356
+ if ( $this->is_network_activated ) {
357
+ $options = get_site_option( $option_name, array() );
358
+ } else {
359
+ $options = get_option( $option_name, array() );
360
+ }
361
+
362
+ // setup array of defaults
363
+ $defaults = array(
364
+ 'key' => '',
365
+ 'status' => '',
366
+ 'expiry_date' => ''
367
+ );
368
+
369
+ // merge options with defaults
370
+ $this->options = wp_parse_args( $options, $defaults );
371
+
372
+ return $this->options;
373
+ }
374
+
375
+ /**
376
+ * Set license related options
377
+ *
378
+ * @param array $options Array of new license options
379
+ */
380
+ protected function set_options( array $options ) {
381
+ // create option name
382
+ $option_name = $this->prefix . 'license';
383
+
384
+ // update db
385
+ if ( $this->is_network_activated ) {
386
+ update_site_option( $option_name, $options );
387
+ } else {
388
+ update_option( $option_name, $options );
389
+ }
390
+
391
+ }
392
+
393
+ /**
394
+ * Gets a license related option
395
+ *
396
+ * @param string $name The option name
397
+ *
398
+ * @return mixed The option value
399
+ */
400
+ protected function get_option( $name ) {
401
+ $options = $this->get_options();
402
+
403
+ return $options[$name];
404
+ }
405
+
406
+ /**
407
+ * Set a license related option
408
+ *
409
+ * @param string $name The option name
410
+ * @param mixed $value The option value
411
+ */
412
+ protected function set_option( $name, $value ) {
413
+ // get options
414
+ $options = $this->get_options();
415
+
416
+ // update option
417
+ $options[$name] = $value;
418
+
419
+ // save options
420
+ $this->set_options( $options );
421
+ }
422
+
423
+ public function show_license_form_heading() {
424
+ ?>
425
+ <h3>
426
+ <?php printf( __( "%s: License Settings", $this->product->get_text_domain() ), $this->product->get_item_name() ); ?>&nbsp; &nbsp;
427
+ </h3>
428
+ <?php
429
+ }
430
+
431
+ /**
432
+ * Show a form where users can enter their license key
433
+ *
434
+ * @param boolean $embedded Boolean indicating whether this form is embedded in another form?
435
+ */
436
+ public function show_license_form( $embedded = true ) {
437
+ $key_name = $this->prefix . 'license_key';
438
+ $nonce_name = $this->prefix . 'license_nonce';
439
+ $action_name = $this->prefix . 'license_action';
440
+
441
+ $api_host_available = $this->get_api_availability();
442
+
443
+ $visible_license_key = $this->get_license_key();
444
+
445
+ // obfuscate license key
446
+ $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) );
447
+
448
+ if ( $obfuscate ) {
449
+ $visible_license_key = str_repeat( '*', strlen( $this->get_license_key() ) - 4 ) . substr( $this->get_license_key(), - 4 );
450
+ }
451
+
452
+ // make license key readonly when license key is valid or license is defined with a constant
453
+ $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined );
454
+
455
+ require dirname( __FILE__ ) . '/views/form.php';
456
+
457
+ // enqueue script in the footer
458
+ add_action( 'admin_footer', array( $this, 'output_script' ), 99 );
459
+ }
460
+
461
+ /**
462
+ * Check if the license form has been submitted
463
+ */
464
+ public function catch_post_request() {
465
+
466
+ $name = $this->prefix . 'license_key';
467
+
468
+ // check if license key was posted and not empty
469
+ if ( ! isset( $_POST[$name] ) ) {
470
+ return;
471
+ }
472
+
473
+ // run a quick security check
474
+ $nonce_name = $this->prefix . 'license_nonce';
475
+
476
+ if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) {
477
+ return;
478
+ }
479
+
480
+ // @TODO: check for user cap?
481
+
482
+ // get key from posted value
483
+ $license_key = $_POST[$name];
484
+
485
+ // check if license key doesn't accidentally contain asterisks
486
+ if ( strstr( $license_key, '*' ) === false ) {
487
+
488
+ // sanitize key
489
+ $license_key = trim( sanitize_key( $_POST[$name] ) );
490
+
491
+ // save license key
492
+ $this->set_license_key( $license_key );
493
+ }
494
+
495
+ // does user have an activated valid license
496
+ if ( ! $this->license_is_valid() ) {
497
+
498
+ // try to auto-activate license
499
+ return $this->activate_license();
500
+
501
+ }
502
+
503
+ $action_name = $this->prefix . 'license_action';
504
+
505
+ // was one of the action buttons clicked?
506
+ if ( isset( $_POST[$action_name] ) ) {
507
+
508
+ $action = trim( $_POST[$action_name] );
509
+
510
+ switch ( $action ) {
511
+
512
+ case 'activate':
513
+ return $this->activate_license();
514
+ break;
515
+
516
+ case 'deactivate':
517
+ return $this->deactivate_license();
518
+ break;
519
+ }
520
+
521
+ }
522
+
523
+ }
524
+
525
+ /**
526
+ * Output the script containing the MILicenseManager JS Object
527
+ *
528
+ * This takes care of disabling the 'activate' and 'deactivate' buttons
529
+ */
530
+ public function output_script() {
531
+ require_once dirname( __FILE__ ) . '/views/script.php';
532
+ }
533
+
534
+ /**
535
+ * Set the constant used to define the license
536
+ *
537
+ * @param string $license_constant_name The license constant name
538
+ */
539
+ public function set_license_constant_name( $license_constant_name ) {
540
+ $this->license_constant_name = trim( $license_constant_name );
541
+ $this->maybe_set_license_key_from_constant();
542
+ }
543
+
544
+ /**
545
+ * Get the API availability information
546
+ *
547
+ * @return array
548
+ */
549
+ protected function get_api_availability(){
550
+ return array(
551
+ 'url' => $this->product->get_api_url(),
552
+ 'availability' => $this->check_api_host_availability(),
553
+ 'curl_version' => $this->get_curl_version(),
554
+ );
555
+ }
556
+
557
+ /**
558
+ * Check if the API host address is available from this server
559
+ *
560
+ * @return bool
561
+ */
562
+ private function check_api_host_availability() {
563
+ $wp_http = new WP_Http();
564
+ if ( $wp_http->block_request( $this->product->get_api_url() ) === false ) {
565
+ return true;
566
+ }
567
+
568
+ return false;
569
+ }
570
+
571
+ /**
572
+ * Get the current curl version, or false
573
+ *
574
+ * @return mixed
575
+ */
576
+ protected function get_curl_version() {
577
+ if ( function_exists( 'curl_version' ) ) {
578
+ $curl_version = curl_version();
579
+
580
+ if ( isset( $curl_version['version'] ) ) {
581
+ return $curl_version['version'];
582
+ }
583
+ }
584
+
585
+ return false;
586
+ }
587
+
588
+ /**
589
+ * Maybe set license key from a defined constant
590
+ */
591
+ private function maybe_set_license_key_from_constant() {
592
+
593
+ if ( empty( $this->license_constant_name ) ) {
594
+ // generate license constant name
595
+ $this->set_license_constant_name( strtoupper( str_replace( array( ' ', '-' ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE' );
596
+ }
597
+
598
+ // set license key from constant
599
+ if ( defined( $this->license_constant_name ) ) {
600
+
601
+ $license_constant_value = constant( $this->license_constant_name );
602
+
603
+ // update license key value with value of constant
604
+ if ( $this->get_license_key() !== $license_constant_value ) {
605
+ $this->set_license_key( $license_constant_value );
606
+ }
607
+
608
+ $this->license_constant_is_defined = true;
609
+ }
610
+ }
611
+ }
612
+
613
+ }
 
 
 
 
 
 
vendor/yoast/license-manager/class-plugin-license-manager.php CHANGED
@@ -1,90 +1,90 @@
1
- <?php
2
-
3
- if ( class_exists( 'MI_License_Manager' ) && ! class_exists( "MI_Plugin_License_Manager", false ) ) {
4
-
5
- class MI_Plugin_License_Manager extends MI_License_Manager {
6
-
7
- /**
8
- * Constructor
9
- *
10
- * @param MI_Product $product
11
- */
12
- public function __construct( MI_Product $product ) {
13
-
14
- parent::__construct( $product );
15
-
16
- // Check if plugin is network activated. We should use site(wide) options in that case.
17
- if( is_admin() && is_multisite() ) {
18
-
19
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
20
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
21
- }
22
-
23
- $this->is_network_activated = is_plugin_active_for_network( $product->get_slug() );
24
- }
25
- }
26
-
27
- /**
28
- * Setup auto updater for plugins
29
- */
30
- public function setup_auto_updater() {
31
- if ( $this->license_is_valid() ) {
32
- // setup auto updater
33
- require_once( dirname( __FILE__ ) . '/class-update-manager.php' );
34
- require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' );
35
- new MI_Plugin_Update_Manager( $this->product, $this );
36
- }
37
- }
38
-
39
- /**
40
- * Setup hooks
41
- */
42
- public function specific_hooks() {
43
-
44
- // deactivate the license remotely on plugin deactivation
45
- register_deactivation_hook( $this->product->get_slug(), array( $this, 'deactivate_license' ) );
46
- }
47
-
48
- /**
49
- * Show a form where users can enter their license key
50
- * Takes Multisites into account
51
- *
52
- * @param bool $embedded
53
- * @return null
54
- */
55
- public function show_license_form( $embedded = true ) {
56
-
57
- // For non-multisites, always show the license form
58
- if( ! is_multisite() ) {
59
- parent::show_license_form( $embedded );
60
- return;
61
- }
62
-
63
- // Plugin is network activated
64
- if( $this->is_network_activated ) {
65
-
66
- // We're on the network admin
67
- if( is_network_admin() ) {
68
- parent::show_license_form( $embedded );
69
- } else {
70
- // We're not in the network admin area, show a notice
71
- parent::show_license_form_heading();
72
- if ( is_super_admin() ) {
73
- echo "<p>" . sprintf( __( '%s is network activated, you can manage your license in the <a href="%s">network admin license page</a>.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "</p>";
74
- } else {
75
- echo "<p>" . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "</p>";
76
- }
77
-
78
- }
79
-
80
- } else {
81
-
82
- if( false == is_network_admin() ) {
83
- parent::show_license_form( $embedded );
84
- }
85
-
86
- }
87
- }
88
- }
89
- }
90
-
1
+ <?php
2
+
3
+ if ( class_exists( 'MI_License_Manager' ) && ! class_exists( "MI_Plugin_License_Manager", false ) ) {
4
+
5
+ class MI_Plugin_License_Manager extends MI_License_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param MI_Product $product
11
+ */
12
+ public function __construct( MI_Product $product ) {
13
+
14
+ parent::__construct( $product );
15
+
16
+ // Check if plugin is network activated. We should use site(wide) options in that case.
17
+ if( is_admin() && is_multisite() ) {
18
+
19
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
20
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
21
+ }
22
+
23
+ $this->is_network_activated = is_plugin_active_for_network( $product->get_file() );
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Setup auto updater for plugins
29
+ */
30
+ public function setup_auto_updater() {
31
+ if ( $this->license_is_valid() ) {
32
+ // setup auto updater
33
+ require_once( dirname( __FILE__ ) . '/class-update-manager.php' );
34
+ require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' );
35
+ new MI_Plugin_Update_Manager( $this->product, $this );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Setup hooks
41
+ */
42
+ public function specific_hooks() {
43
+
44
+ // deactivate the license remotely on plugin deactivation
45
+ register_deactivation_hook( $this->product->get_file(), array( $this, 'deactivate_license' ) );
46
+ }
47
+
48
+ /**
49
+ * Show a form where users can enter their license key
50
+ * Takes Multisites into account
51
+ *
52
+ * @param bool $embedded
53
+ * @return null
54
+ */
55
+ public function show_license_form( $embedded = true ) {
56
+
57
+ // For non-multisites, always show the license form
58
+ if( ! is_multisite() ) {
59
+ parent::show_license_form( $embedded );
60
+ return;
61
+ }
62
+
63
+ // Plugin is network activated
64
+ if( $this->is_network_activated ) {
65
+
66
+ // We're on the network admin
67
+ if( is_network_admin() ) {
68
+ parent::show_license_form( $embedded );
69
+ } else {
70
+ // We're not in the network admin area, show a notice
71
+ parent::show_license_form_heading();
72
+ if ( is_super_admin() ) {
73
+ echo "<p>" . sprintf( __( '%s is network activated, you can manage your license in the <a href="%s">network admin license page</a>.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "</p>";
74
+ } else {
75
+ echo "<p>" . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "</p>";
76
+ }
77
+
78
+ }
79
+
80
+ } else {
81
+
82
+ if( false == is_network_admin() ) {
83
+ parent::show_license_form( $embedded );
84
+ }
85
+
86
+ }
87
+ }
88
+ }
89
+
90
+ }
vendor/yoast/license-manager/class-plugin-update-manager.php CHANGED
@@ -1,102 +1,93 @@
1
- <?php
2
-
3
- //set_site_transient( 'update_plugins', null );
4
-
5
- if( class_exists( 'MI_Update_Manager' ) && ! class_exists( "MI_Plugin_Update_Manager", false ) ) {
6
-
7
- class MI_Plugin_Update_Manager extends MI_Update_Manager {
8
-
9
- /**
10
- * Constructor
11
- *
12
- * @param string $api_url
13
- * @param string $item_name
14
- * @param string $license_key
15
- * @param string $slug The path to the main plugin file, relative to plugins dir
16
- * @param string $version
17
- * @param string $author (optional)
18
- * @param string $text_domain
19
- */
20
- public function __construct( MI_Product $product, $license_key ) {
21
- parent::__construct( $product, $license_key );
22
-
23
- // setup hooks
24
- $this->setup_hooks();
25
-
26
- }
27
-
28
- /**
29
- * Setup hooks
30
- */
31
- private function setup_hooks() {
32
-
33
- // check for updates
34
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) );
35
-
36
- // get correct plugin information (when viewing details)
37
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
38
- }
39
-
40
- /**
41
- * Check for updates and if so, add to "updates available" data
42
- *
43
- * @param object $data
44
- * @return object $data
45
- */
46
- public function set_updates_available_data( $data ) {
47
-
48
- if ( empty( $data ) ) {
49
- return $data;
50
- }
51
-
52
- // send of API request to check for updates
53
- $remote_data = $this->get_remote_data();
54
-
55
- // did we get a response?
56
- if( $remote_data === false ) {
57
- return $data;
58
- }
59
-
60
- // compare local version with remote version
61
- if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) {
62
-
63
- // remote version is newer, add to data
64
- $data->response[ $this->product->get_slug() ] = $remote_data;
65
-
66
- }
67
-
68
- return $data;
69
- }
70
-
71
- /**
72
- * Gets new plugin version details (view version x.x.x details)
73
- *
74
- * @uses api_request()
75
- *
76
- * @param object $data
77
- * @param string $action
78
- * @param object $args (optional)
79
- *
80
- * @return object $data
81
- */
82
- public function plugins_api_filter( $data, $action = '', $args = null ) {
83
-
84
- // only do something if we're checking for our plugin
85
- if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) {
86
- return $data;
87
- }
88
-
89
- $api_response = $this->get_remote_data();
90
-
91
- // did we get a response?
92
- if ( $api_response === false ) {
93
- return $data;
94
- }
95
-
96
- // return api response
97
- return $api_response;
98
- }
99
-
100
- }
101
-
102
- }
1
+ <?php
2
+
3
+ if( class_exists( 'MI_Update_Manager' ) && ! class_exists( "MI_Plugin_Update_Manager", false ) ) {
4
+
5
+ class MI_Plugin_Update_Manager extends MI_Update_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param MI_Product $product The Product.
11
+ * @param string $license_key The License entered.
12
+ */
13
+ public function __construct( MI_Product $product, $license_key ) {
14
+ parent::__construct( $product, $license_key );
15
+
16
+ // setup hooks
17
+ $this->setup_hooks();
18
+ }
19
+
20
+ /**
21
+ * Setup hooks
22
+ */
23
+ private function setup_hooks() {
24
+
25
+ // check for updates
26
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) );
27
+
28
+ // get correct plugin information (when viewing details)
29
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
30
+ }
31
+
32
+ /**
33
+ * Check for updates and if so, add to "updates available" data
34
+ *
35
+ * @param object $data
36
+ * @return object $data
37
+ */
38
+ public function set_updates_available_data( $data ) {
39
+
40
+ if ( empty( $data ) ) {
41
+ return $data;
42
+ }
43
+
44
+ // send of API request to check for updates
45
+ $remote_data = $this->get_remote_data();
46
+
47
+ // did we get a response?
48
+ if( $remote_data === false ) {
49
+ return $data;
50
+ }
51
+
52
+ // compare local version with remote version
53
+ if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) {
54
+
55
+ // remote version is newer, add to data
56
+ $data->response[ $this->product->get_file() ] = $remote_data;
57
+
58
+ }
59
+
60
+ return $data;
61
+ }
62
+
63
+ /**
64
+ * Gets new plugin version details (view version x.x.x details)
65
+ *
66
+ * @uses api_request()
67
+ *
68
+ * @param object $data
69
+ * @param string $action
70
+ * @param object $args (optional)
71
+ *
72
+ * @return object $data
73
+ */
74
+ public function plugins_api_filter( $data, $action = '', $args = null ) {
75
+
76
+ // only do something if we're checking for our plugin
77
+ if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) {
78
+ return $data;
79
+ }
80
+
81
+ $api_response = $this->get_remote_data();
82
+
83
+ // did we get a response?
84
+ if ( $api_response === false ) {
85
+ return $data;
86
+ }
87
+
88
+ // return api response
89
+ return $api_response;
90
+ }
91
+ }
92
+
93
+ }
 
 
 
 
 
 
 
 
 
vendor/yoast/license-manager/class-product.php CHANGED
@@ -1,228 +1,292 @@
1
- <?php
2
-
3
- if( ! class_exists( "MI_Product", false ) ) {
4
-
5
- /**
6
- * Class MI_Product
7
- *
8
- * @todo create a license class and store an object of it in this class
9
- */
10
- class MI_Product {
11
-
12
- /**
13
- * @var string The URL of the shop running the EDD API.
14
- */
15
- protected $api_url;
16
-
17
- /**
18
- * @var string The item name in the EDD shop.
19
- */
20
- protected $item_name;
21
-
22
- /**
23
- * @var string The theme slug or plugin file
24
- */
25
- protected $slug;
26
-
27
- /**
28
- * @var string The version number of the item
29
- */
30
- protected $version;
31
-
32
- /**
33
- * @var string The absolute url on which users can purchase a license
34
- */
35
- protected $item_url;
36
-
37
- /**
38
- * @var string Absolute admin URL on which users can enter their license key.
39
- */
40
- protected $license_page_url;
41
-
42
- /**
43
- * @var string The text domain used for translating strings
44
- */
45
- protected $text_domain;
46
-
47
- /**
48
- * @var string The item author
49
- */
50
- protected $author;
51
-
52
- public function __construct( $api_url, $item_name, $slug, $version, $item_url = '', $license_page_url = '#', $text_domain = 'yoast', $author = 'Yoast' ) {
53
- $this->api_url = $api_url;
54
- $this->item_name = $item_name;
55
- $this->slug = $slug;
56
- $this->version = $version;
57
- $this->item_url = $item_url;
58
- $this->license_page_url = admin_url( $license_page_url );
59
- $this->text_domain = $text_domain;
60
- $this->author = $author;
61
-
62
- // Fix possible empty item url
63
- if ( $this->item_url === '' ) {
64
- $this->item_url = $this->api_url;
65
- }
66
-
67
- if( is_admin() && is_multisite() ) {
68
-
69
- if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
70
- require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
71
- }
72
-
73
- if( is_plugin_active_for_network( $slug ) ) {
74
- $this->license_page_url = network_admin_url( $license_page_url );
75
- }
76
- }
77
- }
78
-
79
-
80
- /**
81
- * @param string $api_url
82
- */
83
- public function set_api_url( $api_url ) {
84
- $this->api_url = $api_url;
85
- }
86
-
87
- /**
88
- * @return string
89
- */
90
- public function get_api_url() {
91
- return $this->api_url;
92
- }
93
-
94
- /**
95
- * @param string $author
96
- */
97
- public function set_author( $author ) {
98
- $this->author = $author;
99
- }
100
-
101
- /**
102
- * @return string
103
- */
104
- public function get_author() {
105
- return $this->author;
106
- }
107
-
108
- /**
109
- * @param string $item_name
110
- */
111
- public function set_item_name( $item_name ) {
112
- $this->item_name = $item_name;
113
- }
114
-
115
- /**
116
- * @return string
117
- */
118
- public function get_item_name() {
119
- return $this->item_name;
120
- }
121
-
122
- /**
123
- * @param string $item_url
124
- */
125
- public function set_item_url( $item_url ) {
126
- $this->item_url = $item_url;
127
- }
128
-
129
- /**
130
- * @return string
131
- */
132
- public function get_item_url() {
133
- return $this->item_url;
134
- }
135
-
136
- /**
137
- * @param string $license_page_url
138
- */
139
- public function set_license_page_url( $license_page_url ) {
140
- $this->license_page_url = admin_page( $license_page_url );
141
- }
142
-
143
- /**
144
- * @return string
145
- */
146
- public function get_license_page_url() {
147
- return $this->license_page_url;
148
- }
149
-
150
- /**
151
- * @param string $slug
152
- */
153
- public function set_slug( $slug ) {
154
- $this->slug = $slug;
155
- }
156
-
157
- /**
158
- * @return string
159
- */
160
- public function get_slug() {
161
- return $this->slug;
162
- }
163
-
164
- /**
165
- * Returns the dirname of the slug and limits it to 15 chars
166
- *
167
- * @return string
168
- */
169
- public function get_transient_prefix() {
170
- return substr( dirname( $this->slug ), 0, 15 );
171
- }
172
-
173
- /**
174
- * @param string $text_domain
175
- */
176
- public function set_text_domain( $text_domain ) {
177
- $this->text_domain = $text_domain;
178
- }
179
-
180
- /**
181
- * @return string
182
- */
183
- public function get_text_domain() {
184
- return $this->text_domain;
185
- }
186
-
187
- /**
188
- * @param string $version
189
- */
190
- public function set_version( $version ) {
191
- $this->version = $version;
192
- }
193
-
194
- /**
195
- * @return string
196
- */
197
- public function get_version() {
198
- return $this->version;
199
- }
200
-
201
- /**
202
- * Gets a Google Analytics Campaign url for this product
203
- *
204
- * @param string $link_identifier
205
- * @return string The full URL
206
- */
207
- public function get_tracking_url( $link_identifier = '' ) {
208
-
209
- $tracking_vars = array(
210
- 'utm_campaign' => $this->get_item_name() . ' licensing',
211
- 'utm_medium' => 'link',
212
- 'utm_source' => $this->get_item_name(),
213
- 'utm_content' => $link_identifier
214
- );
215
-
216
- // url encode tracking vars
217
- $tracking_vars = urlencode_deep( $tracking_vars );
218
-
219
- $query_string = build_query( $tracking_vars );
220
-
221
-
222
- return $this->get_item_url() . '#' . $query_string;
223
- }
224
-
225
- }
226
-
227
- }
228
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( "MI_Product", false ) ) {
4
+
5
+ /**
6
+ * Class MI_Product
7
+ *
8
+ * @todo create a license class and store an object of it in this class
9
+ */
10
+ class MI_Product {
11
+
12
+ /**
13
+ * @var string The URL of the shop running the EDD API.
14
+ */
15
+ protected $api_url;
16
+
17
+ /**
18
+ * @var string The item name in the EDD shop.
19
+ */
20
+ protected $item_name;
21
+
22
+ /**
23
+ * @var string The theme slug or plugin file
24
+ */
25
+ protected $slug;
26
+
27
+ /**
28
+ * @var string The version number of the item
29
+ */
30
+ protected $version;
31
+
32
+ /**
33
+ * @var string The absolute url on which users can purchase a license
34
+ */
35
+ protected $item_url;
36
+
37
+ /**
38
+ * @var string Absolute admin URL on which users can enter their license key.
39
+ */
40
+ protected $license_page_url;
41
+
42
+ /**
43
+ * @var string The text domain used for translating strings
44
+ */
45
+ protected $text_domain;
46
+
47
+ /**
48
+ * @var string The item author
49
+ */
50
+ protected $author;
51
+
52
+ /**
53
+ * @var string Relative file path to the plugin.
54
+ */
55
+ protected $file;
56
+
57
+ /** @var int Product ID in backend system for quick lookup */
58
+ protected $product_id;
59
+
60
+ /**
61
+ * MI_Product constructor.
62
+ *
63
+ * @param string $api_url The URL of the shop running the EDD API.
64
+ * @param string $item_name The item name in the EDD shop.
65
+ * @param string $slug The slug of the plugin, for shiny updates this needs to be a valid HTML id.
66
+ * @param string $version The version number of the item.
67
+ * @param string $item_url The absolute url on which users can purchase a license.
68
+ * @param string $license_page_url Absolute admin URL on which users can enter their license key.
69
+ * @param string $text_domain The text domain used for translating strings.
70
+ * @param string $author The item author.
71
+ * @param string $file The relative file path to the plugin.
72
+ * @param int $product_id The ID of the product in the backend system.
73
+ */
74
+ public function __construct( $api_url, $item_name, $slug, $version, $item_url = '', $license_page_url = '#', $text_domain = 'yoast', $author = 'MI', $file = '', $product_id = 0 ) {
75
+ $this->set_api_url( $api_url );
76
+ $this->set_item_name( $item_name );
77
+ $this->set_slug( $slug );
78
+ $this->set_version( $version );
79
+ $this->set_item_url( $item_url );
80
+ $this->set_license_page_url( $license_page_url );
81
+ $this->set_text_domain( $text_domain );
82
+ $this->set_author( $author );
83
+ $this->set_file( $file );
84
+ $this->set_product_id( $product_id );
85
+ }
86
+
87
+ /**
88
+ * @param string $api_url
89
+ */
90
+ public function set_api_url( $api_url ) {
91
+ $this->api_url = $api_url;
92
+ }
93
+
94
+ /**
95
+ * @return string
96
+ */
97
+ public function get_api_url() {
98
+ return $this->api_url;
99
+ }
100
+
101
+ /**
102
+ * @param string $author
103
+ */
104
+ public function set_author( $author ) {
105
+ $this->author = $author;
106
+ }
107
+
108
+ /**
109
+ * @return string
110
+ */
111
+ public function get_author() {
112
+ return $this->author;
113
+ }
114
+
115
+ /**
116
+ * @param string $item_name
117
+ */
118
+ public function set_item_name( $item_name ) {
119
+ $this->item_name = $item_name;
120
+ }
121
+
122
+ /**
123
+ * @return string
124
+ */
125
+ public function get_item_name() {
126
+ return $this->item_name;
127
+ }
128
+
129
+ /**
130
+ * @param string $item_url
131
+ */
132
+ public function set_item_url( $item_url ) {
133
+ if ( empty( $item_url ) ) {
134
+ $item_url = $this->api_url;
135
+ }
136
+
137
+ $this->item_url = $item_url;
138
+ }
139
+
140
+ /**
141
+ * @return string
142
+ */
143
+ public function get_item_url() {
144
+ return $this->item_url;
145
+ }
146
+
147
+ /**
148
+ * @param string $license_page_url
149
+ */
150
+ public function set_license_page_url( $license_page_url ) {
151
+
152
+ if ( is_admin() && is_multisite() ) {
153
+
154
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
155
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
156
+ }
157
+
158
+ if ( is_plugin_active_for_network( $this->get_slug() ) ) {
159
+ $this->license_page_url = network_admin_url( $license_page_url );
160
+
161
+ return;
162
+ }
163
+ }
164
+
165
+ $this->license_page_url = admin_url( $license_page_url );
166
+ }
167
+
168
+ /**
169
+ * @return string
170
+ */
171
+ public function get_license_page_url() {
172
+ return $this->license_page_url;
173
+ }
174
+
175
+ /**
176
+ * @param string $slug
177
+ */
178
+ public function set_slug( $slug ) {
179
+ $this->slug = $slug;
180
+ }
181
+
182
+ /**
183
+ * @return string
184
+ */
185
+ public function get_slug() {
186
+ return $this->slug;
187
+ }
188
+
189
+ /**
190
+ * Returns the dirname of the slug and limits it to 15 chars
191
+ *
192
+ * @return string
193
+ */
194
+ public function get_transient_prefix() {
195
+ return substr( md5( $this->file ), 0, 15 );
196
+ }
197
+
198
+ /**
199
+ * @param string $text_domain
200
+ */
201
+ public function set_text_domain( $text_domain ) {
202
+ $this->text_domain = $text_domain;
203
+ }
204
+
205
+ /**
206
+ * @return string
207
+ */
208
+ public function get_text_domain() {
209
+ return $this->text_domain;
210
+ }
211
+
212
+ /**
213
+ * @param string $version
214
+ */
215
+ public function set_version( $version ) {
216
+ $this->version = $version;
217
+ }
218
+
219
+ /**
220
+ * @return string
221
+ */
222
+ public function get_version() {
223
+ return $this->version;
224
+ }
225
+
226
+ /**
227
+ * Returns the file path relative to the plugins folder
228
+ *
229
+ * @return string
230
+ */
231
+ public function get_file() {
232
+ /*
233
+ * Fall back to the slug for BC reasons.
234
+ *
235
+ * We used to pass the file to the slug field, but this isn't supported with the shiny updates in WordPress.
236
+ * WordPress uses the slug in the HTML as an ID and a slash isn't a valid
237
+ */
238
+ return empty( $this->file ) ? $this->slug : $this->file;
239
+ }
240
+
241
+ /**
242
+ * Sets the file path relative to the plugins folder
243
+ *
244
+ * @param string $file Relative file path to the plugin.
245
+ */
246
+ public function set_file( $file ) {
247
+ $this->file = $file;
248
+ }
249
+
250
+ /**
251
+ * Return the Product ID
252
+ *
253
+ * @return int
254
+ */
255
+ public function get_product_id() {
256
+ return $this->product_id;
257
+ }
258
+
259
+ /**
260
+ * Set the product ID
261
+ *
262
+ * @param int $product_id Product ID to set.
263
+ */
264
+ public function set_product_id( $product_id ) {
265
+ $this->product_id = (int) $product_id;
266
+ }
267
+
268
+ /**
269
+ * Gets a Google Analytics Campaign url for this product
270
+ *
271
+ * @param string $link_identifier
272
+ *
273
+ * @return string The full URL
274
+ */
275
+ public function get_tracking_url( $link_identifier = '' ) {
276
+
277
+ $tracking_vars = array(
278
+ 'utm_campaign' => $this->get_item_name() . ' licensing',
279
+ 'utm_medium' => 'link',
280
+ 'utm_source' => $this->get_item_name(),
281
+ 'utm_content' => $link_identifier
282
+ );
283
+
284
+ // URL encode tracking vars.
285
+ $tracking_vars = urlencode_deep( $tracking_vars );
286
+ $query_string = build_query( $tracking_vars );
287
+
288
+ return $this->get_item_url() . '#' . $query_string;
289
+ }
290
+ }
291
+
292
+ }
vendor/yoast/license-manager/class-theme-license-manager.php CHANGED
@@ -1,53 +1,51 @@
1
- <?php
2
-
3
- if( class_exists( 'MI_License_Manager' ) && ! class_exists( "MI_Theme_License_Manager", false ) ) {
4
-
5
- class MI_Theme_License_Manager extends MI_License_Manager {
6
-
7
- /**
8
- * Setup auto updater for themes
9
- */
10
- public function setup_auto_updater() {
11
- if ( $this->license_is_valid() ) {
12
- // setup auto updater
13
- require_once dirname( __FILE__ ) . '/class-update-manager.php';
14
- require_once dirname( __FILE__ ) . '/class-theme-update-manager.php'; // @TODO: Autoload?
15
- new MI_Theme_Update_Manager( $this->product, $this );
16
- }
17
- }
18
-
19
- /**
20
- * Setup hooks
21
- */
22
- public function specific_hooks() {
23
- // remotely deactivate license upon switching away from this theme
24
- add_action( 'switch_theme', array( $this, 'deactivate_license' ) );
25
-
26
- // Add the license menu
27
- add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
28
- }
29
-
30
- /**
31
- * Add license page and add it to Themes menu
32
- */
33
- public function add_license_menu() {
34
- $theme_page = add_theme_page( sprintf( __( '%s License', $this->product->get_text_domain() ), $this->product->get_item_name() ), __( 'Theme License', $this->product->get_text_domain() ), 'manage_options', 'theme-license', array( $this, 'show_license_page' ) );
35
- }
36
-
37
- /**
38
- * Shows license page
39
- */
40
- public function show_license_page() {
41
- ?>
42
- <div class="wrap">
43
- <?php settings_errors(); ?>
44
-
45
- <?php $this->show_license_form( false ); ?>
46
- </div>
47
- <?php
48
- }
49
-
50
-
51
- }
52
-
53
- }
1
+ <?php
2
+
3
+ if ( class_exists( 'MI_License_Manager' ) && ! class_exists( "MI_Theme_License_Manager", false ) ) {
4
+
5
+ class MI_Theme_License_Manager extends MI_License_Manager {
6
+
7
+ /**
8
+ * Setup auto updater for themes
9
+ */
10
+ public function setup_auto_updater() {
11
+ if ( $this->license_is_valid() ) {
12
+ // setup auto updater
13
+ require_once dirname( __FILE__ ) . '/class-update-manager.php';
14
+ require_once dirname( __FILE__ ) . '/class-theme-update-manager.php'; // @TODO: Autoload?
15
+ new MI_Theme_Update_Manager( $this->product, $this );
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Setup hooks
21
+ */
22
+ public function specific_hooks() {
23
+ // remotely deactivate license upon switching away from this theme
24
+ add_action( 'switch_theme', array( $this, 'deactivate_license' ) );
25
+
26
+ // Add the license menu
27
+ add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
28
+ }
29
+
30
+ /**
31
+ * Add license page and add it to Themes menu
32
+ */
33
+ public function add_license_menu() {
34
+ add_theme_page( sprintf( __( '%s License', $this->product->get_text_domain() ), $this->product->get_item_name() ), __( 'Theme License', $this->product->get_text_domain() ), 'manage_options', 'theme-license', array( $this, 'show_license_page' ) );
35
+ }
36
+
37
+ /**
38
+ * Shows license page
39
+ */
40
+ public function show_license_page() {
41
+ ?>
42
+ <div class="wrap">
43
+ <?php settings_errors(); ?>
44
+
45
+ <?php $this->show_license_form( false ); ?>
46
+ </div>
47
+ <?php
48
+ }
49
+ }
50
+
51
+ }
 
 
vendor/yoast/license-manager/class-theme-update-manager.php CHANGED
@@ -1,149 +1,141 @@
1
- <?php
2
-
3
- if( class_exists( 'MI_Update_Manager' ) && ! class_exists( "MI_Theme_Update_Manager", false ) ) {
4
-
5
- class MI_Theme_Update_Manager extends MI_Update_Manager {
6
-
7
- /**
8
- * Constructor
9
- *
10
- * @param string $api_url
11
- * @param string $item_name
12
- * @param string $license_key
13
- * @param string $slug
14
- * @param string $theme_version
15
- * @param string $author (optional)
16
- */
17
- public function __construct( MI_Product $product, $license_key ) {
18
-
19
- parent::__construct( $product, $license_key );
20
-
21
- // setup hooks
22
- $this->setup_hooks();
23
- }
24
-
25
- /**
26
- * Get the current theme version
27
- *
28
- * @return string The version number
29
- */
30
- private function get_theme_version() {
31
-
32
- // if version was not set, get it from the Theme stylesheet
33
- if( $this->product->get_version() === '' ) {
34
- $theme = wp_get_theme( $this->product->get_slug() );
35
- return $theme->get( 'Version' );
36
- }
37
-
38
- return $this->product->get_version();
39
- }
40
-
41
- /**
42
- * Setup hooks
43
- */
44
- private function setup_hooks() {
45
- add_filter( 'site_transient_update_themes', array( $this, 'set_theme_update_transient' ) );
46
- add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) );
47
- }
48
-
49
- /**
50
- * Set "updates available" transient
51
- */
52
- public function set_theme_update_transient( $value ) {
53
-
54
- $update_data = $this->get_update_data();
55
-
56
- if( $update_data === false ) {
57
- return $value;
58
- }
59
-
60
- // add update data to "updates available" array. convert object to array.
61
- $value->response[ $this->product->get_slug() ] = (array) $update_data;
62
-
63
- return $value;
64
- }
65
-
66
- /**
67
- * Add hooks and scripts to the Appearance > Themes screen
68
- */
69
- public function load_themes_screen() {
70
-
71
- $update_data = $this->get_update_data();
72
-
73
- // only do if an update is available
74
- if( $update_data === false ) {
75
- return;
76
- }
77
-
78
- add_thickbox();
79
- add_action( 'admin_notices', array( $this, 'show_update_details' ) );
80
- }
81
-
82
- /**
83
- * Show update link.
84
- * Opens Thickbox with Changelog.
85
- */
86
- public function show_update_details() {
87
-
88
- $update_data = $this->get_update_data();
89
-
90
- // only show if an update is available
91
- if( $update_data === false ) {
92
- return;
93
- }
94
-
95
- $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
96
- $update_onclick = ' onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update." ) ) . '\') ) {return true;}return false;"';
97
- ?>
98
- <div id="update-nag">
99
- <?php
100
- printf(
101
- __( '<strong>%s version %s</strong> is available. <a href="%s" class="thickbox" title="%s">Check out what\'s new</a> or <a href="%s" %s>update now</a>.' ),
102
- $this->product->get_item_name(),
103
- $update_data->new_version,
104
- '#TB_inline?width=640&amp;inlineId=' . $this->product->get_slug() . '_changelog',
105
- $this->get_item_name(),
106
- $update_url,
107
- $update_onclick
108
- );
109
- ?>
110
- </div>
111
- <div id="<?php echo $this->product->get_slug(); ?>_changelog" style="display: none;">
112
- <?php echo wpautop( $update_data->sections['changelog'] ); ?>
113
- </div>
114
- <?php
115
- }
116
-
117
-
118
- /**
119
- * Get update data
120
- *
121
- * This gets the update data from a transient (12 hours), if set.
122
- * If not, it will make a remote request and get the update data.
123
- *
124
- * @return object $update_data Object containing the update data
125
- */
126
- public function get_update_data() {
127
-
128
- $api_response = $this->get_remote_data();
129
-
130
- if( false === $api_response ) {
131
- return false;
132
- }
133
-
134
- $update_data = $api_response;
135
-
136
- // check if a new version is available.
137
- if ( version_compare( $this->get_theme_version(), $update_data->new_version, '>=' ) ) {
138
- return false;
139
- }
140
-
141
-
142
- // an update is available
143
- return $update_data;
144
- }
145
-
146
-
147
- }
148
-
149
- }
1
+ <?php
2
+
3
+ if ( class_exists( 'MI_Update_Manager' ) && ! class_exists( 'MI_Theme_Update_Manager', false ) ) {
4
+
5
+ class MI_Theme_Update_Manager extends MI_Update_Manager {
6
+
7
+ /**
8
+ * Constructor
9
+ *
10
+ * @param MI_Product $product The Product.
11
+ * @param string $license_key The License key.
12
+ */
13
+ public function __construct( MI_Product $product, $license_key ) {
14
+ parent::__construct( $product, $license_key );
15
+
16
+ // setup hooks
17
+ $this->setup_hooks();
18
+ }
19
+
20
+ /**
21
+ * Get the current theme version
22
+ *
23
+ * @return string The version number
24
+ */
25
+ private function get_theme_version() {
26
+
27
+ // if version was not set, get it from the Theme stylesheet
28
+ if ( $this->product->get_version() === '' ) {
29
+ $theme = wp_get_theme( $this->product->get_slug() );
30
+
31
+ return $theme->get( 'Version' );
32
+ }
33
+
34
+ return $this->product->get_version();
35
+ }
36
+
37
+ /**
38
+ * Setup hooks
39
+ */
40
+ private function setup_hooks() {
41
+ add_filter( 'site_transient_update_themes', array( $this, 'set_theme_update_transient' ) );
42
+ add_action( 'load-themes.php', array( $this, 'load_themes_screen' ) );
43
+ }
44
+
45
+ /**
46
+ * Set "updates available" transient
47
+ */
48
+ public function set_theme_update_transient( $value ) {
49
+
50
+ $update_data = $this->get_update_data();
51
+
52
+ if ( $update_data === false ) {
53
+ return $value;
54
+ }
55
+
56
+ // add update data to "updates available" array. convert object to array.
57
+ $value->response[ $this->product->get_slug() ] = (array) $update_data;
58
+
59
+ return $value;
60
+ }
61
+
62
+ /**
63
+ * Add hooks and scripts to the Appearance > Themes screen
64
+ */
65
+ public function load_themes_screen() {
66
+
67
+ $update_data = $this->get_update_data();
68
+
69
+ // only do if an update is available
70
+ if ( $update_data === false ) {
71
+ return;
72
+ }
73
+
74
+ add_thickbox();
75
+ add_action( 'admin_notices', array( $this, 'show_update_details' ) );
76
+ }
77
+
78
+ /**
79
+ * Show update link.
80
+ * Opens Thickbox with Changelog.
81
+ */
82
+ public function show_update_details() {
83
+
84
+ $update_data = $this->get_update_data();
85
+
86
+ // only show if an update is available
87
+ if ( $update_data === false ) {
88
+ return;
89
+ }
90
+
91
+ $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
92
+ $update_onclick = ' onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update." ) ) . '\') ) {return true;}return false;"';
93
+ ?>
94
+ <div id="update-nag">
95
+ <?php
96
+ printf(
97
+ __( '<strong>%s version %s</strong> is available. <a href="%s" class="thickbox" title="%s">Check out what\'s new</a> or <a href="%s" %s>update now</a>.' ),
98
+ $this->product->get_item_name(),
99
+ $update_data->new_version,
100
+ '#TB_inline?width=640&amp;inlineId=' . $this->product->get_slug() . '_changelog',
101
+ $this->get_item_name(),
102
+ $update_url,
103
+ $update_onclick
104
+ );
105
+ ?>
106
+ </div>
107
+ <div id="<?php echo $this->product->get_slug(); ?>_changelog" style="display: none;">
108
+ <?php echo wpautop( $update_data->sections['changelog'] ); ?>
109
+ </div>
110
+ <?php
111
+ }
112
+
113
+ /**
114
+ * Get update data
115
+ *
116
+ * This gets the update data from a transient (12 hours), if set.
117
+ * If not, it will make a remote request and get the update data.
118
+ *
119
+ * @return object $update_data Object containing the update data
120
+ */
121
+ public function get_update_data() {
122
+
123
+ $api_response = $this->get_remote_data();
124
+
125
+ if ( false === $api_response ) {
126
+ return false;
127
+ }
128
+
129
+ $update_data = $api_response;
130
+
131
+ // check if a new version is available.
132
+ if ( version_compare( $this->get_theme_version(), $update_data->new_version, '>=' ) ) {
133
+ return false;
134
+ }
135
+
136
+ // an update is available
137
+ return $update_data;
138
+ }
139
+ }
140
+
141
+ }
 
 
 
 
 
 
 
 
vendor/yoast/license-manager/class-update-manager.php CHANGED
@@ -1,211 +1,216 @@
1
- <?php
2
-
3
- if( ! class_exists( "MI_Update_Manager", false ) ) {
4
-
5
- class MI_Update_Manager {
6
-
7
- /**
8
- * @var MI_Product
9
- */
10
- protected $product;
11
-
12
- /**
13
- * @var MI_License_Manager
14
- */
15
- protected $license_manager;
16
-
17
- /**
18
- * @var string
19
- */
20
- protected $error_message = '';
21
-
22
- /**
23
- * @var object
24
- */
25
- protected $update_response = null;
26
-
27
- /**
28
- * @var string The transient name storing the API response
29
- */
30
- private $response_transient_key = '';
31
-
32
- /**
33
- * @var string The transient name that stores failed request tries
34
- */
35
- private $request_failed_transient_key = '';
36
-
37
- /**
38
- * Constructor
39
- *
40
- * @param string $api_url The url to the EDD shop
41
- * @param string $item_name The item name in the EDD shop
42
- * @param string $license_key The (valid) license key
43
- * @param string $slug The slug. This is either the plugin main file path or the theme slug.
44
- * @param string $version The current plugin or theme version
45
- * @param string $author (optional) The item author.
46
- */
47
- public function __construct( MI_Product $product, $license_manager ) {
48
- $this->product = $product;
49
- $this->license_manager = $license_manager;
50
-
51
- // generate transient names
52
- $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
53
- $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
54
-
55
- // maybe delete transient
56
- $this->maybe_delete_transients();
57
- }
58
-
59
- /**
60
- * Deletes the various transients
61
- * If we're on the update-core.php?force-check=1 page
62
- */
63
- private function maybe_delete_transients() {
64
- global $pagenow;
65
-
66
- if( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
67
- delete_transient( $this->response_transient_key );
68
- delete_transient( $this->request_failed_transient_key );
69
- }
70
- }
71
-
72
- /**
73
- * If the update check returned a WP_Error, show it to the user
74
- */
75
- public function show_update_error() {
76
-
77
- if ( $this->error_message === '' ) {
78
- return;
79
- }
80
-
81
- ?>
82
- <div class="error">
83
- <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
84
- </div>
85
- <?php
86
- }
87
-
88
- /**
89
- * Calls the API and, if successfull, returns the object delivered by the API.
90
- *
91
- * @uses get_bloginfo()
92
- * @uses wp_remote_post()
93
- * @uses is_wp_error()
94
- *
95
- * @return false||object
96
- */
97
- private function call_remote_api() {
98
-
99
- // only check if the failed transient is not set (or if it's expired)
100
- if( get_transient( $this->request_failed_transient_key ) !== false ) {
101
- return false;
102
- }
103
-
104
- // start request process
105
- global $wp_version;
106
-
107
- // set a transient to prevent failed update checks on every page load
108
- // this transient will be removed if a request succeeds
109
- set_transient( $this->request_failed_transient_key, 'failed', 10800 );
110
-
111
- // setup api parameters
112
- $api_params = array(
113
- 'edd_action' => 'get_version',
114
- 'license' => $this->license_manager->get_license_key(),
115
- 'item_name' => $this->product->get_item_name(),
116
- 'wp_version' => $wp_version,
117
- 'item_version' => $this->product->get_version(),
118
- 'url' => home_url(),
119
- 'slug' => $this->product->get_slug()
120
- );
121
-
122
- // setup request parameters
123
- $request_params = array(
124
- 'method' => 'POST',
125
- 'body' => $api_params
126
- );
127
-
128
- require_once dirname( __FILE__ ) . '/class-api-request.php';
129
- $request = new MI_API_Request( $this->product->get_api_url(), $request_params );
130
-
131
- if( $request->is_valid() !== true ) {
132
-
133
- // show error message
134
- $this->error_message = $request->get_error_message();
135
- add_action( 'admin_notices', array( $this, 'show_update_error' ) );
136
-
137
- return false;
138
- }
139
-
140
- // request succeeded, delete transient indicating a request failed
141
- delete_transient( $this->request_failed_transient_key );
142
-
143
- // decode response
144
- $response = $request->get_response();
145
-
146
- // check if response returned that a given site was inactive
147
- if( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
148
-
149
- // deactivate local license
150
- $this->license_manager->set_license_status( 'invalid' );
151
-
152
- // show notice to let the user know we deactivated his/her license
153
- $this->error_message = __( "This site has not been activated properly on monsterinsights.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
154
- add_action( 'admin_notices', array( $this, 'show_update_error' ) );
155
- }
156
-
157
- $response->sections = maybe_unserialize( $response->sections );
158
-
159
- // store response
160
- set_transient( $this->response_transient_key, $response, 10800 );
161
-
162
- return $response;
163
- }
164
-
165
- /**
166
- * Gets the remote product data (from the EDD API)
167
- *
168
- * - If it was previously fetched in the current requests, this gets it from the instance property
169
- * - Next, it tries the 3-hour transient
170
- * - Next, it calls the remote API and stores the result
171
- *
172
- * @return object
173
- */
174
- protected function get_remote_data() {
175
-
176
- // always use property if it's set
177
- if( null !== $this->update_response ) {
178
- return $this->update_response;
179
- }
180
-
181
- // get cached remote data
182
- $data = $this->get_cached_remote_data();
183
-
184
- // if cache is empty or expired, call remote api
185
- if( $data === false ) {
186
- $data = $this->call_remote_api();
187
- }
188
-
189
- $this->update_response = $data;
190
- return $data;
191
- }
192
-
193
- /**
194
- * Gets the remote product data from a 3-hour transient
195
- *
196
- * @return bool|mixed
197
- */
198
- private function get_cached_remote_data() {
199
-
200
- $data = get_transient( $this->response_transient_key );
201
-
202
- if( $data ) {
203
- return $data;
204
- }
205
-
206
- return false;
207
- }
208
-
209
- }
210
-
211
- }
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! class_exists( "MI_Update_Manager", false ) ) {
4
+
5
+ class MI_Update_Manager {
6
+
7
+ /**
8
+ * @var MI_Product
9
+ */
10
+ protected $product;
11
+
12
+ /**
13
+ * @var MI_License_Manager
14
+ */
15
+ protected $license_manager;
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected $error_message = '';
21
+
22
+ /**
23
+ * @var object
24
+ */
25
+ protected $update_response = null;
26
+
27
+ /**
28
+ * @var string The transient name storing the API response
29
+ */
30
+ private $response_transient_key = '';
31
+
32
+ /**
33
+ * @var string The transient name that stores failed request tries
34
+ */
35
+ private $request_failed_transient_key = '';
36
+
37
+ /**
38
+ * Constructor
39
+ *
40
+ * @param MI_Product $product The product.
41
+ * @param MI_License_Manager $license_manager The License Manager.
42
+ */
43
+ public function __construct( MI_Product $product, $license_manager ) {
44
+ $this->product = $product;
45
+ $this->license_manager = $license_manager;
46
+
47
+ // generate transient names
48
+ $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
49
+ $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
50
+
51
+ // maybe delete transient
52
+ $this->maybe_delete_transients();
53
+ }
54
+
55
+ /**
56
+ * Deletes the various transients
57
+ * If we're on the update-core.php?force-check=1 page
58
+ */
59
+ private function maybe_delete_transients() {
60
+ global $pagenow;
61
+
62
+ if ( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
63
+ delete_transient( $this->response_transient_key );
64
+ delete_transient( $this->request_failed_transient_key );
65
+ }
66
+ }
67
+
68
+ /**
69
+ * If the update check returned a WP_Error, show it to the user
70
+ */
71
+ public function show_update_error() {
72
+
73
+ if ( $this->error_message === '' ) {
74
+ return;
75
+ }
76
+
77
+ ?>
78
+ <div class="error">
79
+ <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
80
+ </div>
81
+ <?php
82
+ }
83
+
84
+ /**
85
+ * Calls the API and, if successfull, returns the object delivered by the API.
86
+ *
87
+ * @uses get_bloginfo()
88
+ * @uses wp_remote_post()
89
+ * @uses is_wp_error()
90
+ *
91
+ * @return false||object
92
+ */
93
+ private function call_remote_api() {
94
+
95
+ // only check if the failed transient is not set (or if it's expired)
96
+ if ( get_transient( $this->request_failed_transient_key ) !== false ) {
97
+ return false;
98
+ }
99
+
100
+ // start request process
101
+ global $wp_version;
102
+
103
+ // set a transient to prevent failed update checks on every page load
104
+ // this transient will be removed if a request succeeds
105
+ set_transient( $this->request_failed_transient_key, 'failed', 10800 );
106
+
107
+ // setup api parameters
108
+ $api_params = array(
109
+ 'edd_action' => 'get_version',
110
+ 'license' => $this->license_manager->get_license_key(),
111
+ 'item_name' => $this->product->get_item_name(),
112
+ 'wp_version' => $wp_version,
113
+ 'item_version' => $this->product->get_version(),
114
+ 'url' => home_url(),
115
+ 'slug' => $this->product->get_slug(),
116
+ );
117
+
118
+ // Add product ID from product if it is implemented.
119
+ if ( method_exists( $this->product, 'get_product_id' ) ) {
120
+ $product_id = $this->product->get_product_id();
121
+ if ( $product_id > 0 ) {
122
+ $api_params['product_id'] = $this->product->get_product_id();
123
+ }
124
+ }
125
+
126
+ // setup request parameters
127
+ $request_params = array(
128
+ 'method' => 'POST',
129
+ 'body' => $api_params
130
+ );
131
+
132
+ require_once dirname( __FILE__ ) . '/class-api-request.php';
133
+ $request = new MI_API_Request( $this->product->get_api_url(), $request_params );
134
+
135
+ if ( $request->is_valid() !== true ) {
136
+
137
+ // show error message
138
+ $this->error_message = $request->get_error_message();
139
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
140
+
141
+ return false;
142
+ }
143
+
144
+ // request succeeded, delete transient indicating a request failed
145
+ delete_transient( $this->request_failed_transient_key );
146
+
147
+ // decode response
148
+ $response = $request->get_response();
149
+
150
+ // check if response returned that a given site was inactive
151
+ if ( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
152
+
153
+ // deactivate local license
154
+ $this->license_manager->set_license_status( 'invalid' );
155
+
156
+ // show notice to let the user know we deactivated his/her license
157
+ $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
158
+ add_action( 'admin_notices', array( $this, 'show_update_error' ) );
159
+ }
160
+
161
+ $response->sections = maybe_unserialize( $response->sections );
162
+
163
+ // store response
164
+ set_transient( $this->response_transient_key, $response, 10800 );
165
+
166
+ return $response;
167
+ }
168
+
169
+ /**
170
+ * Gets the remote product data (from the EDD API)
171
+ *
172
+ * - If it was previously fetched in the current requests, this gets it from the instance property
173
+ * - Next, it tries the 3-hour transient
174
+ * - Next, it calls the remote API and stores the result
175
+ *
176
+ * @return object
177
+ */
178
+ protected function get_remote_data() {
179
+
180
+ // always use property if it's set
181
+ if ( null !== $this->update_response ) {
182
+ return $this->update_response;
183
+ }
184
+
185
+ // get cached remote data
186
+ $data = $this->get_cached_remote_data();
187
+
188
+ // if cache is empty or expired, call remote api
189
+ if ( $data === false ) {
190
+ $data = $this->call_remote_api();
191
+ }
192
+
193
+ $this->update_response = $data;
194
+
195
+ return $data;
196
+ }
197
+
198
+ /**
199
+ * Gets the remote product data from a 3-hour transient
200
+ *
201
+ * @return bool|mixed
202
+ */
203
+ private function get_cached_remote_data() {
204
+
205
+ $data = get_transient( $this->response_transient_key );
206
+
207
+ if ( $data ) {
208
+ return $data;
209
+ }
210
+
211
+ return false;
212
+ }
213
+
214
+ }
215
+
216
+ }
vendor/yoast/license-manager/composer.json CHANGED
@@ -1,29 +1,29 @@
1
- {
2
- "name" : "yoast/license-manager",
3
- "description": "Yoast License Manager.",
4
- "keywords" : ["wordpress"],
5
- "homepage" : "https://github.com/Yoast/License-Manager",
6
- "license" : "GPL-2.0+",
7
- "authors" : [
8
- {
9
- "name" : "Team Yoast",
10
- "email" : "support@yoast.com",
11
- "homepage": "https://yoast.com"
12
- }
13
- ],
14
- "support" : {
15
- "issues": "https://github.com/Yoast/License-Manager/issues"
16
- },
17
- "autoload" : {
18
- "classmap": [
19
- "class-api-request.php",
20
- "class-license-manager.php",
21
- "class-plugin-license-manager.php",
22
- "class-plugin-update-manager.php",
23
- "class-product.php",
24
- "class-theme-license-manager.php",
25
- "class-theme-update-manager.php",
26
- "class-update-manager.php"
27
- ]
28
- }
29
  }
1
+ {
2
+ "name" : "yoast/license-manager",
3
+ "description": "MI License Manager.",
4
+ "keywords" : ["wordpress"],
5
+ "homepage" : "https://github.com/MI/License-Manager",
6
+ "license" : "GPL-2.0+",
7
+ "authors" : [
8
+ {
9
+ "name" : "Team MI",
10
+ "email" : "support@yoast.com",
11
+ "homepage": "https://yoast.com"
12
+ }
13
+ ],
14
+ "support" : {
15
+ "issues": "https://github.com/MI/License-Manager/issues"
16
+ },
17
+ "autoload" : {
18
+ "classmap": [
19
+ "class-api-request.php",
20
+ "class-license-manager.php",
21
+ "class-plugin-license-manager.php",
22
+ "class-plugin-update-manager.php",
23
+ "class-product.php",
24
+ "class-theme-license-manager.php",
25
+ "class-theme-update-manager.php",
26
+ "class-update-manager.php"
27
+ ]
28
+ }
29
  }
vendor/yoast/license-manager/samples/sample-plugin.php CHANGED
@@ -1,74 +1,74 @@
1
- <?php
2
-
3
- /*
4
- Plugin Name: Sample Plugin
5
- Version: 1.0
6
- Plugin URI: https://www.monsterinsights.com/
7
- Description: A sample plugin to test the License Manager
8
- Author: chriscct7, msub, DvanKooten
9
- Author URI: http://www.monsterinsights.com/
10
- Text Domain: sample-plugin
11
- */
12
-
13
- /**
14
- * Class Sample_Plugin
15
- *
16
- */
17
- class Sample_Plugin {
18
-
19
- public function __construct() {
20
-
21
- // we only need license stuff inside the admin area
22
- if ( is_admin() ) {
23
-
24
- // add menu item
25
- add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
26
-
27
- // load license class
28
- $this->load_license_manager();
29
- }
30
-
31
-
32
- }
33
-
34
- /**
35
- * Loads the License_Plugin_Manager class
36
- *
37
- * The class will take care of the rest: notices, license (de)activations, updates, etc..
38
- */
39
- public function load_license_manager() {
40
-
41
- // Instantiate license class
42
- $license_manager = new MI_Plugin_License_Manager( new Sample_Product() );
43
-
44
- // Setup the required hooks
45
- $license_manager->setup_hooks();
46
-
47
- }
48
-
49
- /**
50
- * Add license page and add it to Themes menu
51
- */
52
- public function add_license_menu() {
53
- $theme_page = add_options_page( sprintf( __( '%s License', $this->text_domain ), $this->item_name ), sprintf( __( '%s License', $this->text_domain ), $this->item_name ), 'manage_options', $this->text_domain . '-license', array( $this, 'show_license_page' ) );
54
- }
55
-
56
- /**
57
- * Shows license page
58
- */
59
- public function show_license_page() {
60
-
61
- // Instantiate license class
62
- $license_manager = new MI_Plugin_License_Manager( new Sample_Product() );
63
-
64
- ?>
65
- <div class="wrap">
66
- <?php //settings_errors(); ?>
67
-
68
- <?php $license_manager->show_license_form( false ); ?>
69
- </div>
70
- <?php
71
- }
72
- }
73
-
74
- new Sample_Plugin();
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Sample Plugin
5
+ Version: 1.0
6
+ Plugin URI: https://www.monsterinsights.com/
7
+ Description: A sample plugin to test the License Manager
8
+ Author: chriscct7, msub, DvanKooten
9
+ Author URI: http://www.monsterinsights.com/
10
+ Text Domain: sample-plugin
11
+ */
12
+
13
+ /**
14
+ * Class Sample_Plugin
15
+ *
16
+ */
17
+ class Sample_Plugin {
18
+
19
+ public function __construct() {
20
+
21
+ // we only need license stuff inside the admin area
22
+ if ( is_admin() ) {
23
+
24
+ // add menu item
25
+ add_action( 'admin_menu', array( $this, 'add_license_menu' ) );
26
+
27
+ // load license class
28
+ $this->load_license_manager();
29
+ }
30
+
31
+
32
+ }
33
+
34
+ /**
35
+ * Loads the License_Plugin_Manager class
36
+ *
37
+ * The class will take care of the rest: notices, license (de)activations, updates, etc..
38
+ */
39
+ public function load_license_manager() {
40
+
41
+ // Instantiate license class
42
+ $license_manager = new MI_Plugin_License_Manager( new Sample_Product() );
43
+
44
+ // Setup the required hooks
45
+ $license_manager->setup_hooks();
46
+
47
+ }
48
+
49
+ /**
50
+ * Add license page and add it to Themes menu
51
+ */
52
+ public function add_license_menu() {
53
+ $theme_page = add_options_page( sprintf( __( '%s License', $this->text_domain ), $this->item_name ), sprintf( __( '%s License', $this->text_domain ), $this->item_name ), 'manage_options', $this->text_domain . '-license', array( $this, 'show_license_page' ) );
54
+ }
55
+
56
+ /**
57
+ * Shows license page
58
+ */
59
+ public function show_license_page() {
60
+
61
+ // Instantiate license class
62
+ $license_manager = new MI_Plugin_License_Manager( new Sample_Product() );
63
+
64
+ ?>
65
+ <div class="wrap">
66
+ <?php //settings_errors(); ?>
67
+
68
+ <?php $license_manager->show_license_form( false ); ?>
69
+ </div>
70
+ <?php
71
+ }
72
+ }
73
+
74
+ new Sample_Plugin();
vendor/yoast/license-manager/samples/sample-product.php CHANGED
@@ -1,23 +1,23 @@
1
- <?php
2
-
3
- /**
4
- * Class Sample_Product
5
- *
6
- * Our sample product class
7
- */
8
- class Sample_Product extends MI_Product {
9
-
10
- public function __construct() {
11
- parent::__construct(
12
- 'https://www.monsterinsights.com',
13
- 'Sample Product',
14
- 'sample-product',
15
- '1.0',
16
- 'https://www.monsterinsights.com/downloads/sample-product/',
17
- 'admin.php?page=sample-product',
18
- 'sample-product',
19
- 'MonsterInsights'
20
- );
21
- }
22
-
23
  }
1
+ <?php
2
+
3
+ /**
4
+ * Class Sample_Product
5
+ *
6
+ * Our sample product class
7
+ */
8
+ class Sample_Product extends MI_Product {
9
+
10
+ public function __construct() {
11
+ parent::__construct(
12
+ 'https://www.monsterinsights.com',
13
+ 'Sample Product',
14
+ 'sample-product',
15
+ '1.0',
16
+ 'https://www.monsterinsights.com/downloads/sample-product/',
17
+ 'admin.php?page=sample-product',
18
+ 'sample-product',
19
+ 'MonsterInsights'
20
+ );
21
+ }
22
+
23
  }