Completed
Push — develop ( d6e54c...488d60 )
by Zack
17:10
created

Extension::add_metabox_tab()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 20
nc 3
nop 0
dl 0
loc 31
rs 8.8571
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 14 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
namespace GV;
3
4
/** If this file is called directly, abort. */
5
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6
	die();
7
}
8
9
/**
10
 * The \GV\Extension class.
11
 *
12
 * An interface that most extensions would want to adhere to and inherit from.
13
 */
14
abstract class Extension {
15
	/**
16
	 * @var string Name of the plugin in gravityview.co
17
	 */
18
	protected $_title = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
19
20
	/**
21
	 * @var string Version number of the plugin
22
	 */
23
	protected $_version = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
24
25
	/**
26
	 * @var int The ID of the download on gravityview.co
27
	 * @since 1.1
28
	 */
29
	protected $_item_id = NULL;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected null, but found NULL.
Loading history...
30
31
	/**
32
	 * @var string Translation textdomain
33
	 */
34
	protected $_text_domain = 'gravityview';
35
36
	/**
37
	 * @var string Minimum version of GravityView the Extension requires
38
	 */
39
	protected $_min_gravityview_version = '2.0-dev';
40
41
	/**
42
	 * @var string Maximum version of GravityView the Extension requires, if any
43
	 */
44
	protected $_max_gravityview_version = null;
45
46
	/**
47
	 * @var string Minimum version of GravityView the Extension requires
48
	 */
49
	protected $_min_php_version = '5.3';
50
51
	/**
52
	 * @var string The URL to fetch license info from. Do not change unless you know what you're doing.
53
	 */
54
	protected $_remote_update_url = 'https://gravityview.co';
55
56
	/**
57
	 * @var string Author of plugin, sent when fetching license info.
58
	 */
59
	protected $_author = 'Katz Web Services, Inc.';
60
61
	/**
62
	 * @var string The path to the extension.
63
	 */
64
	protected $_path = '';
65
66
	/**
67
	 * @var array Admin notices to display
68
	 */
69
	static protected $admin_notices = array();
70
71
	/**
72
	 * @var boolean[] An array of extension compatibility.
73
	 * @since 2.0 This is an array of classes instead.
74
	 */
75
	static public $is_compatible = array();
76
77
	/**
78
	 * Generic initialization.
79
	 */
80
	public function __construct() {
81
		if ( false === $this->is_extension_supported() ) {
82
			return;
83
		}
84
85
		if ( ! $this->_path ) {
86
			$this->_path = __FILE__;
87
		}
88
89
		add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
90
91
		add_action( 'admin_init', array( $this, 'settings' ) );
92
93
		add_action( 'admin_notices', array( $this, 'admin_notice' ), 100 );
94
95
		// Save the view configuration. Run at 14 so that View metadata is already saved (at 10)
96
		add_action( 'save_post', array( $this, 'save_post' ), 14 );
97
98
		add_action( 'gravityview/metaboxes/before_render', array( $this, 'add_metabox_tab' ) );
99
100
		add_filter( 'gravityview/metaboxes/tooltips', array( $this, 'tooltips' ) );
101
102
		$this->add_hooks();
103
	}
104
105
	/**
106
	 * Extensions should override this hook to add their hooks.
107
	 *
108
	 * @return void
109
	 */
110
	public function add_hooks() { }
111
112
	/**
113
	 * Save extra view configuration.
114
	 *
115
	 * @param  int $post_id Post ID
116
	 * @return void
117
	 */
118
	public function save_post( $post_id ) { }
0 ignored issues
show
Unused Code introduced by
The parameter $post_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
119
120
	/**
121
	 * Add tooltips for the extension.
122
	 *
123
	 * Add a tooltip with an array using the `title` and `value` keys. The `title` key is the H6 tag value of the tooltip; it's the headline. The `value` is the tooltip content, and can contain any HTML.
124
	 *
125
	 * The tooltip key must be `gv_{name_of_setting}`. If the name of the setting is "example_extension_setting", the code would be:
126
	 *
127
	 * <code>
128
	 * $tooltips['gv_example_extension_setting'] = array(
129
	 * 	'title'	=> 'About Example Extension Setting',
130
	 *  'value'	=> 'When you do [x] with [y], [z] happens.'
131
	 * );
132
	 * </code>
133
	 *
134
	 * @param  array $tooltips Existing GV tooltips, with `title` and `value` keys
135
	 * @return array Modified tooltips
136
	 */
137
	public function tooltips( $tooltips = array() ) {
138
		return $tooltips;
139
	}
140
141
	/**
142
	 * Add a tab to GravityView Edit View tabbed metabox. By overriding this method, you will add a tab to View settings
143
	 *
144
	 * @since 1.8 (Extension version 1.0.7)
145
	 * @see https://gist.github.com/zackkatz/6cc381bcf54849f2ed41 For example of adding a metabox
146
	 *
147
	 * @return array Array of metabox
148
	 */
149
	protected function tab_settings() {
150
		// When overriding, return array with expected keys
151
		return array();
152
	}
153
154
	/**
155
	 * If Extension overrides tab_settings() and passes its own tab, add it to the tabbed settings metabox
156
	 *
157
	 * @since 1.8 (Extension version 1.0.7)
158
	 *
159
	 * @return void
160
	 */
161
	public function add_metabox_tab() {
162
		$tab_settings = $this->tab_settings();
163
164
		// Don't add a tab if it's empty.
165
		if ( empty( $tab_settings ) ) {
166
			return;
167
		}
168
169
		$tab_defaults = array(
170
			'id' => '',
171
			'title' => '',
172
			'callback' => '',
173
			'icon-class' => '',
174
			'file' => '',
175
			'callback_args' => '',
176
			'context' => 'side',
177
			'priority' => 'default',
178
		);
179
180
		$tab = wp_parse_args( $tab_settings, $tab_defaults );
181
182
		// Force the screen to be GravityView
183
		$tab['screen'] = 'gravityview';
184
185
		if ( class_exists( 'GravityView_Metabox_Tab' ) ) {
186
			$metabox = new \GravityView_Metabox_Tab( $tab['id'], $tab['title'], $tab['file'], $tab['icon-class'], $tab['callback'], $tab['callback_args'] );
187
			\GravityView_Metabox_Tabs::add( $metabox );
188
		} else {
189
			add_meta_box( 'gravityview_' . $tab['id'], $tab['title'], $tab['callback'], $tab['screen'], $tab['context'], $tab['priority'] );
190
		}
191
	}
192
193
	/**
194
	 * Is this extension even compatible?
195
	 *
196
	 * @return boolean|null Is or is not. Null if unknown yet.
197
	 */
198
	public static function is_compatible() {
199
		return Utils::get( self::$is_compatible, get_called_class(), null );
200
	}
201
202
	/**
203
	 * Check whether the extension is supported:
204
	 *
205
	 * - Checks if GravityView and Gravity Forms exist
206
	 * - Checks GravityView and Gravity Forms version numbers
207
	 * - Checks PHP version numbers
208
	 * - Sets self::$is_compatible[__CLASS__] to boolean value
209
	 *
210
	 * @return boolean Is the extension supported?
211
	 */
212
	protected function is_extension_supported() {
213
214
		self::$is_compatible = is_array( self::$is_compatible ) ? self::$is_compatible : array( get_called_class() => (bool) self::$is_compatible );
215
216
		if ( ! function_exists( 'gravityview' ) ) {
217
			$message = sprintf( __( 'Could not activate the %s Extension; GravityView is not active.', 'gravityview' ), esc_html( $this->_title ) );
218
		} else if ( false === version_compare( Plugin::$version, $this->_min_gravityview_version , ">=" ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal >= 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...
219
			$message = sprintf( __( 'The %s Extension requires GravityView Version %s or newer.', 'gravityview' ), esc_html( $this->_title ), '<tt>'.$this->_min_gravityview_version.'</tt>' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
220
		} else if ( isset( $this->_min_php_version ) && false === version_compare( phpversion(), $this->_min_php_version , ">=" ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal >= 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...
221
			$message = sprintf( __( 'The %s Extension requires PHP Version %s or newer. Please ask your host to upgrade your server\'s PHP.', 'gravityview' ), esc_html( $this->_title ), '<tt>'.$this->_min_php_version.'</tt>' );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
222
		} else if ( ! empty( $this->_max_gravityview_version ) && false === version_compare( $this->_max_gravityview_version, Plugin::$version, ">" ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal > 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...
223
			$message = sprintf( __( 'The %s Extension is not compatible with this version of GravityView. Please update the Extension to the latest version.', 'gravityview' ), esc_html( $this->_title ) );
224
		} else {
225
			$message = '';
226
			self::$is_compatible[ get_called_class() ] = gravityview()->plugin->is_compatible();
227
		}
228
229
		if ( ! empty( $message ) ) {
230
			self::add_notice( $message );
231
			self::$is_compatible[ get_called_class() ] = false;
232
			gravityview()->log->error( '{message}', array( 'message' => $message ) );
233
		}
234
235
		return self::is_compatible();
236
	}
237
238
	/**
239
	 * Load translations for the extension
240
	 *
241
	 * 1. Check  `wp-content/languages/gravityview/` folder and load using `load_textdomain()`
242
	 * 2. Check  `wp-content/plugins/gravityview/languages/` folder for `gravityview-[locale].mo` file and load using `load_textdomain()`
243
	 * 3. Load default file using `load_plugin_textdomain()` from `wp-content/plugins/gravityview/languages/`
244
	 *
245
	 * @return void
246
	 */
247
	public function load_plugin_textdomain() {
248
		if ( empty( $this->_text_domain ) ) {
249
			gravityview()->log->debug( 'Extension translation cannot be loaded; the `_text_domain` variable is not defined', array( 'data' => $this ) );
250
			return;
251
		}
252
253
		// Backward compat for Ratings & Reviews / Maps
254
		$path = isset( $this->_path ) ? $this->_path : ( isset( $this->plugin_file ) ? $this->plugin_file : '' );
0 ignored issues
show
Bug introduced by
The property plugin_file does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
255
256
		// Set filter for plugin's languages directory
257
		$lang_dir = dirname( plugin_basename( $path ) ) . '/languages/';
258
259
		// Traditional WordPress plugin locale filter
260
		$locale = apply_filters( 'plugin_locale',  get_locale(), $this->_text_domain );
261
262
		$mofile = sprintf( '%1$s-%2$s.mo', $this->_text_domain, $locale );
263
264
		// Setup paths to current locale file
265
		$mofile_local  = $lang_dir . $mofile;
266
		$mofile_global = WP_LANG_DIR . '/' . $this->_text_domain . '/' . $mofile;
267
268
		if ( file_exists( $mofile_global ) ) {
269
			// Look in global /wp-content/languages/[plugin-dir]/ folder
270
			load_textdomain( $this->_text_domain, $mofile_global );
271
		} elseif ( file_exists( $mofile_local ) ) {
272
			// Look in local /wp-content/plugins/[plugin-dir]/languages/ folder
273
			load_textdomain( $this->_text_domain, $mofile_local );
274
		} else {
275
			// Load the default language files
276
			load_plugin_textdomain( $this->_text_domain, false, $lang_dir );
277
		}
278
	}
279
280
	/**
281
	 * Register the updater for the Extension using GravityView license information
282
	 *
283
	 * @return void
284
	 */
285
	public function settings() {
286
		// If doing ajax, get outta here
287
		if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )  {
288
			return;
289
		}
290
291
		$license = $this->get_license();
292
293
		if ( ! class_exists( '\GV\EDD_SL_Plugin_Updater' ) ) {
294
			require_once gravityview()->plugin->dir( 'future/lib/EDD_SL_Plugin_Updater.php' );
295
		}
296
297
		// Don't update if invalid license.
298
		if ( false === $license || empty( $license['status'] ) || strtolower( $license['status'] ) !== 'valid' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
299
			return;
300
		}
301
302
		new EDD_SL_Plugin_Updater(
303
			$this->_remote_update_url,
304
			$this->_path,
305
			array(
306
            	'version'	=> $this->_version, // current version number
307
            	'license'	=> $license['license'],
308
	            'item_id'   => $this->_item_id, // The ID of the download on _remote_update_url
309
            	'item_name' => $this->_title,  // name of this plugin
310
            	'author' 	=> strip_tags( $this->_author )  // author of this plugin
311
          	)
312
        );
313
	}
314
315
	/**
316
	 * Get license information from GravityView
317
	 *
318
	 * @since 1.8 (Extension version 1.0.7)
319
	 *
320
	 * @return bool|array False: \GV\Addon_Settings class does not exist. Array: array of GV license data.
321
	 */
322
	protected function get_license() {
323
		if ( ! class_exists( '\GV\Addon_Settings' ) ) {
324
			return false;
325
		}
326
		return gravityview()->plugin->settings->get( 'license' );
327
	}
328
329
	/**
330
	 * Add a notice to be displayed in the admin.
331
	 *
332
	 * @param array $notice Array with `class` and `message` keys. The message is not escaped.
333
	 *
334
	 * @return void
335
	 */
336
	public static function add_notice( $notice = array() ) {
337
338
		if ( is_array( $notice ) && empty( $notice['message'] ) ) {
339
			gravityview()->log->error( 'Notice not set', array( 'data' => $notice ) );
340
			return;
341
		} else if ( is_string( $notice ) ) {
342
			$notice = array( 'message' => $notice );
343
		}
344
345
		$notice['class'] = empty( $notice['class'] ) ? 'error' : $notice['class'];
346
347
		self::$admin_notices []= $notice;
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
348
	}
349
350
	/**
351
	 * Outputs the admin notices generated by the all plugins
352
	 *
353
	 * @return void
354
	 */
355
	public function admin_notice() {
356
		if ( empty( self::$admin_notices ) ) {
357
			return;
358
		}
359
360
		foreach ( self::$admin_notices as $key => $notice ) {
361
			echo '<div id="message" class="'. esc_attr( $notice['class'] ).'">';
362
			echo wpautop( $notice['message'] );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'wpautop'
Loading history...
363
			echo '<div class="clear"></div>';
364
			echo '</div>';
365
		}
366
367
		//reset the notices handler
368
		self::$admin_notices = array();
369
	}
370
}
371