1
|
|
|
<?php |
|
|
|
|
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; |
|
|
|
|
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var string Version number of the plugin |
22
|
|
|
*/ |
23
|
|
|
protected $_version = NULL; |
|
|
|
|
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var int The ID of the download on gravityview.co |
27
|
|
|
* @since 1.1 |
28
|
|
|
*/ |
29
|
|
|
protected $_item_id = NULL; |
|
|
|
|
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 ) { } |
|
|
|
|
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 , ">=" ) ) { |
|
|
|
|
219
|
1 |
|
$message = sprintf( __( 'The %s Extension requires GravityView Version %s or newer.', 'gravityview' ), esc_html( $this->_title ), '<tt>'.$this->_min_gravityview_version.'</tt>' ); |
|
|
|
|
220
|
1 |
|
} else if ( isset( $this->_min_php_version ) && false === version_compare( phpversion(), $this->_min_php_version , ">=" ) ) { |
|
|
|
|
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>' ); |
|
|
|
|
222
|
1 |
|
} else if ( ! empty( $this->_max_gravityview_version ) && false === version_compare( $this->_max_gravityview_version, Plugin::$version, ">" ) ) { |
|
|
|
|
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 : '' ); |
|
|
|
|
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() ) { |
|
|
|
|
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') ) ) { |
|
|
|
|
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; |
|
|
|
|
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'] ); |
|
|
|
|
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
|
|
|
|
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.