Completed
Push — develop ( 49e19c...e6c90f )
by Zack
21:07 queued 15:45
created

GravityView_Admin_Installer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 13
ccs 0
cts 11
cp 0
crap 2
rs 9.8333
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 16 and the first side effect is on line 6.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
		$downloads_data = get_site_transient( self::DOWNLOADS_DATA_TRANSIENT );
69
		if ( ! $downloads_data ) {
70
			return;
71
		}
72
73
		add_filter( 'plugins_api', function ( $data, $action, $args ) use ( $downloads_data ) {
74
			foreach ( $downloads_data as $extension ) {
75
				if ( empty( $extension['info'] ) || empty( $args->slug ) || $args->slug !== $extension['info']['slug'] ) {
76
					continue;
77
				}
78
79
				return (object) array(
80
					'slug'          => $extension['info']['slug'],
81
					'name'          => $extension['info']['title'],
82
					'version'       => $extension['licensing']['version'],
83
					'download_link' => $extension['files'][0]['file'],
84
				);
85
			}
86
87
			return $data;
88
		}, 10, 3 );
89
	}
90
91
	/**
92
	 * Add new admin menu
93
	 *
94
	 * @return void
95
	 */
96
	public function add_admin_menu() {
97
98
	    $menu_text = _x( 'Extensions', 'Extensions are WordPress plugins that add functionality to GravityView and Gravity Forms', 'gravityview' );
99
100
		$menu_text = sprintf( '<span title="%s">%s</span>', esc_attr__( 'Plugins that extend GravityView and Gravity Forms functionality.', 'gravityview' ), $menu_text );
101
102
		add_submenu_page(
103
			'edit.php?post_type=gravityview',
104
			__( 'GravityView Extensions and Plugins', 'gravityview' ),
105
			$menu_text,
106
			$this->minimum_capability,
107
			'gv-admin-installer',
108
			array( $this, 'render_screen' )
109
		);
110
	}
111
112
	/**
113
     * When on the Installer page, show a different notice than on the Settings page
114
     *
115
	 * @param array $notice
116
	 *
117
	 * @return string License notice
118
	 */
119
	public function maybe_modify_license_notice( $notice = '' ) {
120
121
		if ( ! gravityview()->request->is_admin( '', 'downloads' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to Request::is_admin() has too many arguments starting with ''.

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.

Loading history...
122
            return $notice;
123
        }
124
125
        return esc_html__( 'Your license %s. Do you want access to these plugins? %sActivate your license%s or %sget a license here%s.', 'gravityview' );
126
	}
127
128
	/**
129
	 * Get an array of plugins with textdomains as keys
130
	 *
131
	 * @return array {
132
	 * @type string $path Path to the plugin
133
	 * @type string $version What version is the plugin
134
	 * @type bool $activated Is the plugin activated
135
	 * }
136
	 */
137
	protected function get_wp_plugins_data() {
138
139
		$wp_plugins = array();
140
141
		$all_plugins = get_plugins();
142
143
		foreach ( $all_plugins as $path => $plugin ) {
144
145
			if ( empty( $plugin['TextDomain'] ) ) {
146
				continue;
147
			}
148
149
			$wp_plugins[ $plugin['TextDomain'] ] = array(
150
				'path'      => $path,
151
				'version'   => $plugin['Version'],
152
				'activated' => is_plugin_active( $path )
153
			);
154
		}
155
156
		return $wp_plugins;
157
	}
158
159
	/**
160
	 * Get downloads data from transient or from API; save transient after getting data from API
161
	 *
162
	 * @return WP_Error|array If error, returns WP_Error. If not valid JSON, empty array. Otherwise, this structure: {
163
     *   @type array  $info {
164
     *       @type string $id int 17
165
     *       @type string $slug Extension slug
166
     *       @type string $title Extension title
167
     *       @type string $create_date in '2018-07-19 20:03:10' format
168
     *       @type string $modified_date
169
     *       @type string $status
170
     *       @type string $link URL to public plugin page
171
     *       @type string $content
172
     *       @type string $excerpt
173
     *       @type string $thumbnail URL to thumbnail
174
     *       @type array  $category Taxonomy details for the plugin's category {
175
     *         @type int $term_id => int 30
176
     *         @type string $name => string 'Plugins' (length=7)
177
     *         @type string $slug => string 'plugins' (length=7)
178
     *         @type int $term_group => int 0
179
     *         @type int $term_taxonomy_id => int 30
180
     *         @type string $taxonomy => string 'download_category' (length=17)
181
     *         @type string $description => string '' (length=0)
182
     *         @type int $parent => int 0
183
     *         @type int $count => int 4
184
     *         @type string $filter => string 'raw' (length=3)
185
     *       }
186
     *       @type array $tags {see $category above}
187
     *       @type string $textdomain string 'gravityview' (length=11)
188
     *   }
189
     *   @type array $pricing array of `price_name_slugs` => '00.00' values, if price options exist
190
     *   @type array $licensing {
191
     *       @type bool   $enabled Is licensing enabled for the extension
192
     *       @type string $version Version number
193
     *       @type string $exp_unit Expiration unit ('years')
194
     *       @type string $exp_length Expiration length ('1')
195
     *   }
196
     *   @type array $files Array of files. Empty if user has no access to the file. {
197
     *       @type string $file string URL of the file download
198
     *   }
199
     * }
200
	 */
201
	public function get_downloads_data() {
202
203
		$downloads_data = get_site_transient( self::DOWNLOADS_DATA_TRANSIENT );
204
205
		if ( $downloads_data ) {
206
			return $downloads_data;
207
		}
208
209
		$home_url = parse_url( home_url() );
210
211
		$api_url = add_query_arg(
212
			array(
213
				'key'         => self::EDD_API_KEY,
214
				'token'       => self::EDD_API_TOKEN,
215
				'url'         => \GV\Utils::get( $home_url, 'host', home_url() ),
216
				'license_key' => gravityview()->plugin->settings->get( 'license_key' )
217
			),
218
			self::EDD_API_URL
219
		);
220
221
		$response = wp_remote_get( $api_url, array(
0 ignored issues
show
introduced by
wp_remote_get is highly discouraged, please use vip_safe_wp_remote_get() instead.
Loading history...
222
			'sslverify' => false,
223
			'timeout'   => 5,
224
		) );
225
226
		if ( is_wp_error( $response ) ) {
227
		    gravityview()->log->error( "Extension data response is an error", array( 'data' => $response ) );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Extension data response is an error does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
228
			return $response;
229
		}
230
231
		$downloads_data = json_decode( wp_remote_retrieve_body( $response ), true );
232
233
		if ( empty( $downloads_data['products'] ) ) {
234
			return array();
235
		}
236
237
		$this->set_downloads_data( $downloads_data['products'] );
238
239
		return $downloads_data['products'];
240
	}
241
242
	/**
243
	 * Save downloads data in a time-bound transient
244
	 *
245
	 * @param array $data
246
	 *
247
	 * @return true if successful, false otherwise
248
	 */
249
	public function set_downloads_data( $data ) {
250
		return set_site_transient( self::DOWNLOADS_DATA_TRANSIENT, $data, self::DOWNLOADS_DATA_TRANSIENT_EXPIRY );
251
	}
252
253
	/**
254
	 * Delete downloads data transient
255
	 *
256
	 * @return bool true if successful, false otherwise
257
	 */
258
	public function delete_downloads_data() {
259
		return delete_site_transient( self::DOWNLOADS_DATA_TRANSIENT );
260
	}
261
262
	/**
263
	 * Display a grid of available downloads and controls to install/activate/deactivate them
264
	 *
265
	 * @since 2.1
266
	 *
267
	 * @return void
268
	 */
269
	public function render_screen() {
270
271
		$downloads_data = $this->get_downloads_data();
272
273
		if ( is_wp_error( $downloads_data ) || empty( $downloads_data ) ) {
274
			?>
275
            <div class="wrap">
276
                <h1><?php esc_html_e( 'GravityView Extensions and Plugins', 'gravityview' ); ?></h1>
277
                <div class="gv-admin-installer-notice notice inline error">
278
                    <h3><?php esc_html_e( 'Extensions and plugins data cannot be loaded at the moment. Please try again later.', 'gravityview' ); ?></h3>
279
                    <?php
280
                    if ( is_wp_error( $downloads_data ) ) {
281
	                    echo wpautop( '<pre>' . esc_html( $downloads_data->get_error_message() ) . '</pre>' );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'wpautop'
Loading history...
282
                    }
283
                    ?>
284
                </div>
285
            </div>
286
			<?php
287
288
			return;
289
		}
290
291
		?>
292
        <div class="wrap">
293
294
295
            <h1><?php esc_html_e( 'GravityView Extensions and Plugins', 'gravityview' ); ?></h1>
296
297
            <h2><?php esc_html_e( 'The following plugins extend GravityView and Gravity Forms functionality:', 'gravityview' ); ?></h2>
298
299
            <div class="wp-header-end"></div>
300
301
            <div class="gv-admin-installer-notice notice inline error hidden is-dismissible">
302
                <p><!-- Contents will be replaced by JavaScript if there is an error --></p>
303
            </div>
304
305
            <div class="gv-admin-installer-container">
306
				<?php
307
308
				$wp_plugins = $this->get_wp_plugins_data();
309
310
				foreach ( $downloads_data as $extension ) {
311
312
					if ( empty( $extension['info'] ) ) {
313
						continue;
314
					}
315
316
					if ( 'gravityview' === \GV\Utils::get( $extension, 'info/slug' ) ) {
317
						continue;
318
					}
319
320
					$this->render_download( $extension, $wp_plugins );
321
				}
322
				?>
323
            </div>
324
        </div>
325
		<?php
326
	}
327
328
	/**
329
	 * Outputs the HTML of a single download
330
	 *
331
	 * @param array $download Download data, as returned from EDD API
332
	 * @param array $wp_plugins
333
	 *
334
	 * @return void
335
	 */
336
	protected function render_download( $download, $wp_plugins ) {
337
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
338
339
        $details = $this->get_download_display_details( $download, $wp_plugins );
340
341
        $download_info = $details['download_info'];
342
343
		?>
344
        <div class="item <?php echo esc_attr( $details['item_class'] ); ?>">
345
            <div class="addon-inner">
346
                <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>
347
                <h3><?php echo esc_html( $download_info['title'] ); ?></h3>
348
                <div>
349
                    <?php if( $details['status_label'] ) { ?>
350
                    <div class="status <?php echo esc_attr( $details['status'] ); ?>" title="<?php printf( esc_attr__( 'Plugin status: %s', 'gravityview' ), esc_html( $details['status_label'] ) ); ?>">
351
                        <span class="dashicons dashicons-admin-plugins"></span> <span class="status-label"><?php echo esc_html( $details['status_label'] ); ?></span>
352
                    </div>
353
			        <?php } ?>
354
355
                    <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'] ); ?>">
356
                        <span class="title"><?php echo esc_html( $details['button_label'] ); ?></span>
357
                        <?php if( $details['spinner'] ) { ?><span class="spinner"></span><?php } ?>
358
                    </a>
359
                </div>
360
361
                <div class="addon-excerpt">
362
					<?php echo wpautop( esc_html( $download_info['excerpt'] ) ); ?>
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'wpautop'
Loading history...
363
                </div>
364
            </div>
365
        </div>
366
		<?php
367
	}
368
369
	/**
370
     * Generates details array for the download to keep the render_download() method a bit tidier
371
     *
372
	 * @param array $download Single download, as returned by {@see get_downloads_data}
373
	 * @param array $wp_plugins All active plugins, as returned by {@see get_plugins()}
374
	 *
375
	 * @return array {
376
     *   @type array $download_info
377
     *   @type string $plugin_path
378
     *   @type string $status License status returned by Easy Digital Downloads ("active", "inactive", "expired", "revoked", etc)
379
     *   @type string $status_label
380
     *   @type string $button_title Title attribute to show when hovering over the download's button
381
     *   @type string $button_class CSS class to use for the button
382
     *   @type string $button_label Text to use for the download's anchor link
383
     *   @type string $href URL for the download's button
384
     *   @type bool   $spinner Whether to show the spinner icon
385
     *   @type string $item_class CSS class for the download container
386
     *   @type string $required_license The name of the required license for the download ("Galactic" or "Interstellar")
387
     *   @type bool   $is_active Is the current GravityView license (as entered in Settings) active?
388
     * }
389
	 */
390
	private function get_download_display_details( $download, $wp_plugins ) {
391
392
		$download_info = wp_parse_args( (array) $download['info'], array(
393
			'thumbnail' => '',
394
			'title' => '',
395
			'textdomain' => '',
396
			'slug' => '',
397
			'excerpt' => '',
398
			'link' => '',
399
		) );
400
401
		$wp_plugin = \GV\Utils::get( $wp_plugins, $download_info['textdomain'], false );
402
403
		$has_access = ! empty( $download['files'] );
404
		$spinner = true;
405
		$href = $plugin_path = '#';
406
		$status = $item_class = $button_title = $button_class = '';
407
		$base_price = $this->get_download_base_price( $download );
408
		$is_active = in_array( gravityview()->plugin->settings->get( 'license_key_response/license' ), array( 'active', 'valid' ), true );
409
		$galactic_only = in_array( \GV\Utils::get( $download, 'info/category/0/slug' ), array( 'plugins', 'views' ) );
410
		$required_license = $galactic_only ? __( 'Galactic', 'gravityview' ) : __( 'Interstellar', 'gravityview' );
411
412
		// The license is not active - no matter what level, this should not work
413
		if( ! $is_active  && empty( $base_price ) ) {
414
			$spinner      = false;
415
			$button_class = 'disabled disabled-license';
416
			$button_label = sprintf( __( 'Active %s License is Required.', 'gravityview' ), $required_license );
417
		}
418
419
		// No access with the current license level, and the download is available to purchase
420
		else if ( ! $has_access && ! empty( $base_price ) ) {
421
			$spinner      = false;
422
			$status_label = '';
423
			$button_label = sprintf( __( 'Purchase Now for %s', 'gravityview' ), '$' . $base_price );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$base_price'
Loading history...
424
			$button_class = 'button-primary button-large';
425
			$href         = $download_info['link'];
426
			$item_class   = 'featured';
427
		}
428
429
		// No access with the current license level, and the download is not sold separately
430
		else if ( ! $has_access && $is_active ) {
431
			$spinner      = false;
432
			$status_label = '';
433
			$button_label = sprintf( __( 'Upgrade to %s for Access', 'gravityview' ), $required_license );
434
			$button_class = 'button-primary button-large';
435
			$href         = 'https://gravityview.co/pricing/?utm_source=admin-installer&utm_medium=admin&utm_campaign=Admin%20Notice&utm_content=' . $required_license;
436
		}
437
438
		// Access but the plugin is not installed
439
		else if ( ! $wp_plugin ) {
440
441
			$href = add_query_arg(
442
				array(
443
					'action'   => 'install-plugin',
444
					'plugin'   => $download_info['slug'],
445
					'_wpnonce' => wp_create_nonce( 'install-plugin_' . $download_info['slug'] ),
446
				),
447
				self_admin_url( 'update.php' )
448
			);
449
450
			$status = 'notinstalled';
451
			$status_label = __( 'Not Installed', 'gravityview' );
452
			$button_label = __( 'Install', 'gravityview' );
453
454
		}
455
456
		// Access and the plugin is installed but not active
457
		else if ( false === $wp_plugin['activated'] ) {
458
459
			$status = 'inactive';
460
			$status_label = __( 'Inactive', 'gravityview' );
461
			$button_label = __( 'Activate', 'gravityview' );
462
			$plugin_path = $wp_plugin['path'];
463
464
		}
465
466
		// Access and the plugin is installed and active
467
		else {
468
469
			$plugin_path = $wp_plugin['path'];
470
			$status = 'active';
471
			$status_label = __( 'Active', 'gravityview' );
472
			$button_label = __( 'Deactivate', 'gravityview' );
473
474
		}
475
476
		return compact( 'download_info','plugin_path', 'status', 'status_label', 'button_title', 'button_class', 'button_label', 'href', 'spinner', 'item_class', 'required_license', 'is_active' );
477
    }
478
479
	/**
480
     * Returns the base price for an extension
481
     *
482
	 * @param array $download
483
	 *
484
	 * @return float Base price for an extension. If not for sale separately, returns 0
485
	 */
486
	private function get_download_base_price( $download ) {
487
488
	    $base_price = \GV\Utils::get( $download, 'pricing/amount', 0 );
489
		$base_price = \GFCommon::to_number( $base_price );
490
491
		unset( $download['pricing']['amount'] );
492
493
		// Price options array, not single price
494
		if ( ! $base_price && ! empty( $download['pricing'] ) ) {
495
			$base_price = array_shift( $download['pricing'] );
496
		}
497
498
		return floatval( $base_price );
499
    }
500
501
	/**
502
	 * Handle AJAX request to activate extension
503
	 *
504
	 * @return void Exits with JSON response
505
	 */
506
	public function activate_download() {
507
		$data = \GV\Utils::_POST( 'data', array() );
508
509
		if ( empty( $data['path'] ) ) {
510
			return;
511
		}
512
513
		$result = activate_plugin( $data['path'] );
514
515
		if ( is_wp_error( $result ) || ! is_plugin_active( $data['path'] ) ) {
516
			wp_send_json_error( array(
517
                'error' => sprintf( __( 'Plugin activation failed: %s', 'gravityview' ), $result->get_error_message() )
518
            ) );
519
		}
520
521
		wp_send_json_success();
522
	}
523
524
	/**
525
	 * Handle AJAX request to deactivate extension
526
	 *
527
	 * @return void Send JSON response status and error message
528
	 */
529
	public function deactivate_download() {
530
		$data = \GV\Utils::_POST( 'data', array() );
531
532
		if ( empty( $data['path'] ) ) {
533
			return;
534
		}
535
536
		deactivate_plugins( $data['path'] );
537
538
		if( is_plugin_active( $data['path'] ) ) {
539
            wp_send_json_error( array(
540
                'error' => sprintf( __( 'Plugin deactivation failed.', 'gravityview' ) )
541
            ) );
542
        }
543
544
		wp_send_json_success();
545
	}
546
547
	/**
548
	 * Register and enqueue assets; localize script
549
	 *
550
	 * @return void
551
	 */
552
	public function maybe_enqueue_scripts_and_styles() {
553
554
		if ( ! gravityview()->request->is_admin( '', 'downloads' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to Request::is_admin() has too many arguments starting with ''.

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.

Loading history...
555
			return;
556
		}
557
558
		$script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
559
560
		wp_enqueue_style( 'gravityview-admin-installer', GRAVITYVIEW_URL . 'assets/css/admin-installer.css', array(), \GV\Plugin::$version );
561
562
		wp_enqueue_script( 'gravityview-admin-installer', GRAVITYVIEW_URL . 'assets/js/admin-installer' . $script_debug . '.js', array( 'jquery' ), \GV\Plugin::$version, true );
563
564
		wp_localize_script( 'gravityview-admin-installer', 'gvAdminInstaller', array(
565
			'activateErrorLabel'    => __( 'Plugin activation failed.', 'gravityview' ),
566
			'deactivateErrorLabel'  => __( 'Plugin deactivation failed.', 'gravityview' ),
567
			'activeStatusLabel'     => __( 'Active', 'gravityview' ),
568
			'inactiveStatusLabel'   => __( 'Inactive', 'gravityview' ),
569
			'activateActionLabel'   => __( 'Activate', 'gravityview' ),
570
			'deactivateActionLabel' => __( 'Deactivate', 'gravityview' )
571
		) );
572
	}
573
}
574
575
new GravityView_Admin_Installer;
576