1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
// Exit if accessed directly |
4
|
|
|
|
5
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
6
|
|
|
exit; |
7
|
|
|
} |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* GravityView_Admin_Installer Class |
11
|
|
|
* |
12
|
|
|
* A general class for About page. |
13
|
|
|
* |
14
|
|
|
* @since 2.1 |
15
|
|
|
*/ |
16
|
|
|
class GravityView_Admin_Installer { |
17
|
|
|
|
18
|
|
|
const EDD_API_URL = 'https://gravityview.co/edd-api/products/'; |
19
|
|
|
|
20
|
|
|
const EDD_API_KEY = 'e4c7321c4dcf342c9cb078e27bf4ba97'; |
21
|
|
|
|
22
|
|
|
const EDD_API_TOKEN = 'e031fd350b03bc223b10f04d8b5dde42'; |
23
|
|
|
|
24
|
|
|
const DOWNLOADS_DATA_TRANSIENT = 'gv_downloads_data'; |
25
|
|
|
|
26
|
|
|
const DOWNLOADS_DATA_TRANSIENT_EXPIRY = DAY_IN_SECONDS; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
public $minimum_capability = 'install_plugins'; |
32
|
|
|
|
33
|
|
|
public function __construct() { |
34
|
|
|
|
35
|
|
|
$this->add_downloads_data_filters(); |
36
|
|
|
|
37
|
|
|
add_action( 'admin_menu', array( $this, 'add_admin_menu' ), 200 ); |
38
|
|
|
add_action( 'gravityview/admin_installer/delete_downloads_data', array( $this, 'delete_downloads_data' ) ); |
39
|
|
|
add_action( 'wp_ajax_gravityview_admin_installer_activate', array( $this, 'activate_download' ) ); |
40
|
|
|
add_action( 'wp_ajax_gravityview_admin_installer_deactivate', array( $this, 'deactivate_download' ) ); |
41
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_scripts_and_styles' ) ); |
42
|
|
|
add_filter( 'gravityview_noconflict_scripts', array( $this, 'register_noconflict' ) ); |
43
|
|
|
add_filter( 'gravityview_noconflict_styles', array( $this, 'register_noconflict' ) ); |
44
|
|
|
add_filter( 'gravityview/settings/license-key-notice', array( $this, 'maybe_modify_license_notice' ) ); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Let us operate when GF no-conflict is enabled |
49
|
|
|
* |
50
|
|
|
* @param array $items Scripts or styles to exclude from no-conflict |
51
|
|
|
* |
52
|
|
|
* @return array |
53
|
|
|
*/ |
54
|
|
|
public function register_noconflict( $items ) { |
55
|
|
|
|
56
|
|
|
$items[] = 'gravityview-admin-installer'; |
57
|
|
|
|
58
|
|
|
return $items; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Modify plugins data with custom GV extension info |
64
|
|
|
* |
65
|
|
|
* @return void |
66
|
|
|
*/ |
67
|
|
|
public function add_downloads_data_filters() { |
68
|
|
|
|
69
|
|
|
$downloads_data = get_site_transient( self::DOWNLOADS_DATA_TRANSIENT ); |
70
|
|
|
|
71
|
|
|
if ( ! $downloads_data && ! isset( $_GET['cache'] ) ) { |
72
|
|
|
return; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
add_filter( 'plugins_api', function ( $data, $action, $args ) use ( $downloads_data ) { |
76
|
|
|
foreach ( $downloads_data as $extension ) { |
77
|
|
|
if ( empty( $extension['info'] ) || empty( $args->slug ) || $args->slug !== $extension['info']['slug'] ) { |
78
|
|
|
continue; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
return (object) array( |
82
|
|
|
'slug' => $extension['info']['slug'], |
83
|
|
|
'name' => $extension['info']['title'], |
84
|
|
|
'version' => $extension['licensing']['version'], |
85
|
|
|
'download_link' => $extension['files'][0]['file'], |
86
|
|
|
); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
return $data; |
90
|
|
|
}, 10, 3 ); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Add new admin menu |
95
|
|
|
* |
96
|
|
|
* @return void |
97
|
|
|
*/ |
98
|
|
|
public function add_admin_menu() { |
99
|
|
|
|
100
|
|
|
$menu_text = _x( 'Manage Add-Ons', 'Extensions are WordPress plugins that add functionality to GravityView and Gravity Forms', 'gravityview' ); |
101
|
|
|
|
102
|
|
|
$menu_text = sprintf( '<span title="%s" style="margin: 0">%s</span>', esc_attr__( 'Plugins that extend GravityView and Gravity Forms functionality.', 'gravityview' ), $menu_text ); |
103
|
|
|
|
104
|
|
|
add_submenu_page( |
105
|
|
|
'edit.php?post_type=gravityview', |
106
|
|
|
__( 'GravityView Extensions and Plugins', 'gravityview' ), |
107
|
|
|
$menu_text, |
108
|
|
|
$this->minimum_capability, |
109
|
|
|
'gv-admin-installer', |
110
|
|
|
array( $this, 'render_screen' ) |
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* When on the Installer page, show a different notice than on the Settings page |
116
|
|
|
* |
117
|
|
|
* @param array $notice |
118
|
|
|
* |
119
|
|
|
* @return string License notice |
120
|
|
|
*/ |
121
|
|
|
public function maybe_modify_license_notice( $notice = '' ) { |
122
|
|
|
|
123
|
|
|
if ( ! gravityview()->request->is_admin( '', 'downloads' ) ) { |
|
|
|
|
124
|
|
|
return $notice; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return esc_html__( 'Your license %s. Do you want access to these plugins? %sActivate your license%s or %sget a license here%s.', 'gravityview' ); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Get an array of plugins with textdomains as keys |
132
|
|
|
* |
133
|
|
|
* @since 2.1 |
134
|
|
|
* @since 2.10 Added $textdomain argument. Converted to static method. Made method public (from protected). |
135
|
|
|
* |
136
|
|
|
* @param string $textdomain If set, only return plugins that have a matching textdomain. |
137
|
|
|
* |
138
|
|
|
* @return array { |
139
|
|
|
* @type string $path Path to the plugin. |
140
|
|
|
* @type string $version What version is the plugin. |
141
|
|
|
* @type bool $activated Is the plugin activated. |
142
|
|
|
* } |
143
|
|
|
*/ |
144
|
|
|
static public function get_wp_plugins_data( $textdomain = null ) { |
145
|
|
|
|
146
|
|
|
$wp_plugins = array(); |
147
|
|
|
|
148
|
|
|
$all_plugins = get_plugins(); |
149
|
|
|
|
150
|
|
|
foreach ( $all_plugins as $path => $plugin ) { |
151
|
|
|
|
152
|
|
|
if ( empty( $plugin['TextDomain'] ) ) { |
153
|
|
|
continue; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
$wp_plugins[ $plugin['TextDomain'] ] = array( |
157
|
|
|
'path' => $path, |
158
|
|
|
'version' => $plugin['Version'], |
159
|
|
|
'activated' => is_plugin_active( $path ) |
160
|
|
|
); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return is_null( $textdomain ) ? $wp_plugins : \GV\Utils::get( $wp_plugins, $textdomain, array() ); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Get downloads data from transient or from API; save transient after getting data from API |
168
|
|
|
* |
169
|
|
|
* @return WP_Error|array If error, returns WP_Error. If not valid JSON, empty array. Otherwise, this structure: { |
170
|
|
|
* @type array $info { |
171
|
|
|
* @type string $id int 17 |
172
|
|
|
* @type string $slug Extension slug |
173
|
|
|
* @type string $title Extension title |
174
|
|
|
* @type string $create_date in '2018-07-19 20:03:10' format |
175
|
|
|
* @type string $modified_date |
176
|
|
|
* @type string $status |
177
|
|
|
* @type string $link URL to public plugin page |
178
|
|
|
* @type string $content |
179
|
|
|
* @type string $excerpt |
180
|
|
|
* @type string $thumbnail URL to thumbnail |
181
|
|
|
* @type array $category Taxonomy details for the plugin's category { |
182
|
|
|
* @type int $term_id => int 30 |
183
|
|
|
* @type string $name => string 'Plugins' (length=7) |
184
|
|
|
* @type string $slug => string 'plugins' (length=7) |
185
|
|
|
* @type int $term_group => int 0 |
186
|
|
|
* @type int $term_taxonomy_id => int 30 |
187
|
|
|
* @type string $taxonomy => string 'download_category' (length=17) |
188
|
|
|
* @type string $description => string '' (length=0) |
189
|
|
|
* @type int $parent => int 0 |
190
|
|
|
* @type int $count => int 4 |
191
|
|
|
* @type string $filter => string 'raw' (length=3) |
192
|
|
|
* } |
193
|
|
|
* @type array $tags {see $category above} |
194
|
|
|
* @type string $textdomain string 'gravityview' (length=11) |
195
|
|
|
* } |
196
|
|
|
* @type array $pricing array of `price_name_slugs` => '00.00' values, if price options exist |
197
|
|
|
* @type array $licensing { |
198
|
|
|
* @type bool $enabled Is licensing enabled for the extension |
199
|
|
|
* @type string $version Version number |
200
|
|
|
* @type string $exp_unit Expiration unit ('years') |
201
|
|
|
* @type string $exp_length Expiration length ('1') |
202
|
|
|
* } |
203
|
|
|
* @type array $files Array of files. Empty if user has no access to the file. { |
204
|
|
|
* @type string $file string URL of the file download |
205
|
|
|
* } |
206
|
|
|
* } |
207
|
|
|
*/ |
208
|
|
|
public function get_downloads_data() { |
209
|
|
|
|
210
|
|
|
$downloads_data = get_site_transient( self::DOWNLOADS_DATA_TRANSIENT ); |
211
|
|
|
|
212
|
|
|
if ( $downloads_data && ! isset( $_GET['cache'] ) ) { |
213
|
|
|
return $downloads_data; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
if( \GV\Plugin::is_network_activated() ) { |
217
|
|
|
$home_url = network_home_url(); |
218
|
|
|
} else { |
219
|
|
|
$home_url = home_url(); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
$api_url = add_query_arg( |
223
|
|
|
array( |
224
|
|
|
'key' => self::EDD_API_KEY, |
225
|
|
|
'token' => self::EDD_API_TOKEN, |
226
|
|
|
'url' => $home_url, |
227
|
|
|
'license_key' => gravityview()->plugin->settings->get( 'license_key' ) |
228
|
|
|
), |
229
|
|
|
self::EDD_API_URL |
230
|
|
|
); |
231
|
|
|
|
232
|
|
|
$response = wp_remote_get( $api_url, array( |
233
|
|
|
'sslverify' => false, |
234
|
|
|
'timeout' => 5, |
235
|
|
|
) ); |
236
|
|
|
|
237
|
|
|
if ( is_wp_error( $response ) ) { |
238
|
|
|
gravityview()->log->error( "Extension data response is an error", array( 'data' => $response ) ); |
239
|
|
|
return $response; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
$downloads_data = json_decode( wp_remote_retrieve_body( $response ), true ); |
243
|
|
|
|
244
|
|
|
if ( empty( $downloads_data['products'] ) ) { |
245
|
|
|
return array(); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
$this->set_downloads_data( $downloads_data['products'] ); |
249
|
|
|
|
250
|
|
|
return $downloads_data['products']; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Save downloads data in a time-bound transient |
255
|
|
|
* |
256
|
|
|
* @param array $data |
257
|
|
|
* |
258
|
|
|
* @return true if successful, false otherwise |
259
|
|
|
*/ |
260
|
|
|
public function set_downloads_data( $data ) { |
261
|
|
|
return set_site_transient( self::DOWNLOADS_DATA_TRANSIENT, $data, self::DOWNLOADS_DATA_TRANSIENT_EXPIRY ); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Delete downloads data transient |
266
|
|
|
* |
267
|
|
|
* @return bool true if successful, false otherwise |
268
|
|
|
*/ |
269
|
|
|
public function delete_downloads_data() { |
270
|
|
|
return delete_site_transient( self::DOWNLOADS_DATA_TRANSIENT ); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Display a grid of available downloads and controls to install/activate/deactivate them |
275
|
|
|
* |
276
|
|
|
* @since 2.1 |
277
|
|
|
* |
278
|
|
|
* @return void |
279
|
|
|
*/ |
280
|
|
|
public function render_screen() { |
281
|
|
|
|
282
|
|
|
$downloads_data = $this->get_downloads_data(); |
283
|
|
|
|
284
|
|
|
if ( is_wp_error( $downloads_data ) || empty( $downloads_data ) ) { |
285
|
|
|
?> |
286
|
|
|
<div class="wrap"> |
287
|
|
|
<h1><?php esc_html_e( 'GravityView Extensions and Plugins', 'gravityview' ); ?></h1> |
288
|
|
|
<div class="gv-admin-installer-notice notice inline error"> |
289
|
|
|
<h3><?php esc_html_e( 'Extensions and plugins data cannot be loaded at the moment. Please try again later.', 'gravityview' ); ?></h3> |
290
|
|
|
<?php |
291
|
|
|
if ( is_wp_error( $downloads_data ) ) { |
292
|
|
|
echo wpautop( '<pre>' . esc_html( $downloads_data->get_error_message() ) . '</pre>' ); |
293
|
|
|
} |
294
|
|
|
?> |
295
|
|
|
</div> |
296
|
|
|
</div> |
297
|
|
|
<?php |
298
|
|
|
|
299
|
|
|
return; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
?> |
303
|
|
|
<div class="wrap"> |
304
|
|
|
|
305
|
|
|
|
306
|
|
|
<h1><?php esc_html_e( 'GravityView Extensions and Plugins', 'gravityview' ); ?></h1> |
307
|
|
|
|
308
|
|
|
<h2><?php esc_html_e( 'The following plugins extend GravityView and Gravity Forms functionality:', 'gravityview' ); ?></h2> |
309
|
|
|
|
310
|
|
|
<a class="button button-secondary gv-admin-installer-refresh-link" href="<?php echo add_query_arg(array( 'cache' => 1 ) ); ?>"><i class="dashicons dashicons-update" style="margin-top: .2em"></i> <?php esc_html_e( 'Refresh', 'gravityview' ); ?></a> |
311
|
|
|
|
312
|
|
|
<hr class="wp-header-end" /> |
313
|
|
|
|
314
|
|
|
<div class="gv-admin-installer-notice notice inline error hidden is-dismissible"> |
315
|
|
|
<p><!-- Contents will be replaced by JavaScript if there is an error --></p> |
316
|
|
|
</div> |
317
|
|
|
|
318
|
|
|
<div class="gv-admin-installer-container"> |
319
|
|
|
<?php |
320
|
|
|
|
321
|
|
|
$wp_plugins = self::get_wp_plugins_data(); |
322
|
|
|
|
323
|
|
|
$this->render_section( 'views', esc_html__( 'GravityView Layouts', 'gravityview' ), $downloads_data, $wp_plugins ); |
324
|
|
|
|
325
|
|
|
$this->render_section( 'extensions', esc_html__( 'GravityView Extensions', 'gravityview' ), $downloads_data, $wp_plugins ); |
326
|
|
|
|
327
|
|
|
$this->render_section( 'plugins', esc_html__( 'Gravity Forms Add-Ons', 'gravityview' ), $downloads_data, $wp_plugins ); |
328
|
|
|
|
329
|
|
|
$this->render_section( 'friends', esc_html__( 'Friends of GravityView', 'gravityview' ), $downloads_data, $wp_plugins ); |
330
|
|
|
?> |
331
|
|
|
</div> |
332
|
|
|
</div> |
333
|
|
|
<?php |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Renders each category of download (Add-Ons, Extensions, Layouts) |
338
|
|
|
* |
339
|
|
|
* @since 2.10 |
340
|
|
|
* |
341
|
|
|
* @param string $section_slug The slug to display downloads from (based on the category slug on gravityview.co) |
342
|
|
|
* @param string $heading The section heading text ("GravityView Layouts", "GravityView Extensions", "Gravity Forms Add-Ons") |
343
|
|
|
* @param array $downloads_data Downloads data from gravityview.co EDD API {@see get_downloads_data} |
344
|
|
|
* @param array $wp_plugins All active plugins, as returned by {@see \get_plugins()} |
345
|
|
|
*/ |
346
|
|
|
private function render_section( $section_slug, $heading, $downloads_data, $wp_plugins = array() ) { |
347
|
|
|
|
348
|
|
|
ob_start(); |
349
|
|
|
|
350
|
|
|
foreach ( $downloads_data as $download ) { |
351
|
|
|
|
352
|
|
|
if ( $section_slug !== \GV\Utils::get( $download, 'info/category/0/slug' ) && $section_slug !== \GV\Utils::get( $download, 'info/category/1/slug' ) ) { |
353
|
|
|
continue; |
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
if ( empty( $download['info'] ) ) { |
357
|
|
|
continue; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
$this->render_download( $download, $wp_plugins ); |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
$output = ob_get_clean(); |
364
|
|
|
$output = trim( $output ); |
365
|
|
|
|
366
|
|
|
if ( ! empty( $output ) ) { |
367
|
|
|
echo '<div class="gv-admin-installer-section"><h3>' . esc_html( $heading ) . '</h3></div>'; |
368
|
|
|
echo $output; |
369
|
|
|
} |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* Outputs the HTML of a single download |
374
|
|
|
* |
375
|
|
|
* @param array $download Download data, as returned from EDD API |
376
|
|
|
* @param array $wp_plugins |
377
|
|
|
* |
378
|
|
|
* @return void |
379
|
|
|
*/ |
380
|
|
|
protected function render_download( $download, $wp_plugins ) { |
381
|
|
|
|
382
|
|
|
$details = $this->get_download_display_details( $download, $wp_plugins ); |
383
|
|
|
|
384
|
|
|
$download_info = $details['download_info']; |
385
|
|
|
|
386
|
|
|
?> |
387
|
|
|
<div class="item <?php echo esc_attr( $details['item_class'] ); ?>"> |
388
|
|
|
<div class="addon-inner"> |
389
|
|
|
<a href="<?php echo esc_url( $download_info['link'] ); ?>" rel="external noreferrer noopener" title="<?php esc_html_e( 'Visit the plugin page', 'gravityview' ); ?>"><img class="thumbnail" src="<?php echo esc_attr( $download_info['thumbnail'] ); ?>" alt="" /></a> |
390
|
|
|
<h3><?php echo esc_html( \GV\Utils::get( $download_info, 'installer_title', $download_info['title'] ) ); ?></h3> |
391
|
|
|
<div> |
392
|
|
|
<?php if( ! empty( $details['status_label'] ) ) { ?> |
393
|
|
|
<div class="status <?php echo esc_attr( $details['status'] ); ?>" title="<?php printf( esc_attr__( 'Plugin status: %s', 'gravityview' ), esc_html( $details['status_label'] ) ); ?>"> |
394
|
|
|
<span class="dashicons dashicons-admin-plugins"></span> <span class="status-label"><?php echo esc_html( $details['status_label'] ); ?></span> |
395
|
|
|
</div> |
396
|
|
|
<?php } ?> |
397
|
|
|
|
398
|
|
|
<?php if ( 'gravityview' !== $download_info['slug'] ) { ?> |
399
|
|
|
<a data-status="<?php echo esc_attr( $details['status'] ); ?>" data-plugin-path="<?php echo esc_attr( $details['plugin_path'] ); ?>" href="<?php echo esc_url( $details['href'] ); ?>" class="button <?php echo esc_attr( $details['button_class'] ); ?>" title="<?php echo esc_attr( $details['button_title'] ); ?>"> |
400
|
|
|
<span class="title"><?php echo esc_html( $details['button_label'] ); ?></span> |
401
|
|
|
<?php if( $details['spinner'] ) { ?><span class="spinner"></span><?php } ?> |
402
|
|
|
</a> |
403
|
|
|
<?php } ?> |
404
|
|
|
</div> |
405
|
|
|
|
406
|
|
|
<div class="addon-excerpt"><?php |
407
|
|
|
|
408
|
|
|
$excerpt = \GV\Utils::get( $download_info, 'installer_excerpt', $download_info['excerpt'] ); |
409
|
|
|
|
410
|
|
|
// Allow some pure HTML tags, but remove everything else from the excerpt. |
411
|
|
|
$tags = array( '<strong>', '</strong>', '<em>', '</em>', '<code>', '</code>' ); |
412
|
|
|
$replacements = array( '[b]', '[/b]', '[i]', '[/i]', '[code]', '[/code]' ); |
413
|
|
|
|
414
|
|
|
$excerpt = str_replace( $tags, $replacements, $excerpt ); |
415
|
|
|
$excerpt = esc_html( strip_tags( $excerpt ) ); |
416
|
|
|
$excerpt = str_replace( $replacements, $tags, $excerpt ); |
417
|
|
|
|
418
|
|
|
echo wpautop( $excerpt ); |
419
|
|
|
?></div> |
420
|
|
|
</div> |
421
|
|
|
</div> |
422
|
|
|
<?php |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* Generates details array for the download to keep the render_download() method a bit tidier |
427
|
|
|
* |
428
|
|
|
* @since 2.10 Allow managing installed add-ons whether or not the user's license shows they have access. |
429
|
|
|
* |
430
|
|
|
* @param array $download Single download, as returned by {@see get_downloads_data} |
431
|
|
|
* @param array $wp_plugins All active plugins, as returned by {@see get_plugins()} |
432
|
|
|
* |
433
|
|
|
* @return array { |
434
|
|
|
* @type array $download_info |
435
|
|
|
* @type string $plugin_path |
436
|
|
|
* @type string $status License status returned by Easy Digital Downloads ("active", "inactive", "expired", "revoked", etc) |
437
|
|
|
* @type string $status_label |
438
|
|
|
* @type string $button_title Title attribute to show when hovering over the download's button |
439
|
|
|
* @type string $button_class CSS class to use for the button |
440
|
|
|
* @type string $button_label Text to use for the download's anchor link |
441
|
|
|
* @type string $href URL for the download's button |
442
|
|
|
* @type bool $spinner Whether to show the spinner icon |
443
|
|
|
* @type string $item_class CSS class for the download container |
444
|
|
|
* @type string $required_license The name of the required license for the download ("All Access" or "Core + Extensions") |
445
|
|
|
* @type bool $is_active Is the current GravityView license (as entered in Settings) active? |
446
|
|
|
* } |
447
|
|
|
*/ |
448
|
|
|
private function get_download_display_details( $download, $wp_plugins ) { |
449
|
|
|
|
450
|
|
|
$download_info = wp_parse_args( (array) $download['info'], array( |
451
|
|
|
'thumbnail' => '', |
452
|
|
|
'title' => '', |
453
|
|
|
'textdomain' => '', |
454
|
|
|
'slug' => '', |
455
|
|
|
'excerpt' => '', |
456
|
|
|
'link' => '', |
457
|
|
|
'coming_soon' => false, |
458
|
|
|
'installer_title' => null, // May not be defined |
459
|
|
|
'installer_excerpt' => null, // May not be defined |
460
|
|
|
) ); |
461
|
|
|
|
462
|
|
|
$wp_plugin = \GV\Utils::get( $wp_plugins, $download_info['textdomain'], false ); |
463
|
|
|
|
464
|
|
|
$has_access = ! empty( $download['files'] ); |
465
|
|
|
$spinner = true; |
466
|
|
|
$href = $plugin_path = '#'; |
467
|
|
|
$status = $item_class = $button_title = $button_class = ''; |
468
|
|
|
$base_price = $this->get_download_base_price( $download ); |
469
|
|
|
$is_active = in_array( gravityview()->plugin->settings->get( 'license_key_response/license' ), array( 'active', 'valid' ), true ); |
470
|
|
|
$galactic_only = in_array( \GV\Utils::get( $download, 'info/category/0/slug' ), array( 'plugins', 'views' ) ); |
471
|
|
|
$required_license = $galactic_only ? __( 'All Access', 'gravityview' ) : __( 'Core + Extensions', 'gravityview' ); |
472
|
|
|
|
473
|
|
|
// The license is not active - no matter what level, this should not work |
474
|
|
|
if( ! $is_active && empty( $base_price ) ) { |
475
|
|
|
$spinner = false; |
476
|
|
|
$status_label = ''; |
477
|
|
|
$button_label = sprintf( __( 'Active %s License is Required.', 'gravityview' ), $required_license ); |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
// No access with the current license level, and the download is available to purchase |
481
|
|
|
elseif ( ! $has_access && ! empty( $base_price ) ) { |
482
|
|
|
$spinner = false; |
483
|
|
|
$status_label = ''; |
484
|
|
|
$button_label = sprintf( __( 'Purchase Now for %s', 'gravityview' ), '$' . $base_price ); |
485
|
|
|
$button_class = 'button-primary button-large'; |
486
|
|
|
$href = $download_info['link']; |
487
|
|
|
$item_class = 'featured'; |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
// No access with the current license level, and the download is not sold separately |
491
|
|
|
elseif ( ! $has_access && $is_active ) { |
492
|
|
|
$spinner = false; |
493
|
|
|
$status_label = ''; |
494
|
|
|
$button_label = sprintf( __( 'Upgrade to %s for Access', 'gravityview' ), $required_license ); |
495
|
|
|
$button_class = 'button-primary button-large'; |
496
|
|
|
$href = 'https://gravityview.co/pricing/?utm_source=admin-installer&utm_medium=admin&utm_campaign=Admin%20Notice&utm_content=' . $required_license; |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
elseif ( ! empty( $download_info['coming_soon'] ) ) { |
500
|
|
|
$spinner = false; |
501
|
|
|
$status = 'notinstalled'; |
502
|
|
|
$status_label = __( 'Coming Soon', 'gravityview' ); |
503
|
|
|
$button_label = __( 'Learn More', 'gravityview' ); |
504
|
|
|
$button_class = 'button-primary button-large'; |
505
|
|
|
$href = \GV\Utils::get( $download_info, 'link', 'https://gravityview.co/extensions/' ); |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
// Access but the plugin is not installed |
509
|
|
|
elseif ( ! $wp_plugin ) { |
510
|
|
|
|
511
|
|
|
$href = add_query_arg( |
512
|
|
|
array( |
513
|
|
|
'action' => 'install-plugin', |
514
|
|
|
'plugin' => $download_info['slug'], |
515
|
|
|
'_wpnonce' => wp_create_nonce( 'install-plugin_' . $download_info['slug'] ), |
516
|
|
|
), |
517
|
|
|
self_admin_url( 'update.php' ) |
518
|
|
|
); |
519
|
|
|
|
520
|
|
|
$status = 'notinstalled'; |
521
|
|
|
$status_label = __( 'Not Installed', 'gravityview' ); |
522
|
|
|
$button_label = __( 'Install', 'gravityview' ); |
523
|
|
|
|
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
// The plugin is installed but not active |
527
|
|
|
if ( false === \GV\Utils::get( $wp_plugin, 'activated' ) ) { |
528
|
|
|
$status = 'inactive'; |
529
|
|
|
$status_label = __( 'Inactive', 'gravityview' ); |
530
|
|
|
$button_label = __( 'Activate', 'gravityview' ); |
531
|
|
|
$plugin_path = $wp_plugin['path']; |
532
|
|
|
} |
533
|
|
|
// The plugin is installed and active |
534
|
|
|
elseif ( ! empty( $wp_plugin['path'] ) ) { |
535
|
|
|
$plugin_path = $wp_plugin['path']; |
536
|
|
|
$status = 'active'; |
537
|
|
|
$status_label = __( 'Active', 'gravityview' ); |
538
|
|
|
$button_label = __( 'Deactivate', 'gravityview' ); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
return compact( 'download_info','plugin_path', 'status', 'status_label', 'button_title', 'button_class', 'button_label', 'href', 'spinner', 'item_class', 'required_license', 'is_active' ); |
542
|
|
|
} |
543
|
|
|
|
544
|
|
|
/** |
545
|
|
|
* Returns the base price for an extension |
546
|
|
|
* |
547
|
|
|
* @param array $download |
548
|
|
|
* |
549
|
|
|
* @return float Base price for an extension. If not for sale separately, returns 0 |
550
|
|
|
*/ |
551
|
|
|
private function get_download_base_price( $download ) { |
552
|
|
|
|
553
|
|
|
$base_price = \GV\Utils::get( $download, 'pricing/amount', 0 ); |
554
|
|
|
$base_price = \GFCommon::to_number( $base_price ); |
555
|
|
|
|
556
|
|
|
unset( $download['pricing']['amount'] ); |
557
|
|
|
|
558
|
|
|
// Price options array, not single price |
559
|
|
|
if ( ! $base_price && ! empty( $download['pricing'] ) ) { |
560
|
|
|
$base_price = array_shift( $download['pricing'] ); |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
return floatval( $base_price ); |
564
|
|
|
} |
565
|
|
|
|
566
|
|
|
/** |
567
|
|
|
* Handle AJAX request to activate extension |
568
|
|
|
* |
569
|
|
|
* @return void Exits with JSON response |
570
|
|
|
*/ |
571
|
|
|
public function activate_download() { |
572
|
|
|
$data = \GV\Utils::_POST( 'data', array() ); |
573
|
|
|
|
574
|
|
|
if ( empty( $data['path'] ) ) { |
575
|
|
|
return; |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
$result = activate_plugin( $data['path'] ); |
579
|
|
|
|
580
|
|
|
if ( is_wp_error( $result ) || ! is_plugin_active( $data['path'] ) ) { |
581
|
|
|
wp_send_json_error( array( |
582
|
|
|
'error' => sprintf( __( 'Plugin activation failed: %s', 'gravityview' ), $result->get_error_message() ) |
583
|
|
|
) ); |
584
|
|
|
} |
585
|
|
|
|
586
|
|
|
wp_send_json_success(); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
/** |
590
|
|
|
* Handle AJAX request to deactivate extension |
591
|
|
|
* |
592
|
|
|
* @return void Send JSON response status and error message |
593
|
|
|
*/ |
594
|
|
|
public function deactivate_download() { |
595
|
|
|
$data = \GV\Utils::_POST( 'data', array() ); |
596
|
|
|
|
597
|
|
|
if ( empty( $data['path'] ) ) { |
598
|
|
|
return; |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
deactivate_plugins( $data['path'] ); |
602
|
|
|
|
603
|
|
|
if( is_plugin_active( $data['path'] ) ) { |
604
|
|
|
wp_send_json_error( array( |
605
|
|
|
'error' => sprintf( __( 'Plugin deactivation failed.', 'gravityview' ) ) |
606
|
|
|
) ); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
wp_send_json_success(); |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* Register and enqueue assets; localize script |
614
|
|
|
* |
615
|
|
|
* @return void |
616
|
|
|
*/ |
617
|
|
|
public function maybe_enqueue_scripts_and_styles() { |
618
|
|
|
|
619
|
|
|
if ( ! gravityview()->request->is_admin( '', 'downloads' ) ) { |
|
|
|
|
620
|
|
|
return; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; |
624
|
|
|
|
625
|
|
|
wp_enqueue_style( 'gravityview-admin-installer', GRAVITYVIEW_URL . 'assets/css/admin-installer.css', array(), \GV\Plugin::$version ); |
626
|
|
|
|
627
|
|
|
wp_enqueue_script( 'gravityview-admin-installer', GRAVITYVIEW_URL . 'assets/js/admin-installer' . $script_debug . '.js', array( 'jquery' ), \GV\Plugin::$version, true ); |
628
|
|
|
|
629
|
|
|
wp_localize_script( 'gravityview-admin-installer', 'gvAdminInstaller', array( |
630
|
|
|
'activateErrorLabel' => __( 'Plugin activation failed.', 'gravityview' ), |
631
|
|
|
'deactivateErrorLabel' => __( 'Plugin deactivation failed.', 'gravityview' ), |
632
|
|
|
'activeStatusLabel' => __( 'Active', 'gravityview' ), |
633
|
|
|
'inactiveStatusLabel' => __( 'Inactive', 'gravityview' ), |
634
|
|
|
'activateActionLabel' => __( 'Activate', 'gravityview' ), |
635
|
|
|
'deactivateActionLabel' => __( 'Deactivate', 'gravityview' ) |
636
|
|
|
) ); |
637
|
|
|
} |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
new GravityView_Admin_Installer; |
641
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.