Completed
Push — develop ( b9a07b...9c0de7 )
by Zack
17:18
created

Extension::add_notice()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 5.9256

Importance

Changes 0
Metric Value
cc 5
eloc 8
nc 5
nop 1
dl 0
loc 13
ccs 4
cts 6
cp 0.6667
crap 5.9256
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 1
	public function __construct() {
81 1
		if ( false === $this->is_extension_supported() ) {
82 1
			return;
83
		}
84
85 1
		if ( ! $this->_path ) {
86 1
			$this->_path = __FILE__;
87
		}
88
89 1
		add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
90
91 1
		add_action( 'admin_init', array( $this, 'settings' ) );
92
93 1
		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 1
		add_action( 'save_post', array( $this, 'save_post' ), 14 );
97
98 1
		add_action( 'gravityview/metaboxes/before_render', array( $this, 'add_metabox_tab' ) );
99
100 1
		add_filter( 'gravityview/metaboxes/tooltips', array( $this, 'tooltips' ) );
101
102 1
		$this->add_hooks();
103 1
	}
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 1
	public function tooltips( $tooltips = array() ) {
138 1
		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 1
	public function add_metabox_tab() {
162 1
		$tab_settings = $this->tab_settings();
163
164
		// Don't add a tab if it's empty.
165 1
		if ( empty( $tab_settings ) ) {
166
			return;
167
		}
168
169
		$tab_defaults = array(
170 1
			'id' => '',
171
			'title' => '',
172
			'callback' => '',
173
			'icon-class' => '',
174
			'file' => '',
175
			'callback_args' => '',
176
			'context' => 'side',
177
			'priority' => 'default',
178
		);
179
180 1
		$tab = wp_parse_args( $tab_settings, $tab_defaults );
181
182
		// Force the screen to be GravityView
183 1
		$tab['screen'] = 'gravityview';
184
185 1
		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 1
			add_meta_box( 'gravityview_' . $tab['id'], $tab['title'], $tab['callback'], $tab['screen'], $tab['context'], $tab['priority'] );
190
		}
191 1
	}
192
193
	/**
194
	 * Is this extension even compatible?
195
	 *
196
	 * @return boolean|null Is or is not. Null if unknown yet.
197
	 */
198 1
	public static function is_compatible() {
199 1
		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 1
	protected function is_extension_supported() {
213
214 1
		self::$is_compatible = is_array( self::$is_compatible ) ? self::$is_compatible : array( get_called_class() => (bool) self::$is_compatible );
215
216 1
		if ( ! function_exists( 'gravityview' ) ) {
217
			$message = sprintf( __( 'Could not activate the %s Extension; GravityView is not active.', 'gravityview' ), esc_html( $this->_title ) );
218 1
		} 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 1
			$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 1
		} 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 1
		} 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 1
			$message = '';
226 1
			self::$is_compatible[ get_called_class() ] = gravityview()->plugin->is_compatible();
227
		}
228
229 1
		if ( ! empty( $message ) ) {
230 1
			self::add_notice( $message );
231 1
			self::$is_compatible[ get_called_class() ] = false;
232 1
			gravityview()->log->error( '{message}', array( 'message' => $message ) );
233
		}
234
235 1
		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 1
	public function load_plugin_textdomain() {
248 1
		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 1
		$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 1
		$lang_dir = dirname( plugin_basename( $path ) ) . '/languages/';
258
259 1
		$locale = get_locale();
260
261 1
		if ( function_exists('get_user_locale') && is_admin() ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
262
			$locale = get_user_locale();
263
		}
264
265
		// Traditional WordPress plugin locale filter
266 1
		$locale = apply_filters( 'plugin_locale',  $locale, $this->_text_domain );
267
268 1
		$mofile = sprintf( '%1$s-%2$s.mo', $this->_text_domain, $locale );
269
270
		// Setup paths to current locale file
271 1
		$mofile_local  = $lang_dir . $mofile;
272 1
		$mofile_global = WP_LANG_DIR . '/' . $this->_text_domain . '/' . $mofile;
273
274 1
		if ( file_exists( $mofile_global ) ) {
275
			// Look in global /wp-content/languages/[plugin-dir]/ folder
276
			load_textdomain( $this->_text_domain, $mofile_global );
277 1
		} elseif ( file_exists( $mofile_local ) ) {
278
			// Look in local /wp-content/plugins/[plugin-dir]/languages/ folder
279
			load_textdomain( $this->_text_domain, $mofile_local );
280
		} else {
281
			// Load the default language files
282 1
			load_plugin_textdomain( $this->_text_domain, false, $lang_dir );
283
		}
284 1
	}
285
286
	/**
287
	 * Register the updater for the Extension using GravityView license information
288
	 *
289
	 * @return void
290
	 */
291 1
	public function settings() {
292
293 1
		// If doing ajax, get outta here
294
		if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX && 'update-plugin' !== Utils::_POST('action') ) )  {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
295
			return;
296
		}
297 1
298
		$license = $this->get_license();
299 1
300
		if ( ! class_exists( '\GV\EDD_SL_Plugin_Updater' ) ) {
301
			require_once gravityview()->plugin->dir( 'future/lib/EDD_SL_Plugin_Updater.php' );
302
		}
303
304 1
		new EDD_SL_Plugin_Updater(
305
			$this->_remote_update_url,
306
			$this->_path,
307
			array(
308 1
            	'version'	=> $this->_version, // current version number
309 1
            	'license'	=> $license['license'],
310 1
	            'item_id'   => $this->_item_id, // The ID of the download on _remote_update_url
311
            	'item_name' => $this->_title,  // name of this plugin
312 1
            	'author' 	=> strip_tags( $this->_author )  // author of this plugin
313 1
          	)
314 1
        );
315 1
	}
316 1
317
	/**
318
	 * Get license information from GravityView
319 1
	 *
320
	 * @since 1.8 (Extension version 1.0.7)
321
	 *
322
	 * @return bool|array False: \GV\Addon_Settings class does not exist. Array: array of GV license data.
323
	 */
324
	protected function get_license() {
325
		if ( ! class_exists( '\GV\Addon_Settings' ) ) {
326
			return false;
327
		}
328 1
		return gravityview()->plugin->settings->get( 'license' );
329 1
	}
330
331
	/**
332 1
	 * Add a notice to be displayed in the admin.
333
	 *
334
	 * @param array $notice Array with `class` and `message` keys. The message is not escaped.
335
	 *
336
	 * @return void
337
	 */
338
	public static function add_notice( $notice = array() ) {
339
340
		if ( is_array( $notice ) && empty( $notice['message'] ) ) {
341
			gravityview()->log->error( 'Notice not set', array( 'data' => $notice ) );
342 1
			return;
343
		} else if ( is_string( $notice ) ) {
344 1
			$notice = array( 'message' => $notice );
345
		}
346
347 1
		$notice['class'] = empty( $notice['class'] ) ? 'error' : $notice['class'];
348 1
349
		self::$admin_notices []= $notice;
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
350
	}
351 1
352
	/**
353 1
	 * Outputs the admin notices generated by the all plugins
354 1
	 *
355
	 * @return void
356
	 */
357
	public function admin_notice() {
358
		if ( empty( self::$admin_notices ) ) {
359
			return;
360
		}
361 1
362 1
		foreach ( self::$admin_notices as $key => $notice ) {
363
			echo '<div id="message" class="'. esc_attr( $notice['class'] ).'">';
364
			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...
365
			echo '<div class="clear"></div>';
366 1
			echo '</div>';
367 1
		}
368 1
369 1
		//reset the notices handler
370 1
		self::$admin_notices = array();
371
	}
372
}
373