|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Shortcode Dialog Generator abstract class |
|
4
|
|
|
* |
|
5
|
|
|
* @package Give/Admin |
|
6
|
|
|
* @author Paul Ryley |
|
7
|
|
|
* @copyright Copyright (c) 2016, WordImpress |
|
8
|
|
|
* @license https://opensource.org/licenses/gpl-license GNU Public License |
|
9
|
|
|
* @version 1.0 |
|
10
|
|
|
* @since 1.3 |
|
11
|
|
|
*/ |
|
12
|
|
|
|
|
13
|
|
|
// Exit if accessed directly. |
|
14
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
|
15
|
|
|
exit; |
|
16
|
|
|
} |
|
17
|
|
|
|
|
18
|
|
|
/** |
|
19
|
|
|
* Class Give_Shortcode_Generator |
|
20
|
|
|
*/ |
|
21
|
|
|
abstract class Give_Shortcode_Generator { |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* The current class name |
|
25
|
|
|
* |
|
26
|
|
|
* @since 1.0 |
|
27
|
|
|
*/ |
|
28
|
|
|
public $self; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* The current shortcode |
|
32
|
|
|
* |
|
33
|
|
|
* @since 1.0 |
|
34
|
|
|
*/ |
|
35
|
|
|
public $shortcode; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* The current shortcode tag |
|
39
|
|
|
* |
|
40
|
|
|
* @since 1.0 |
|
41
|
|
|
*/ |
|
42
|
|
|
public $shortcode_tag; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* Shortcode field errors |
|
46
|
|
|
* |
|
47
|
|
|
* @since 1.0 |
|
48
|
|
|
*/ |
|
49
|
|
|
protected $errors; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* Required shortcode fields |
|
53
|
|
|
* |
|
54
|
|
|
* @since 1.0 |
|
55
|
|
|
*/ |
|
56
|
|
|
protected $required; |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* Class constructor |
|
60
|
|
|
* |
|
61
|
|
|
* @param string $shortcode The shortcode tag |
|
62
|
|
|
* |
|
63
|
|
|
* @since 1.0 |
|
64
|
|
|
*/ |
|
65
|
|
|
public function __construct( $shortcode ) { |
|
66
|
|
|
|
|
67
|
|
|
$this->shortcode_tag = $shortcode; |
|
68
|
|
|
|
|
69
|
|
|
add_action( 'admin_init', array( $this, 'init' ) ); |
|
70
|
|
|
|
|
71
|
|
|
} |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* Kick things off for the shortcode generator |
|
75
|
|
|
* |
|
76
|
|
|
* @since 1.3.0.2 |
|
77
|
|
|
*/ |
|
78
|
|
|
public function init() { |
|
79
|
|
|
|
|
80
|
|
|
if ( $this->shortcode_tag ) { |
|
81
|
|
|
|
|
82
|
|
|
$this->self = get_class( $this ); |
|
83
|
|
|
|
|
84
|
|
|
$this->errors = array(); |
|
85
|
|
|
$this->required = array(); |
|
86
|
|
|
|
|
87
|
|
|
// Generate the fields, errors, and requirements |
|
88
|
|
|
$fields = $this->get_fields(); |
|
89
|
|
|
|
|
90
|
|
|
$defaults = array( |
|
91
|
|
|
'btn_close' => esc_html__( 'Close', 'give' ), |
|
92
|
|
|
'btn_okay' => esc_html__( 'Insert Shortcode', 'give' ), |
|
93
|
|
|
'errors' => $this->errors, |
|
94
|
|
|
'fields' => $fields, |
|
95
|
|
|
'label' => '[' . $this->shortcode_tag . ']', |
|
96
|
|
|
'required' => $this->required, |
|
97
|
|
|
'title' => esc_html__( 'Insert Shortcode', 'give' ), |
|
98
|
|
|
); |
|
99
|
|
|
|
|
100
|
|
|
if ( user_can_richedit() ) { |
|
101
|
|
|
|
|
102
|
|
|
Give_Shortcode_Button::$shortcodes[ $this->shortcode_tag ] = wp_parse_args( $this->shortcode, $defaults ); |
|
103
|
|
|
|
|
104
|
|
|
} |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
|
|
110
|
|
|
/** |
|
111
|
|
|
* Define the shortcode attribute fields |
|
112
|
|
|
* |
|
113
|
|
|
* @return false|array |
|
114
|
|
|
* |
|
115
|
|
|
* @since 1.0 |
|
116
|
|
|
*/ |
|
117
|
|
|
public function define_fields() { |
|
118
|
|
|
|
|
119
|
|
|
return false; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Generate the shortcode dialog fields |
|
124
|
|
|
* |
|
125
|
|
|
* @param array $defined_fields |
|
126
|
|
|
* |
|
127
|
|
|
* @return array |
|
128
|
|
|
* |
|
129
|
|
|
* @since 1.0 |
|
130
|
|
|
*/ |
|
131
|
|
|
protected function generate_fields( $defined_fields ) { |
|
132
|
|
|
|
|
133
|
|
|
$fields = array(); |
|
134
|
|
|
|
|
135
|
|
|
if ( is_array( $defined_fields ) ) { |
|
136
|
|
|
|
|
137
|
|
|
foreach ( $defined_fields as $field ) { |
|
138
|
|
|
|
|
139
|
|
|
$defaults = array( |
|
140
|
|
|
'label' => false, |
|
141
|
|
|
'name' => false, |
|
142
|
|
|
'options' => array(), |
|
143
|
|
|
'placeholder' => false, |
|
144
|
|
|
'tooltip' => false, |
|
145
|
|
|
'type' => '', |
|
146
|
|
|
); |
|
147
|
|
|
|
|
148
|
|
|
$field = wp_parse_args( (array) $field, $defaults ); |
|
149
|
|
|
$method = 'generate_' . strtolower( $field['type'] ); |
|
150
|
|
|
|
|
151
|
|
|
if ( method_exists( $this, $method ) ) { |
|
152
|
|
|
|
|
153
|
|
|
$field = call_user_func( array( $this, $method ), $field ); |
|
154
|
|
|
|
|
155
|
|
|
if ( $field ) { |
|
156
|
|
|
$fields[] = $field; |
|
157
|
|
|
} |
|
158
|
|
|
} |
|
159
|
|
|
} |
|
160
|
|
|
} |
|
161
|
|
|
|
|
162
|
|
|
return $fields; |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
/** |
|
166
|
|
|
* Get the generated shortcode dialog fields |
|
167
|
|
|
* |
|
168
|
|
|
* @return array |
|
169
|
|
|
* |
|
170
|
|
|
* @since 1.0 |
|
171
|
|
|
*/ |
|
172
|
|
|
protected function get_fields() { |
|
173
|
|
|
|
|
174
|
|
|
$defined_fields = $this->define_fields(); |
|
175
|
|
|
$generated_fields = $this->generate_fields( $defined_fields ); |
|
|
|
|
|
|
176
|
|
|
|
|
177
|
|
|
$errors = array(); |
|
178
|
|
|
|
|
179
|
|
|
if ( ! empty( $this->errors ) ) { |
|
180
|
|
|
foreach ( $this->required as $name => $alert ) { |
|
181
|
|
|
// Using WordPress function in place of array_column wp_list_pluck as it support older version as well. |
|
182
|
|
|
if ( false === array_search( $name, give_list_pluck( $generated_fields, 'name' ) ) ) { |
|
183
|
|
|
|
|
184
|
|
|
$errors[] = $this->errors[ $name ]; |
|
185
|
|
|
} |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
$this->errors = $errors; |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
if ( ! empty( $errors ) ) { |
|
192
|
|
|
|
|
193
|
|
|
return $errors; |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
return $generated_fields; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
/** |
|
200
|
|
|
* Generate a TinyMCE container field |
|
201
|
|
|
* |
|
202
|
|
|
* @param array $field |
|
203
|
|
|
* |
|
204
|
|
|
* @return array|false |
|
205
|
|
|
* |
|
206
|
|
|
* @since 1.0 |
|
207
|
|
|
*/ |
|
208
|
|
|
protected function generate_container( $field ) { |
|
209
|
|
|
|
|
210
|
|
|
if ( array_key_exists( 'html', $field ) ) { |
|
211
|
|
|
|
|
212
|
|
|
return array( |
|
213
|
|
|
'type' => $field['type'], |
|
214
|
|
|
'html' => $field['html'], |
|
215
|
|
|
); |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
return false; |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
/** |
|
222
|
|
|
* Generate a TinyMCE listbox field |
|
223
|
|
|
* |
|
224
|
|
|
* @param array $field |
|
225
|
|
|
* |
|
226
|
|
|
* @return array|false |
|
227
|
|
|
* |
|
228
|
|
|
* @since 1.0 |
|
229
|
|
|
*/ |
|
230
|
|
|
protected function generate_listbox( $field ) { |
|
231
|
|
|
|
|
232
|
|
|
$listbox = shortcode_atts( array( |
|
233
|
|
|
'label' => '', |
|
234
|
|
|
'minWidth' => '', |
|
235
|
|
|
'name' => false, |
|
236
|
|
|
'tooltip' => '', |
|
237
|
|
|
'type' => '', |
|
238
|
|
|
'value' => '', |
|
239
|
|
|
'classes' => '' |
|
|
|
|
|
|
240
|
|
|
), $field ); |
|
241
|
|
|
|
|
242
|
|
|
if ( $this->validate( $field ) ) { |
|
243
|
|
|
|
|
244
|
|
|
$new_listbox = array(); |
|
245
|
|
|
|
|
246
|
|
|
foreach ( $listbox as $key => $value ) { |
|
247
|
|
|
|
|
248
|
|
|
if ( $key == 'value' && empty( $value ) ) { |
|
|
|
|
|
|
249
|
|
|
$new_listbox[ $key ] = $listbox['name']; |
|
250
|
|
|
} else if ( $value ) { |
|
251
|
|
|
$new_listbox[ $key ] = $value; |
|
252
|
|
|
} |
|
253
|
|
|
} |
|
254
|
|
|
|
|
255
|
|
|
// do not reindex array! |
|
256
|
|
|
$field['options'] = array( |
|
257
|
|
|
'' => ( $field['placeholder'] ? $field['placeholder'] : esc_attr__( '- Select -', 'give' ) ), |
|
258
|
|
|
) + $field['options']; |
|
259
|
|
|
|
|
260
|
|
|
foreach ( $field['options'] as $value => $text ) { |
|
261
|
|
|
$new_listbox['values'][] = array( |
|
262
|
|
|
'text' => $text, |
|
263
|
|
|
'value' => $value, |
|
264
|
|
|
); |
|
265
|
|
|
} |
|
266
|
|
|
|
|
267
|
|
|
return $new_listbox; |
|
268
|
|
|
} |
|
269
|
|
|
|
|
270
|
|
|
return false; |
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* Generate a TinyMCE listbox field for a post_type. |
|
275
|
|
|
* |
|
276
|
|
|
* @param array $field |
|
277
|
|
|
* |
|
278
|
|
|
* @return array|false |
|
279
|
|
|
* |
|
280
|
|
|
* @since 1.0 |
|
281
|
|
|
*/ |
|
282
|
|
|
protected function generate_post( $field ) { |
|
283
|
|
|
|
|
284
|
|
|
$args = array( |
|
285
|
|
|
'post_type' => 'post', |
|
286
|
|
|
'orderby' => 'title', |
|
287
|
|
|
'order' => 'ASC', |
|
288
|
|
|
'posts_per_page' => 30, |
|
289
|
|
|
); |
|
290
|
|
|
|
|
291
|
|
|
$args = wp_parse_args( (array) $field['query_args'], $args ); |
|
292
|
|
|
$posts = new WP_Query( $args ); |
|
293
|
|
|
$options = array(); |
|
294
|
|
|
|
|
295
|
|
|
if ( $posts->have_posts() ) { |
|
296
|
|
|
while ( $posts->have_posts() ) { |
|
297
|
|
|
$posts->the_post(); |
|
298
|
|
|
$post_title = get_the_title(); |
|
299
|
|
|
$post_id = get_the_ID(); |
|
300
|
|
|
$options[ absint( $post_id ) ] = ( empty( $post_title ) ? sprintf( __( 'Untitled (#%s)', 'give' ), $post_id ) : $post_title ); |
|
301
|
|
|
} |
|
302
|
|
|
|
|
303
|
|
|
$field['type'] = 'listbox'; |
|
304
|
|
|
$field['options'] = $options; |
|
305
|
|
|
|
|
306
|
|
|
return $this->generate_listbox( $field ); |
|
307
|
|
|
} |
|
308
|
|
|
|
|
309
|
|
|
// perform validation here before returning false |
|
310
|
|
|
$this->validate( $field ); |
|
311
|
|
|
|
|
312
|
|
|
return false; |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
/** |
|
316
|
|
|
* Generate a TinyMCE textbox field |
|
317
|
|
|
* |
|
318
|
|
|
* @param array $field |
|
319
|
|
|
* |
|
320
|
|
|
* @return array|false |
|
321
|
|
|
* |
|
322
|
|
|
* @since 1.0 |
|
323
|
|
|
*/ |
|
324
|
|
|
protected function generate_textbox( $field ) { |
|
325
|
|
|
|
|
326
|
|
|
$textbox = shortcode_atts( array( |
|
327
|
|
|
'label' => '', |
|
328
|
|
|
'maxLength' => '', |
|
329
|
|
|
'minHeight' => '', |
|
330
|
|
|
'minWidth' => '', |
|
331
|
|
|
'multiline' => false, |
|
332
|
|
|
'name' => false, |
|
333
|
|
|
'tooltip' => '', |
|
334
|
|
|
'type' => '', |
|
335
|
|
|
'value' => '', |
|
336
|
|
|
'classes' => '', |
|
337
|
|
|
'placeholder' => '' |
|
|
|
|
|
|
338
|
|
|
), $field ); |
|
339
|
|
|
|
|
340
|
|
|
// Remove empty placeholder. |
|
341
|
|
|
if( empty( $textbox['placeholder'] ) ) { |
|
|
|
|
|
|
342
|
|
|
unset( $textbox['placeholder'] ); |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
if ( $this->validate( $field ) ) { |
|
346
|
|
|
return array_filter( $textbox, array( $this, 'return_textbox_value' ) ); |
|
347
|
|
|
} |
|
348
|
|
|
|
|
349
|
|
|
return false; |
|
350
|
|
|
} |
|
351
|
|
|
|
|
352
|
|
|
/** |
|
353
|
|
|
* Validate Textbox Value |
|
354
|
|
|
* |
|
355
|
|
|
* @param $value |
|
356
|
|
|
* |
|
357
|
|
|
* @return bool |
|
358
|
|
|
*/ |
|
359
|
|
|
function return_textbox_value( $value ) { |
|
|
|
|
|
|
360
|
|
|
return $value !== ''; |
|
361
|
|
|
} |
|
362
|
|
|
|
|
363
|
|
|
/** |
|
364
|
|
|
* Perform validation for a single field |
|
365
|
|
|
* |
|
366
|
|
|
* Returns true or false depending on whether the field has a 'name' attribute. |
|
367
|
|
|
* This method also populates the shortcode's $errors and $required arrays. |
|
368
|
|
|
* |
|
369
|
|
|
* @param array $field |
|
370
|
|
|
* |
|
371
|
|
|
* @return bool |
|
372
|
|
|
* |
|
373
|
|
|
* @since 1.0 |
|
374
|
|
|
*/ |
|
375
|
|
|
protected function validate( $field ) { |
|
376
|
|
|
|
|
377
|
|
|
extract( shortcode_atts( |
|
|
|
|
|
|
378
|
|
|
array( |
|
|
|
|
|
|
379
|
|
|
'name' => false, |
|
380
|
|
|
'required' => false, |
|
381
|
|
|
'label' => '', |
|
382
|
|
|
), $field ) |
|
|
|
|
|
|
383
|
|
|
); |
|
384
|
|
|
|
|
385
|
|
|
if ( $name ) { |
|
386
|
|
|
|
|
387
|
|
|
if ( isset( $required['error'] ) ) { |
|
388
|
|
|
|
|
389
|
|
|
$error = array( |
|
390
|
|
|
'type' => 'container', |
|
391
|
|
|
'html' => $required['error'], |
|
392
|
|
|
); |
|
393
|
|
|
|
|
394
|
|
|
$this->errors[ $name ] = $this->generate_container( $error ); |
|
395
|
|
|
} |
|
396
|
|
|
|
|
397
|
|
|
if ( ! ! $required || is_array( $required ) ) { |
|
398
|
|
|
|
|
399
|
|
|
$alert = esc_html__( 'Some of the shortcode options are required.', 'give' ); |
|
400
|
|
|
|
|
401
|
|
|
if ( isset( $required['alert'] ) ) { |
|
402
|
|
|
|
|
403
|
|
|
$alert = $required['alert']; |
|
404
|
|
|
|
|
405
|
|
|
} else if ( ! empty( $label ) ) { |
|
406
|
|
|
|
|
407
|
|
|
$alert = sprintf( |
|
408
|
|
|
/* translators: %s: option label */ |
|
|
|
|
|
|
409
|
|
|
esc_html__( 'The "%s" option is required.', 'give' ), |
|
410
|
|
|
str_replace( ':', '', $label ) |
|
411
|
|
|
); |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
$this->required[ $name ] = $alert; |
|
415
|
|
|
} |
|
416
|
|
|
|
|
417
|
|
|
return true; |
|
418
|
|
|
} |
|
419
|
|
|
|
|
420
|
|
|
return false; |
|
421
|
|
|
} |
|
422
|
|
|
} |
|
423
|
|
|
|
This check looks for type mismatches where the missing type is
false. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTimeobject or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalsebefore passing on the value to another function or method that may not be able to handle afalse.