Meta Box - Version 4.5.3

Version Description

  • Improvement: Use wp_json_encode instead of json_encode. Thank Sam Ford.
  • Fix: Escape value for cloneable fields
  • Fix: Notice for missing parameters for rwmb_meta field for map
Download this release

Release Info

Developer rilwis
Plugin Icon 128x128 Meta Box
Version 4.5.3
Comparing to
See all releases

Code changes from version 4.4.3 to 4.5.3

css/color.css CHANGED
@@ -4,4 +4,10 @@
4
  background: rgb(238, 238, 238);
5
  border: 1px solid rgb(204, 204, 204);
6
  position: absolute;
7
- }
 
 
 
 
 
 
4
  background: rgb(238, 238, 238);
5
  border: 1px solid rgb(204, 204, 204);
6
  position: absolute;
7
+ }
8
+ .rwmb-color-wrapper .wp-picker-container {
9
+ position: relative;
10
+ }
11
+ .rwmb-color-wrapper .wp-picker-holder {
12
+ position: absolute;
13
+ }
css/map.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ .rwmb-map-canvas {
2
+ width: 100%;
3
+ height: 400px;
4
+ }
inc/field-multiple-values.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Field_Multiple_Values' ) )
6
+ {
7
+ /**
8
+ * This class implements common methods used in fields which have multiple values
9
+ * like checkbox list, autocomplete, etc.
10
+ *
11
+ * The difference when handling actions for these fields are the way they get/set
12
+ * meta value. Briefly:
13
+ * - If field is cloneable, value is saved as a single entry in the database
14
+ * - Otherwise value is saved as multiple entries
15
+ */
16
+ class RWMB_Field_Multiple_Values extends RWMB_Field
17
+ {
18
+ /**
19
+ * Normalize parameters for field
20
+ *
21
+ * @param array $field
22
+ *
23
+ * @return array
24
+ */
25
+ static function normalize_field( $field )
26
+ {
27
+ $field['multiple'] = true;
28
+ $field['field_name'] = $field['id'];
29
+ if ( ! $field['clone'] )
30
+ $field['field_name'] .= '[]';
31
+
32
+ return $field;
33
+ }
34
+
35
+ /**
36
+ * Output the field value
37
+ * Display option name instead of option value
38
+ *
39
+ * @param array $field Field parameters
40
+ * @param array $args Additional arguments. Not used for these fields.
41
+ * @param int|null $post_id Post ID. null for current post. Optional.
42
+ *
43
+ * @return mixed Field value
44
+ */
45
+ static function the_value( $field, $args = array(), $post_id = null )
46
+ {
47
+ $value = self::get_value( $field, $args, $post_id );
48
+ if ( ! $value )
49
+ return '';
50
+
51
+ $output = '<ul>';
52
+ if ( $field['clone'] )
53
+ {
54
+ foreach ( $value as $subvalue )
55
+ {
56
+ $output .= '<li>';
57
+ $output .= '<ul>';
58
+ foreach ( $subvalue as $option )
59
+ {
60
+ $output .= '<li>' . $field['options'][$option] . '</li>';
61
+ }
62
+ $output .= '</ul>';
63
+ $output .= '</li>';
64
+ }
65
+ }
66
+ else
67
+ {
68
+ foreach ( $value as $option )
69
+ {
70
+ $output .= '<li>' . $field['options'][$option] . '</li>';
71
+ }
72
+ }
73
+ $output .= '</ul>';
74
+
75
+ return $output;
76
+ }
77
+ }
78
+ }
inc/field.php CHANGED
@@ -65,10 +65,12 @@ if ( ! class_exists( 'RWMB_Field ' ) )
65
  // Cloneable fields
66
  if ( $field['clone'] )
67
  {
68
- $meta = (array) $meta;
69
-
70
  $field_html = '';
71
 
 
 
 
 
72
  foreach ( $meta as $index => $sub_meta )
73
  {
74
  $sub_field = $field;
@@ -254,23 +256,49 @@ if ( ! class_exists( 'RWMB_Field ' ) )
254
  {
255
  /**
256
  * For special fields like 'divider', 'heading' which don't have ID, just return empty string
257
- * to prevent notice error when displayin fields
258
  */
259
  if ( empty( $field['id'] ) )
260
  return '';
261
 
262
- $meta = get_post_meta( $post_id, $field['id'], ! $field['multiple'] );
 
263
 
264
  // Use $field['std'] only when the meta box hasn't been saved (i.e. the first time we run)
265
  $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
266
 
267
- // Escape attributes for non-wysiwyg fields
268
- if ( 'wysiwyg' !== $field['type'] )
269
- $meta = is_array( $meta ) ? array_map( 'esc_attr', $meta ) : esc_attr( $meta );
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  return $meta;
272
  }
273
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  /**
275
  * Set value of meta before saving into database
276
  *
@@ -298,6 +326,7 @@ if ( ! class_exists( 'RWMB_Field ' ) )
298
  {
299
  $name = $field['id'];
300
 
 
301
  if ( '' === $new || array() === $new )
302
  {
303
  delete_post_meta( $post_id, $name );
@@ -305,6 +334,20 @@ if ( ! class_exists( 'RWMB_Field ' ) )
305
  return;
306
  }
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  if ( $field['multiple'] )
309
  {
310
  foreach ( $new as $new_value )
@@ -317,20 +360,11 @@ if ( ! class_exists( 'RWMB_Field ' ) )
317
  if ( ! in_array( $old_value, $new ) )
318
  delete_post_meta( $post_id, $name, $old_value );
319
  }
 
320
  }
321
- else
322
- {
323
- if ( $field['clone'] )
324
- {
325
- $new = (array) $new;
326
- foreach ( $new as $k => $v )
327
- {
328
- if ( '' === $v )
329
- unset( $new[$k] );
330
- }
331
- }
332
- update_post_meta( $post_id, $name, $new );
333
- }
334
  }
335
 
336
  /**
@@ -344,5 +378,87 @@ if ( ! class_exists( 'RWMB_Field ' ) )
344
  {
345
  return $field;
346
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  }
348
  }
65
  // Cloneable fields
66
  if ( $field['clone'] )
67
  {
 
 
68
  $field_html = '';
69
 
70
+ /**
71
+ * Note: $meta must contain value so that the foreach loop runs!
72
+ * @see self::meta()
73
+ */
74
  foreach ( $meta as $index => $sub_meta )
75
  {
76
  $sub_field = $field;
256
  {
257
  /**
258
  * For special fields like 'divider', 'heading' which don't have ID, just return empty string
259
+ * to prevent notice error when displaying fields
260
  */
261
  if ( empty( $field['id'] ) )
262
  return '';
263
 
264
+ $single = $field['clone'] || ! $field['multiple'];
265
+ $meta = get_post_meta( $post_id, $field['id'], $single );
266
 
267
  // Use $field['std'] only when the meta box hasn't been saved (i.e. the first time we run)
268
  $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
269
 
270
+ // Escape attributes
271
+ $meta = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'esc_meta' ), $meta );
272
+
273
+ // Make sure meta value is an array for clonable and multiple fields
274
+ if ( $field['clone'] || $field['multiple'] )
275
+ {
276
+ if ( empty( $meta ) || ! is_array( $meta ) )
277
+ {
278
+ /**
279
+ * Note: if field is clonable, $meta must be an array with values
280
+ * so that the foreach loop in self::show() runs properly
281
+ * @see self::show()
282
+ */
283
+ $meta = $field['clone'] ? array( '' ) : array();
284
+ }
285
+ }
286
 
287
  return $meta;
288
  }
289
 
290
+ /**
291
+ * Escape meta for field output
292
+ *
293
+ * @param mixed $meta
294
+ *
295
+ * @return mixed
296
+ */
297
+ static function esc_meta( $meta )
298
+ {
299
+ return is_array( $meta ) ? array_map( __METHOD__, $meta ) : esc_attr( $meta );
300
+ }
301
+
302
  /**
303
  * Set value of meta before saving into database
304
  *
326
  {
327
  $name = $field['id'];
328
 
329
+ // Remove post meta if it's empty
330
  if ( '' === $new || array() === $new )
331
  {
332
  delete_post_meta( $post_id, $name );
334
  return;
335
  }
336
 
337
+ // If field is cloneable, value is saved as a single entry in the database
338
+ if ( $field['clone'] )
339
+ {
340
+ $new = (array) $new;
341
+ foreach ( $new as $k => $v )
342
+ {
343
+ if ( '' === $v )
344
+ unset( $new[$k] );
345
+ }
346
+ update_post_meta( $post_id, $name, $new );
347
+ return;
348
+ }
349
+
350
+ // If field is multiple, value is saved as multiple entries in the database (WordPress behaviour)
351
  if ( $field['multiple'] )
352
  {
353
  foreach ( $new as $new_value )
360
  if ( ! in_array( $old_value, $new ) )
361
  delete_post_meta( $post_id, $name, $old_value );
362
  }
363
+ return;
364
  }
365
+
366
+ // Default: just update post meta
367
+ update_post_meta( $post_id, $name, $new );
 
 
 
 
 
 
 
 
 
 
368
  }
369
 
370
  /**
378
  {
379
  return $field;
380
  }
381
+
382
+ /**
383
+ * Get the field value
384
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
385
+ * of the field saved in the database, while this function returns more meaningful value of the field, for ex.:
386
+ * for file/image: return array of file/image information instead of file/image IDs
387
+ *
388
+ * Each field can extend this function and add more data to the returned value.
389
+ * See specific field classes for details.
390
+ *
391
+ * @param array $field Field parameters
392
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
393
+ * @param int|null $post_id Post ID. null for current post. Optional.
394
+ *
395
+ * @return mixed Field value
396
+ */
397
+ static function get_value( $field, $args = array(), $post_id = null )
398
+ {
399
+ if ( ! $post_id )
400
+ $post_id = get_the_ID();
401
+
402
+ /**
403
+ * Get raw meta value in the database, no escape
404
+ * Very similar to self::meta() function
405
+ */
406
+
407
+ /**
408
+ * For special fields like 'divider', 'heading' which don't have ID, just return empty string
409
+ * to prevent notice error when display in fields
410
+ */
411
+ $value = '';
412
+ if ( ! empty( $field['id'] ) )
413
+ {
414
+ $single = $field['clone'] || ! $field['multiple'];
415
+ $value = get_post_meta( $post_id, $field['id'], $single );
416
+
417
+ // Make sure meta value is an array for clonable and multiple fields
418
+ if ( $field['clone'] || $field['multiple'] )
419
+ {
420
+ $value = is_array( $value ) && $value ? $value : array();
421
+ }
422
+ }
423
+
424
+ /**
425
+ * Return the meta value by default.
426
+ * For specific fields, the returned value might be different. See each field class for details
427
+ */
428
+ return $value;
429
+ }
430
+
431
+ /**
432
+ * Output the field value
433
+ * Depends on field value and field types, each field can extend this method to output its value in its own way
434
+ * See specific field classes for details.
435
+ *
436
+ * Note: we don't echo the field value directly. We return the output HTML of field, which will be used in
437
+ * rwmb_the_field function later.
438
+ *
439
+ * @use self::get_value()
440
+ * @see rwmb_the_field()
441
+ *
442
+ * @param array $field Field parameters
443
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
444
+ * @param int|null $post_id Post ID. null for current post. Optional.
445
+ *
446
+ * @return string HTML output of the field
447
+ */
448
+ static function the_value( $field, $args = array(), $post_id = null )
449
+ {
450
+ $value = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id );
451
+ $output = $value;
452
+ if ( is_array( $value ) )
453
+ {
454
+ $output = '<ul>';
455
+ foreach ( $value as $subvalue )
456
+ {
457
+ $output .= '<li>' . $subvalue . '</li>';
458
+ }
459
+ $output .= '</ul>';
460
+ }
461
+ return $output;
462
+ }
463
  }
464
  }
inc/fields/autocomplete.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
6
  {
7
- class RWMB_Autocomplete_Field extends RWMB_Field
8
  {
9
  /**
10
  * Enqueue scripts and styles
@@ -31,13 +31,21 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
31
  if ( ! is_array( $meta ) )
32
  $meta = array( $meta );
33
 
34
- $options = array();
35
- foreach ( $field['options'] as $value => $label )
36
  {
37
- $options[] = array(
38
- 'value' => $value,
39
- 'label' => $label,
40
- );
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
  // Input field that triggers autocomplete.
@@ -47,7 +55,7 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
47
  '<input type="text" class="rwmb-autocomplete" id="%s" data-name="%s" data-options="%s" size="%s">',
48
  $field['id'],
49
  $field['field_name'],
50
- esc_attr( json_encode( $options ) ),
51
  $field['size']
52
  );
53
 
@@ -62,10 +70,30 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
62
  <input type="hidden" class="rwmb-autocomplete-value" name="%s" value="%s">
63
  </div>
64
  ';
65
- foreach ( $field['options'] as $value => $label )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  {
67
- if ( in_array( $value, $meta ) )
68
  {
 
 
 
69
  $html .= sprintf(
70
  $tpl,
71
  $label,
@@ -75,57 +103,12 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
75
  );
76
  }
77
  }
 
78
  $html .= '</div>'; // .rwmb-autocomplete-results
79
 
80
  return $html;
81
  }
82
 
83
- /**
84
- * Get meta value
85
- * If field is cloneable, value is saved as a single entry in DB
86
- * Otherwise value is saved as multiple entries (for backward compatibility)
87
- *
88
- * @see "save" method for better understanding
89
- *
90
- * @param $post_id
91
- * @param $saved
92
- * @param $field
93
- *
94
- * @return array
95
- */
96
- static function meta( $post_id, $saved, $field )
97
- {
98
- $meta = get_post_meta( $post_id, $field['id'], $field['clone'] );
99
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
100
-
101
- return $meta;
102
- }
103
-
104
- /**
105
- * Save meta value
106
- * If field is cloneable, value is saved as a single entry in DB
107
- * Otherwise value is saved as multiple entries (for backward compatibility)
108
- *
109
- * @param $new
110
- * @param $old
111
- * @param $post_id
112
- * @param $field
113
- */
114
- static function save( $new, $old, $post_id, $field )
115
- {
116
- if ( ! $field['clone'] )
117
- {
118
- parent::save( $new, $old, $post_id, $field );
119
-
120
- return;
121
- }
122
-
123
- if ( empty( $new ) )
124
- delete_post_meta( $post_id, $field['id'] );
125
- else
126
- update_post_meta( $post_id, $field['id'], $new );
127
- }
128
-
129
  /**
130
  * Normalize parameters for field
131
  *
@@ -135,15 +118,10 @@ if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
135
  */
136
  static function normalize_field( $field )
137
  {
 
138
  $field = wp_parse_args( $field, array(
139
  'size' => 30,
140
  ) );
141
-
142
- $field['multiple'] = true;
143
- $field['field_name'] = $field['id'];
144
- if ( ! $field['clone'] )
145
- $field['field_name'] .= '[]';
146
-
147
  return $field;
148
  }
149
  }
4
 
5
  if ( ! class_exists( 'RWMB_Autocomplete_Field' ) )
6
  {
7
+ class RWMB_Autocomplete_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Enqueue scripts and styles
31
  if ( ! is_array( $meta ) )
32
  $meta = array( $meta );
33
 
34
+ if ( is_string( $field['options'] ) )
 
35
  {
36
+ $options = $field['options'];
37
+ }
38
+ else
39
+ {
40
+ $options = array();
41
+ foreach ( $field['options'] as $value => $label )
42
+ {
43
+ $options[] = array(
44
+ 'value' => $value,
45
+ 'label' => $label,
46
+ );
47
+ }
48
+ $options = wp_json_encode( $options );
49
  }
50
 
51
  // Input field that triggers autocomplete.
55
  '<input type="text" class="rwmb-autocomplete" id="%s" data-name="%s" data-options="%s" size="%s">',
56
  $field['id'],
57
  $field['field_name'],
58
+ esc_attr( $options ),
59
  $field['size']
60
  );
61
 
70
  <input type="hidden" class="rwmb-autocomplete-value" name="%s" value="%s">
71
  </div>
72
  ';
73
+
74
+ if ( is_array( $field['options'] ) )
75
+ {
76
+ foreach ( $field['options'] as $value => $label )
77
+ {
78
+ if ( in_array( $value, $meta ) )
79
+ {
80
+ $html .= sprintf(
81
+ $tpl,
82
+ $label,
83
+ __( 'Delete', 'meta-box' ),
84
+ $field['field_name'],
85
+ $value
86
+ );
87
+ }
88
+ }
89
+ }
90
+ else
91
  {
92
+ foreach ( $meta as $value )
93
  {
94
+ if ( empty( $value ) )
95
+ continue;
96
+ $label = apply_filters( 'rwmb_autocomplete_result_label', $value, $field );
97
  $html .= sprintf(
98
  $tpl,
99
  $label,
103
  );
104
  }
105
  }
106
+
107
  $html .= '</div>'; // .rwmb-autocomplete-results
108
 
109
  return $html;
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  /**
113
  * Normalize parameters for field
114
  *
118
  */
119
  static function normalize_field( $field )
120
  {
121
+ $field = parent::normalize_field( $field );
122
  $field = wp_parse_args( $field, array(
123
  'size' => 30,
124
  ) );
 
 
 
 
 
 
125
  return $field;
126
  }
127
  }
inc/fields/checkbox-list.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
6
  {
7
- class RWMB_Checkbox_List_Field extends RWMB_Field
8
  {
9
  /**
10
  * Get field HTML
@@ -33,73 +33,5 @@ if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
33
 
34
  return implode( '<br>', $html );
35
  }
36
-
37
- /**
38
- * Get meta value
39
- * If field is cloneable, value is saved as a single entry in DB
40
- * Otherwise value is saved as multiple entries (for backward compatibility)
41
- *
42
- * @see "save" method for better understanding
43
- *
44
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
45
- *
46
- * @param $post_id
47
- * @param $saved
48
- * @param $field
49
- *
50
- * @return array
51
- */
52
- static function meta( $post_id, $saved, $field )
53
- {
54
- $meta = get_post_meta( $post_id, $field['id'], $field['clone'] );
55
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
56
- $meta = array_map( 'esc_attr', (array) $meta );
57
-
58
- return $meta;
59
- }
60
-
61
- /**
62
- * Save meta value
63
- * If field is cloneable, value is saved as a single entry in DB
64
- * Otherwise value is saved as multiple entries (for backward compatibility)
65
- *
66
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
67
- *
68
- * @param $new
69
- * @param $old
70
- * @param $post_id
71
- * @param $field
72
- */
73
- static function save( $new, $old, $post_id, $field )
74
- {
75
- if ( ! $field['clone'] )
76
- {
77
- parent::save( $new, $old, $post_id, $field );
78
-
79
- return;
80
- }
81
-
82
- if ( empty( $new ) )
83
- delete_post_meta( $post_id, $field['id'] );
84
- else
85
- update_post_meta( $post_id, $field['id'], $new );
86
- }
87
-
88
- /**
89
- * Normalize parameters for field
90
- *
91
- * @param array $field
92
- *
93
- * @return array
94
- */
95
- static function normalize_field( $field )
96
- {
97
- $field['multiple'] = true;
98
- $field['field_name'] = $field['id'];
99
- if ( ! $field['clone'] )
100
- $field['field_name'] .= '[]';
101
-
102
- return $field;
103
- }
104
  }
105
  }
4
 
5
  if ( ! class_exists( 'RWMB_Checkbox_List_Field' ) )
6
  {
7
+ class RWMB_Checkbox_List_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Get field HTML
33
 
34
  return implode( '<br>', $html );
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
  }
inc/fields/checkbox.php CHANGED
@@ -26,34 +26,14 @@ if ( ! class_exists( 'RWMB_Checkbox_Field' ) )
26
  */
27
  static function html( $meta, $field )
28
  {
29
- $desc = $field['desc'] ? "<span id='{$field['id']}_description' class='description'>{$field['desc']}</span>" : '';
30
  return sprintf(
31
- '<label><input type="checkbox" class="rwmb-checkbox" name="%s" id="%s" value="1" %s> %s</label>',
32
  $field['field_name'],
33
  $field['id'],
34
- checked( ! empty( $meta ), 1, false ),
35
- $desc
36
  );
37
  }
38
 
39
- /**
40
- * Show end HTML markup for fields
41
- *
42
- * @param mixed $meta
43
- * @param array $field
44
- *
45
- * @return string
46
- */
47
- static function end_html( $meta, $field )
48
- {
49
- $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ) ) : '';
50
-
51
- // Closes the container
52
- $html = "$button</div>";
53
-
54
- return $html;
55
- }
56
-
57
  /**
58
  * Set the value of checkbox to 1 or 0 instead of 'checked' and empty string
59
  * This prevents using default value once the checkbox has been unchecked
@@ -71,5 +51,28 @@ if ( ! class_exists( 'RWMB_Checkbox_Field' ) )
71
  {
72
  return empty( $new ) ? 0 : 1;
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
  }
26
  */
27
  static function html( $meta, $field )
28
  {
 
29
  return sprintf(
30
+ '<input type="checkbox" class="rwmb-checkbox" name="%s" id="%s" value="1" %s>',
31
  $field['field_name'],
32
  $field['id'],
33
+ checked( ! empty( $meta ), 1, false )
 
34
  );
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  /**
38
  * Set the value of checkbox to 1 or 0 instead of 'checked' and empty string
39
  * This prevents using default value once the checkbox has been unchecked
51
  {
52
  return empty( $new ) ? 0 : 1;
53
  }
54
+
55
+ /**
56
+ * Output the field value
57
+ * Display 'Yes' or 'No' instead of '1' and '0'
58
+ *
59
+ * Note: we don't echo the field value directly. We return the output HTML of field, which will be used in
60
+ * rwmb_the_field function later.
61
+ *
62
+ * @use self::get_value()
63
+ * @see rwmb_the_field()
64
+ *
65
+ * @param array $field Field parameters
66
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
67
+ * @param int|null $post_id Post ID. null for current post. Optional.
68
+ *
69
+ * @return string HTML output of the field
70
+ */
71
+ static function the_value( $field, $args = array(), $post_id = null )
72
+ {
73
+ $value = self::get_value( $field, $args, $post_id );
74
+
75
+ return $value ? __( 'Yes', 'meta-box' ) : __( 'No', 'meta-box' );
76
+ }
77
  }
78
  }
inc/fields/custom-html.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Custom_Html_Field' ) )
6
+ {
7
+ class RWMB_Custom_Html_Field extends RWMB_Field
8
+ {
9
+ /**
10
+ * Get field HTML
11
+ *
12
+ * @param mixed $meta
13
+ * @param array $field
14
+ *
15
+ * @return string
16
+ */
17
+ static function html( $meta, $field )
18
+ {
19
+ $html = ! empty( $field['std'] ) ? $field['std'] : '';
20
+ if ( ! empty( $field['callback'] ) && is_callable( $field['callback'] ) )
21
+ {
22
+ $html = call_user_func_array( $field['callback'], array( $meta, $field ) );
23
+ }
24
+ return $html;
25
+ }
26
+ }
27
+ }
inc/fields/date.php CHANGED
@@ -54,7 +54,7 @@ if ( ! class_exists( 'RWMB_Date_Field' ) )
54
  $meta,
55
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
56
  $field['size'],
57
- esc_attr( json_encode( $field['js_options'] ) )
58
  );
59
  }
60
 
54
  $meta,
55
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
56
  $field['size'],
57
+ esc_attr( wp_json_encode( $field['js_options'] ) )
58
  );
59
  }
60
 
inc/fields/datetime.php CHANGED
@@ -98,7 +98,7 @@ if ( ! class_exists( 'RWMB_Datetime_Field' ) )
98
  isset( $field['timestamp'] ) && $field['timestamp'] ? date( self::translate_format( $field ), $meta ) : $meta,
99
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
100
  $field['size'],
101
- esc_attr( json_encode( $field['js_options'] ) )
102
  );
103
  }
104
 
98
  isset( $field['timestamp'] ) && $field['timestamp'] ? date( self::translate_format( $field ), $meta ) : $meta,
99
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
100
  $field['size'],
101
+ esc_attr( wp_json_encode( $field['js_options'] ) )
102
  );
103
  }
104
 
inc/fields/fieldset-text.php CHANGED
@@ -16,63 +16,92 @@ if ( ! class_exists( 'RWMB_Fieldset_Text_Field' ) )
16
  */
17
  static function html( $meta, $field )
18
  {
19
- if ( 1 == count( $meta ) && '' == trim( $meta[0] ) )
20
- $meta = '';
21
 
22
- $html = array();
23
- $before = '<fieldset><legend>' . $field['desc'] . '</legend>';
24
- $after = '</fieldset>';
25
-
26
- $tpl = '<label>%s <input type="text" class="rwmb-fieldset-text" name="%s[%s][%d]" placeholder="%s" value="%s" /></label>';
27
-
28
- for ( $n = 0; $n < $field['rows']; $n ++ )
29
  {
30
- foreach ( $field['options'] as $k => $v )
31
  {
32
- $fid = $field['id'];
33
- if ( is_array( $meta ) && ! empty( $meta ) )
34
- $html[] = sprintf( $tpl, $k, $fid, $v, $n, $k, $meta[$v][$n] );
35
- else
36
- $html[] = sprintf( $tpl, $k, $fid, $v, $n, $k, '' );
37
  }
38
  $html[] = '<br>';
39
  }
40
 
41
- $out = $before . implode( ' ', $html ) . $after;
42
 
43
  return $out;
44
  }
45
 
46
  /**
47
- * Get meta value
 
48
  *
49
- * @param $post_id
50
- * @param $saved
51
- * @param $field
52
  *
53
- * @return array
54
  */
55
- static function meta( $post_id, $saved, $field )
56
  {
57
- $meta = get_post_meta( $post_id, $field['id'] );
58
 
59
- if ( is_array( $meta ) && ! empty( $meta ) )
60
- $meta = $meta[0];
61
 
62
- return $meta;
63
  }
64
 
65
  /**
66
- * Save meta value
67
  *
68
- * @param $new
69
- * @param $old
70
- * @param $post_id
71
- * @param $field
72
  */
73
- static function save( $new, $old, $post_id, $field )
74
  {
75
- update_post_meta( $post_id, $field['id'], $new, $old );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
  }
78
  }
16
  */
17
  static function html( $meta, $field )
18
  {
19
+ $html = array();
20
+ $tpl = '<label>%s <input type="text" class="rwmb-fieldset-text" name="%s[%d][%s]" value="%s"></label>';
21
 
22
+ for ( $row = 0; $row < $field['rows']; $row ++ )
 
 
 
 
 
 
23
  {
24
+ foreach ( $field['options'] as $key => $label )
25
  {
26
+ $value = isset( $meta[$row][$key] ) ? $meta[$row][$key] : '';
27
+ $html[] = sprintf( $tpl, $label, $field['id'], $row, $key, $value );
 
 
 
28
  }
29
  $html[] = '<br>';
30
  }
31
 
32
+ $out = '<fieldset><legend>' . $field['desc'] . '</legend>' . implode( ' ', $html ) . '</fieldset>';
33
 
34
  return $out;
35
  }
36
 
37
  /**
38
+ * Show end HTML markup for fields
39
+ * Do not show field description. Field description is shown before list of fields
40
  *
41
+ * @param mixed $meta
42
+ * @param array $field
 
43
  *
44
+ * @return string
45
  */
46
+ static function end_html( $meta, $field )
47
  {
48
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
49
 
50
+ // Closes the container
51
+ $html = "$button</div>";
52
 
53
+ return $html;
54
  }
55
 
56
  /**
57
+ * Normalize parameters for field
58
  *
59
+ * @param array $field
60
+ *
61
+ * @return array
 
62
  */
63
+ static function normalize_field( $field )
64
  {
65
+ $field['multiple'] = false;
66
+ return $field;
67
+ }
68
+
69
+ /**
70
+ * Output the field value
71
+ * Display options in format Label: value in unordered list
72
+ *
73
+ * @param array $field Field parameters
74
+ * @param array $args Additional arguments. Not used for these fields.
75
+ * @param int|null $post_id Post ID. null for current post. Optional.
76
+ *
77
+ * @return mixed Field value
78
+ */
79
+ static function the_value( $field, $args = array(), $post_id = null )
80
+ {
81
+ $value = self::get_value( $field, $args, $post_id );
82
+ if ( ! $value )
83
+ return '';
84
+
85
+ $output = '<table>';
86
+ $output .= '<thead><tr>';
87
+ foreach ( $field['options'] as $label )
88
+ {
89
+ $output .= "<th>$label</th>";
90
+ }
91
+ $output .= '</tr></thead><tbody>';
92
+
93
+ foreach ( $value as $subvalue )
94
+ {
95
+ $output .= '<tr>';
96
+ foreach ( $subvalue as $value )
97
+ {
98
+ $output .= "<td>$value</td>";
99
+ }
100
+ $output .= '</tr>';
101
+ }
102
+ $output .= '</tbody></table>';
103
+
104
+ return $output;
105
  }
106
  }
107
  }
inc/fields/file.php CHANGED
@@ -290,19 +290,93 @@ if ( ! class_exists( 'RWMB_File_Field' ) )
290
  }
291
 
292
  /**
293
- * Standard meta retrieval
 
 
294
  *
295
- * @param int $post_id
296
- * @param array $field
297
- * @param bool $saved
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  *
299
- * @return mixed
300
  */
301
- static function meta( $post_id, $saved, $field )
302
  {
303
- $meta = parent::meta( $post_id, $saved, $field );
 
 
 
 
304
 
305
- return empty( $meta ) ? array() : (array) $meta;
 
 
 
 
 
 
306
  }
307
  }
308
  }
290
  }
291
 
292
  /**
293
+ * Get the field value
294
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
295
+ * of the field saved in the database, while this function returns more meaningful value of the field
296
  *
297
+ * @param array $field Field parameters
298
+ * @param array $args Not used for this field
299
+ * @param int|null $post_id Post ID. null for current post. Optional.
300
+ *
301
+ * @return mixed Full info of uploaded files
302
+ */
303
+ static function get_value( $field, $args = array(), $post_id = null )
304
+ {
305
+ if ( ! $post_id )
306
+ $post_id = get_the_ID();
307
+
308
+ /**
309
+ * Get raw meta value in the database, no escape
310
+ * Very similar to self::meta() function
311
+ */
312
+ $file_ids = get_post_meta( $post_id, $field['id'], false );
313
+
314
+ // For each file, get full file info
315
+ $value = array();
316
+ foreach ( $file_ids as $file_id )
317
+ {
318
+ if ( $file_info = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'file_info' ), $file_id, $args ) )
319
+ {
320
+ $value[$file_id] = $file_info;
321
+ }
322
+ }
323
+
324
+ return $value;
325
+ }
326
+
327
+ /**
328
+ * Output the field value
329
+ * Display unordered list of files
330
+ *
331
+ * @param array $field Field parameters
332
+ * @param array $args Additional arguments. Not used for these fields.
333
+ * @param int|null $post_id Post ID. null for current post. Optional.
334
+ *
335
+ * @return mixed Field value
336
+ */
337
+ static function the_value( $field, $args = array(), $post_id = null )
338
+ {
339
+ $value = self::get_value( $field, $args, $post_id );
340
+ if ( ! $value )
341
+ return '';
342
+
343
+ $output = '<ul>';
344
+ foreach ( $value as $file_id => $file_info )
345
+ {
346
+ $output .= sprintf(
347
+ '<li><a href="%s" target="_blank">%s</a></li>',
348
+ wp_get_attachment_url( $file_id ),
349
+ get_the_title( $file_id )
350
+ );
351
+ }
352
+ $output .= '</ul>';
353
+
354
+ return $output;
355
+ }
356
+
357
+ /**
358
+ * Get uploaded file information
359
+ *
360
+ * @param int $file_id Attachment file ID (post ID). Required.
361
+ * @param array $args Array of arguments (for size).
362
  *
363
+ * @return array|bool False if file not found. Array of (id, name, path, url) on success
364
  */
365
+ static function file_info( $file_id, $args = array() )
366
  {
367
+ $path = get_attached_file( $file_id );
368
+ if ( ! $path )
369
+ {
370
+ return false;
371
+ }
372
 
373
+ return array(
374
+ 'ID' => $file_id,
375
+ 'name' => basename( $path ),
376
+ 'path' => $path,
377
+ 'url' => wp_get_attachment_url( $file_id ),
378
+ 'title' => get_the_title( $file_id ),
379
+ );
380
  }
381
  }
382
  }
inc/fields/image-select.php CHANGED
@@ -59,5 +59,67 @@ if ( ! class_exists( 'RWMB_Image_Select_Field' ) )
59
 
60
  return $field;
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
  }
59
 
60
  return $field;
61
  }
62
+
63
+ /**
64
+ * Output the field value
65
+ * Display unordered list of images with option for size and link to full size
66
+ *
67
+ * @param array $field Field parameters
68
+ * @param array $args Additional arguments. Not used for these fields.
69
+ * @param int|null $post_id Post ID. null for current post. Optional.
70
+ *
71
+ * @return mixed Field value
72
+ */
73
+ static function the_value( $field, $args = array(), $post_id = null )
74
+ {
75
+ $value = self::get_value( $field, $args, $post_id );
76
+ if ( ! $value )
77
+ return '';
78
+
79
+ $function = array( RW_Meta_Box::get_class_name( $field ), 'get_option_label' );
80
+
81
+ if ( $field['clone'] )
82
+ {
83
+ $output = '<ul>';
84
+ if ( $field['multiple'] )
85
+ {
86
+ foreach ( $value as $subvalue )
87
+ {
88
+ $output .= '<li><ul>';
89
+ foreach ( $subvalue as &$option )
90
+ {
91
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$value] ) );
92
+ }
93
+ $output .= '</ul></li>';
94
+ }
95
+ }
96
+ else
97
+ {
98
+ foreach ( $value as &$subvalue )
99
+ {
100
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$subvalue] ) );
101
+ }
102
+ }
103
+ $output .= '</ul>';
104
+ }
105
+ else
106
+ {
107
+ if ( $field['multiple'] )
108
+ {
109
+ $output = '<ul>';
110
+ foreach ( $value as &$subvalue )
111
+ {
112
+ $output .= sprintf( '<li><img src="%s"></li>', esc_url( $field['options'][$subvalue] ) );
113
+ }
114
+ $output .= '</ul>';
115
+ }
116
+ else
117
+ {
118
+ $output = sprintf( '<img src="%s">', esc_url( $field['options'][$value] ) );
119
+ }
120
+ }
121
+
122
+ return $output;
123
+ }
124
  }
125
  }
inc/fields/image.php CHANGED
@@ -158,5 +158,85 @@ if ( ! class_exists( 'RWMB_Image_Field' ) )
158
  );
159
  }
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
  }
158
  );
159
  }
160
 
161
+ /**
162
+ * Output the field value
163
+ * Display unordered list of images with option for size and link to full size
164
+ *
165
+ * @param array $field Field parameters
166
+ * @param array $args Additional arguments. Not used for these fields.
167
+ * @param int|null $post_id Post ID. null for current post. Optional.
168
+ *
169
+ * @return mixed Field value
170
+ */
171
+ static function the_value( $field, $args = array(), $post_id = null )
172
+ {
173
+ $value = self::get_value( $field, $args, $post_id );
174
+ if ( ! $value )
175
+ return '';
176
+
177
+ $output = '<ul>';
178
+ foreach ( $value as $file_id => $file_info )
179
+ {
180
+ $img = sprintf(
181
+ '<img src="%s" alt="%s" title="%s">',
182
+ esc_url( $file_info['url'] ),
183
+ esc_attr( $file_info['alt'] ),
184
+ esc_attr( $file_info['title'] )
185
+ );
186
+
187
+ // Link thumbnail to full size image?
188
+ if ( isset( $args['link'] ) && $args['link'] )
189
+ {
190
+ $img = sprintf(
191
+ '<a href="%s" title="%s">%s</a>',
192
+ esc_url( $file_info['full_url'] ),
193
+ esc_attr( $file_info['title'] ),
194
+ $img
195
+ );
196
+ }
197
+
198
+ $output .= "<li>$img</li>";
199
+ }
200
+ $output .= '</ul>';
201
+
202
+ return $output;
203
+ }
204
+
205
+ /**
206
+ * Get uploaded file information
207
+ *
208
+ * @param int $file_id Attachment image ID (post ID). Required.
209
+ * @param array $args Array of arguments (for size).
210
+ *
211
+ * @return array|bool False if file not found. Array of image info on success
212
+ */
213
+ static function file_info( $file_id, $args = array() )
214
+ {
215
+ $args = wp_parse_args( $args, array(
216
+ 'size' => 'thumbnail',
217
+ ) );
218
+
219
+ $img_src = wp_get_attachment_image_src( $file_id, $args['size'] );
220
+ if ( ! $img_src )
221
+ {
222
+ return false;
223
+ }
224
+
225
+ $attachment = get_post( $file_id );
226
+ $path = get_attached_file( $file_id );
227
+ return array(
228
+ 'ID' => $file_id,
229
+ 'name' => basename( $path ),
230
+ 'path' => $path,
231
+ 'url' => $img_src[0],
232
+ 'width' => $img_src[1],
233
+ 'height' => $img_src[2],
234
+ 'full_url' => wp_get_attachment_url( $file_id ),
235
+ 'title' => $attachment->post_title,
236
+ 'caption' => $attachment->post_excerpt,
237
+ 'description' => $attachment->post_content,
238
+ 'alt' => get_post_meta( $file_id, '_wp_attachment_image_alt', true ),
239
+ );
240
+ }
241
  }
242
  }
inc/fields/key-value.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Prevent loading this file directly
3
+ defined( 'ABSPATH' ) || exit;
4
+
5
+ if ( ! class_exists( 'RWMB_Key_Value_Field' ) )
6
+ {
7
+ class RWMB_Key_Value_Field extends RWMB_Field
8
+ {
9
+ /**
10
+ * Get field HTML
11
+ *
12
+ * @param mixed $meta
13
+ * @param array $field
14
+ *
15
+ * @return string
16
+ */
17
+ static function html( $meta, $field )
18
+ {
19
+ $tpl = '<input type="text" class="rwmb-key-val" name="%s[]" value="%s" placeholder="' . esc_attr__( 'Key', 'meta-box' ) . '">';
20
+ $tpl .= '<input type="text" class="rwmb-key-val" name="%s[]" value="%s" placeholder="' . esc_attr__( 'Value', 'meta-box' ) . '">';
21
+
22
+ $key = isset( $meta[0] ) ? $meta[0] : '';
23
+ $val = isset( $meta[1] ) ? $meta[1] : '';
24
+
25
+ $html = sprintf( $tpl, $field['field_name'], $key, $field['field_name'], $val );
26
+
27
+ return $html;
28
+ }
29
+
30
+ /**
31
+ * Show begin HTML markup for fields
32
+ *
33
+ * @param mixed $meta
34
+ * @param array $field
35
+ *
36
+ * @return string
37
+ */
38
+ static function begin_html( $meta, $field )
39
+ {
40
+ $desc = $field['desc'] ? "<p id='{$field['id']}_description' class='description'>{$field['desc']}</p>" : '';
41
+
42
+ if ( empty( $field['name'] ) )
43
+ return '<div class="rwmb-input">' . $desc;
44
+
45
+ return sprintf(
46
+ '<div class="rwmb-label">
47
+ <label for="%s">%s</label>
48
+ </div>
49
+ <div class="rwmb-input">
50
+ %s',
51
+ $field['id'],
52
+ $field['name'],
53
+ $desc
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Show end HTML markup for fields
59
+ * Do not show field description. Field description is shown before list of fields
60
+ *
61
+ * @param mixed $meta
62
+ * @param array $field
63
+ *
64
+ * @return string
65
+ */
66
+ static function end_html( $meta, $field )
67
+ {
68
+ $button = $field['clone'] ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'add_clone_button' ), $field ) : '';
69
+
70
+ // Closes the container
71
+ $html = "$button</div>";
72
+
73
+ return $html;
74
+ }
75
+
76
+ /**
77
+ * Escape meta for field output
78
+ *
79
+ * @param mixed $meta
80
+ *
81
+ * @return mixed
82
+ */
83
+ static function esc_meta( $meta )
84
+ {
85
+ foreach ( (array) $meta as $k => $pairs )
86
+ {
87
+ $meta[$k] = array_map( 'esc_attr', (array) $pairs );
88
+ }
89
+ return $meta;
90
+ }
91
+
92
+ /**
93
+ * Sanitize email
94
+ *
95
+ * @param mixed $new
96
+ * @param mixed $old
97
+ * @param int $post_id
98
+ * @param array $field
99
+ *
100
+ * @return string
101
+ */
102
+ static function value( $new, $old, $post_id, $field )
103
+ {
104
+ foreach ( $new as &$arr )
105
+ {
106
+ if ( empty( $arr[0] ) && empty( $arr[1] ) )
107
+ $arr = false;
108
+ }
109
+
110
+ $new = array_filter( $new );
111
+
112
+ return $new;
113
+ }
114
+
115
+ /**
116
+ * Normalize parameters for field
117
+ *
118
+ * @param array $field
119
+ *
120
+ * @return array
121
+ */
122
+ static function normalize_field( $field )
123
+ {
124
+ $field['clone'] = true;
125
+ $field['multiple'] = false;
126
+
127
+ return $field;
128
+ }
129
+
130
+ /**
131
+ * Output the field value
132
+ * Display unordered list of key - value pairs
133
+ *
134
+ * @use self::get_value()
135
+ * @see rwmb_the_field()
136
+ *
137
+ * @param array $field Field parameters
138
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
139
+ * @param int|null $post_id Post ID. null for current post. Optional.
140
+ *
141
+ * @return string HTML output of the field
142
+ */
143
+ static function the_value( $field, $args = array(), $post_id = null )
144
+ {
145
+ $value = self::get_value( $field, $args, $post_id );
146
+ if ( ! is_array( $value ) )
147
+ return '';
148
+
149
+ $output = '<ul>';
150
+ foreach ( $value as $subvalue )
151
+ {
152
+ $output .= sprintf( '<li><label>%s</label>: %s</li>', $subvalue[0], $subvalue[1] );
153
+ }
154
+ $output .= '</ul>';
155
+ return $output;
156
+ }
157
+ }
158
+ }
inc/fields/map.php CHANGED
@@ -13,8 +13,9 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
13
  */
14
  static function admin_enqueue_scripts()
15
  {
16
- wp_enqueue_script( 'googlemap', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
17
- wp_enqueue_script( 'rwmb-map', RWMB_JS_URL . 'map.js', array( 'jquery', 'jquery-ui-autocomplete', 'googlemap' ), RWMB_VER, true );
 
18
  }
19
 
20
  /**
@@ -27,20 +28,17 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
27
  */
28
  static function html( $meta, $field )
29
  {
30
- $address = isset( $field['address_field'] ) ? $field['address_field'] : false;
31
-
32
  $html = '<div class="rwmb-map-field">';
33
 
34
  $html .= sprintf(
35
- '<div class="rwmb-map-canvas" style="%s"%s></div>
36
  <input type="hidden" name="%s" class="rwmb-map-coordinate" value="%s">',
37
- isset( $field['style'] ) ? $field['style'] : '',
38
- isset( $field['std'] ) ? " data-default-loc=\"{$field['std']}\"" : '',
39
- $field['field_name'],
40
- $meta
41
  );
42
 
43
- if ( $address )
44
  {
45
  $html .= sprintf(
46
  '<button class="button rwmb-map-goto-address-button" value="%s">%s</button>',
@@ -53,5 +51,104 @@ if ( ! class_exists( 'RWMB_Map_Field' ) )
53
 
54
  return $html;
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
  }
13
  */
14
  static function admin_enqueue_scripts()
15
  {
16
+ wp_register_script( 'google-maps', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
17
+ wp_enqueue_style( 'rwmb-map', RWMB_CSS_URL . 'map.css' );
18
+ wp_enqueue_script( 'rwmb-map', RWMB_JS_URL . 'map.js', array( 'jquery-ui-autocomplete', 'google-maps' ), RWMB_VER, true );
19
  }
20
 
21
  /**
28
  */
29
  static function html( $meta, $field )
30
  {
 
 
31
  $html = '<div class="rwmb-map-field">';
32
 
33
  $html .= sprintf(
34
+ '<div class="rwmb-map-canvas" data-default-loc="%s"></div>
35
  <input type="hidden" name="%s" class="rwmb-map-coordinate" value="%s">',
36
+ esc_attr( $field['std'] ),
37
+ esc_attr( $field['field_name'] ),
38
+ esc_attr( $meta )
 
39
  );
40
 
41
+ if ( $address = $field['address_field'] )
42
  {
43
  $html .= sprintf(
44
  '<button class="button rwmb-map-goto-address-button" value="%s">%s</button>',
51
 
52
  return $html;
53
  }
54
+
55
+ /**
56
+ * Normalize parameters for field
57
+ *
58
+ * @param array $field
59
+ *
60
+ * @return array
61
+ */
62
+ static function normalize_field( $field )
63
+ {
64
+ $field = wp_parse_args( $field, array(
65
+ 'std' => '',
66
+ 'address_field' => '',
67
+ ) );
68
+
69
+ return $field;
70
+ }
71
+
72
+ /**
73
+ * Get the field value
74
+ * The difference between this function and 'meta' function is 'meta' function always returns the escaped value
75
+ * of the field saved in the database, while this function returns more meaningful value of the field
76
+ *
77
+ * @param array $field Field parameters
78
+ * @param array $args Not used for this field
79
+ * @param int|null $post_id Post ID. null for current post. Optional.
80
+ *
81
+ * @return mixed Array(latitude, longitude, zoom)
82
+ */
83
+ static function get_value( $field, $args = array(), $post_id = null )
84
+ {
85
+ $value = parent::get_value( $field, $args, $post_id );
86
+ list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' );
87
+ return compact( 'latitude', 'longitude', 'zoom' );
88
+ }
89
+
90
+ /**
91
+ * Output the field value
92
+ * Display Google maps
93
+ *
94
+ * @param array $field Field parameters
95
+ * @param array $args Additional arguments. Not used for these fields.
96
+ * @param int|null $post_id Post ID. null for current post. Optional.
97
+ *
98
+ * @return mixed Field value
99
+ */
100
+ static function the_value( $field, $args = array(), $post_id = null )
101
+ {
102
+ $value = self::get_value( $field, $args, $post_id );
103
+ if ( ! $value['latitude'] || ! $value['longitude'] )
104
+ {
105
+ return '';
106
+ }
107
+ if ( ! $value['zoom'] )
108
+ {
109
+ $value['zoom'] = 14;
110
+ }
111
+
112
+ /**
113
+ * Enqueue scripts
114
+ * Note: We still can enqueue script which outputs in the footer
115
+ */
116
+ wp_register_script( 'google-maps', 'https://maps.google.com/maps/api/js?sensor=false', array(), '', true );
117
+ wp_enqueue_script( 'rwmb-map-frontend', RWMB_JS_URL . 'map-frontend.js', array( 'google-maps' ), '', true );
118
+
119
+ // Map parameters
120
+ $args = wp_parse_args( $args, array(
121
+ 'latitude' => $value['latitude'],
122
+ 'longitude' => $value['longitude'],
123
+ 'width' => '100%',
124
+ 'height' => '480px',
125
+ 'marker' => true, // Display marker?
126
+ 'marker_title' => '', // Marker title, when hover
127
+ 'info_window' => '', // Content of info window (when click on marker). HTML allowed
128
+ 'js_options' => array(),
129
+ ) );
130
+
131
+ /**
132
+ * Google Maps options
133
+ * Option name is the same as specified in Google Maps documentation
134
+ * This array will be convert to Javascript Object and pass as map options
135
+ * @link https://developers.google.com/maps/documentation/javascript/reference
136
+ */
137
+ $args['js_options'] = wp_parse_args( $args['js_options'], array(
138
+ // Default to 'zoom' level set in admin, but can be overwritten
139
+ 'zoom' => $value['zoom'],
140
+
141
+ // Map type, see https://developers.google.com/maps/documentation/javascript/reference#MapTypeId
142
+ 'mapTypeId' => 'ROADMAP',
143
+ ) );
144
+
145
+ $output = sprintf(
146
+ '<div class="rwmb-map-canvas" data-map_options="%s" style="width:%s;height:%s"></div>',
147
+ esc_attr( wp_json_encode( $args ) ),
148
+ esc_attr( $args['width'] ),
149
+ esc_attr( $args['height'] )
150
+ );
151
+ return $output;
152
+ }
153
  }
154
  }
inc/fields/oembed.php CHANGED
@@ -78,5 +78,34 @@ if ( ! class_exists( 'RWMB_OEmbed_Field' ) )
78
  $meta ? self::get_embed( $meta ) : ''
79
  );
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
  }
78
  $meta ? self::get_embed( $meta ) : ''
79
  );
80
  }
81
+
82
+ /**
83
+ * Output the field value
84
+ * Display embed media
85
+ *
86
+ * @param array $field Field parameters
87
+ * @param array $args Additional arguments. Not used for these fields.
88
+ * @param int|null $post_id Post ID. null for current post. Optional.
89
+ *
90
+ * @return mixed Field value
91
+ */
92
+ static function the_value( $field, $args = array(), $post_id = null )
93
+ {
94
+ $value = self::get_value( $field, $args, $post_id );
95
+ if ( $field['clone'] )
96
+ {
97
+ $output = '<ul>';
98
+ foreach ( $value as $subvalue )
99
+ {
100
+ $output .= '<li>' . self::get_embed( $subvalue ) . '</li>';
101
+ }
102
+ $output .= '</ul>';
103
+ }
104
+ else
105
+ {
106
+ $output = self::get_embed( $value );
107
+ }
108
+ return $output;
109
+ }
110
  }
111
  }
inc/fields/plupload-image.php CHANGED
@@ -127,7 +127,7 @@ if ( ! class_exists( 'RWMB_Plupload_Image_Field' ) )
127
  $field['id'],
128
  implode( ' ', $classes ),
129
  wp_create_nonce( "rwmb-upload-images_{$field['id']}" ),
130
- esc_attr( json_encode( $field['js_options'] ) ),
131
  $i18n_drop,
132
  $i18n_or,
133
  $field['id'],
127
  $field['id'],
128
  implode( ' ', $classes ),
129
  wp_create_nonce( "rwmb-upload-images_{$field['id']}" ),
130
+ esc_attr( wp_json_encode( $field['js_options'] ) ),
131
  $i18n_drop,
132
  $i18n_or,
133
  $field['id'],
inc/fields/post.php CHANGED
@@ -2,23 +2,13 @@
2
  // Prevent loading this file directly
3
  defined( 'ABSPATH' ) || exit;
4
 
5
- // Make sure "select" field is loaded
6
  require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_Post_Field' ) )
9
  {
10
- class RWMB_Post_Field extends RWMB_Field
11
  {
12
- /**
13
- * Enqueue scripts and styles
14
- *
15
- * @return void
16
- */
17
- static function admin_enqueue_scripts()
18
- {
19
- RWMB_Select_Advanced_Field::admin_enqueue_scripts();
20
- }
21
-
22
  /**
23
  * Get field HTML
24
  *
@@ -49,13 +39,6 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
49
  */
50
  static function normalize_field( $field )
51
  {
52
- $default_post_type = __( 'Post', 'meta-box' );
53
- if ( is_string( $field['post_type'] ) )
54
- {
55
- $post_type_object = get_post_type_object( $field['post_type'] );
56
- $default_post_type = $post_type_object->labels->singular_name;
57
- }
58
-
59
  $field = wp_parse_args( $field, array(
60
  'post_type' => 'post',
61
  'field_type' => 'select_advanced',
@@ -63,7 +46,21 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
63
  'query_args' => array(),
64
  ) );
65
 
66
- $field['std'] = empty( $field['std'] ) ? sprintf( __( 'Select a %s', 'meta-box' ), $default_post_type ) : $field['std'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  if ( $field['parent'] )
69
  {
@@ -110,24 +107,7 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
110
  return $post->post_parent;
111
  }
112
 
113
- return RWMB_Select_Field::meta( $post_id, $saved, $field );
114
- }
115
-
116
- /**
117
- * Save meta value
118
- * If field is cloneable, value is saved as a single entry in DB
119
- * Otherwise value is saved as multiple entries (for backward compatibility)
120
- *
121
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
122
- *
123
- * @param $new
124
- * @param $old
125
- * @param $post_id
126
- * @param $field
127
- */
128
- static function save( $new, $old, $post_id, $field )
129
- {
130
- return RWMB_Select_Field::save( $new, $old, $post_id, $field );
131
  }
132
 
133
  /**
@@ -152,5 +132,27 @@ if ( ! class_exists( 'RWMB_Post_Field' ) )
152
 
153
  return $options;
154
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
  }
2
  // Prevent loading this file directly
3
  defined( 'ABSPATH' ) || exit;
4
 
5
+ // Make sure "select-advanced" field is loaded
6
  require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_Post_Field' ) )
9
  {
10
+ class RWMB_Post_Field extends RWMB_Select_Advanced_Field
11
  {
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Get field HTML
14
  *
39
  */
40
  static function normalize_field( $field )
41
  {
 
 
 
 
 
 
 
42
  $field = wp_parse_args( $field, array(
43
  'post_type' => 'post',
44
  'field_type' => 'select_advanced',
46
  'query_args' => array(),
47
  ) );
48
 
49
+ /**
50
+ * Set default placeholder
51
+ * - If multiple post types: show 'Select a post'
52
+ * - If single post type: show 'Select a %post_type_name%'
53
+ */
54
+ if ( empty( $field['placeholder'] ) )
55
+ {
56
+ $label = __( 'Select a post', 'meta-box' );
57
+ if ( is_string( $field['post_type'] ) )
58
+ {
59
+ $post_type_object = get_post_type_object( $field['post_type'] );
60
+ $label = sprintf( __( 'Select a %s', 'meta-box' ), $post_type_object->labels->singular_name );
61
+ }
62
+ $field['placeholder'] = $label;
63
+ }
64
 
65
  if ( $field['parent'] )
66
  {
107
  return $post->post_parent;
108
  }
109
 
110
+ return parent::meta( $post_id, $saved, $field );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
  /**
132
 
133
  return $options;
134
  }
135
+
136
+ /**
137
+ * Get post link to display in the frontend
138
+ *
139
+ * @param int $value Option value, e.g. post ID
140
+ * @param int $index Array index
141
+ * @param array $field Field parameter
142
+ *
143
+ * @return string
144
+ */
145
+ static function get_option_label( &$value, $index, $field )
146
+ {
147
+ $value = sprintf(
148
+ '<a href="%s" title="%s">%s</a>',
149
+ esc_url( get_permalink( $value ) ),
150
+ the_title_attribute( array(
151
+ 'post' => $value,
152
+ 'echo' => false,
153
+ ) ),
154
+ get_the_title( $value )
155
+ );
156
+ }
157
  }
158
  }
inc/fields/radio.php CHANGED
@@ -32,5 +32,24 @@ if ( ! class_exists( 'RWMB_Radio_Field' ) )
32
 
33
  return implode( ' ', $html );
34
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  }
32
 
33
  return implode( ' ', $html );
34
  }
35
+
36
+ /**
37
+ * Output the field value
38
+ * Display option name instead of option value
39
+ *
40
+ * @use self::meta()
41
+ *
42
+ * @param array $field Field parameters
43
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
44
+ * @param int|null $post_id Post ID. null for current post. Optional.
45
+ *
46
+ * @return mixed Field value
47
+ */
48
+ static function the_value( $field, $args = array(), $post_id = null )
49
+ {
50
+ $value = parent::get_value( $field, $args, $post_id );
51
+
52
+ return empty( $value ) ? '' : $field['options'][$value];
53
+ }
54
  }
55
  }
inc/fields/select-advanced.php CHANGED
@@ -38,8 +38,8 @@ if ( ! class_exists( 'RWMB_Select_Advanced_Field' ) )
38
  $field['field_name'],
39
  $field['id'],
40
  $field['size'],
41
- $field['multiple'] ? ' multiple="multiple"' : '',
42
- esc_attr( json_encode( $field['js_options'] ) )
43
  );
44
 
45
  $html .= self::options_html( $field, $meta );
38
  $field['field_name'],
39
  $field['id'],
40
  $field['size'],
41
+ $field['multiple'] ? ' multiple' : '',
42
+ esc_attr( wp_json_encode( $field['js_options'] ) )
43
  );
44
 
45
  $html .= self::options_html( $field, $meta );
inc/fields/select.php CHANGED
@@ -31,7 +31,7 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
31
  $field['field_name'],
32
  $field['id'],
33
  $field['size'],
34
- $field['multiple'] ? ' multiple="multiple"' : ''
35
  );
36
 
37
  $html .= self::options_html( $field, $meta );
@@ -41,43 +41,17 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
41
  return $html;
42
  }
43
 
44
- /**
45
- * Get meta value
46
- * If field is cloneable, value is saved as a single entry in DB
47
- * Otherwise value is saved as multiple entries (for backward compatibility)
48
- *
49
- * @see "save" method for better understanding
50
- *
51
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
52
- *
53
- * @param $post_id
54
- * @param $saved
55
- * @param $field
56
- *
57
- * @return array
58
- */
59
- static function meta( $post_id, $saved, $field )
60
- {
61
- $single = $field['clone'] || ! $field['multiple'];
62
- $meta = get_post_meta( $post_id, $field['id'], $single );
63
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
64
-
65
- $meta = array_map( 'esc_attr', (array) $meta );
66
-
67
- return $meta;
68
- }
69
-
70
  /**
71
  * Save meta value
72
  * If field is cloneable, value is saved as a single entry in DB
73
  * Otherwise value is saved as multiple entries (for backward compatibility)
74
  *
75
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
76
- *
77
  * @param $new
78
  * @param $old
79
  * @param $post_id
80
  * @param $field
 
 
81
  */
82
  static function save( $new, $old, $post_id, $field )
83
  {
@@ -128,10 +102,10 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
128
  $html = '';
129
  if ( $field['placeholder'] )
130
  {
131
- $show_placeholder = ( 'select' == $field['type'] ) // Normal select field
132
- || ( isset( $field['field_type'] ) && 'select' == $field['field_type'] ) // For 'post' field
133
- || ( isset( $field['display_type'] ) && 'select' == $field['display_type'] ); // For 'taxonomy' field
134
- $html = $show_placeholder ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
135
  }
136
 
137
  $option = '<option value="%s"%s>%s</option>';
@@ -148,5 +122,74 @@ if ( ! class_exists( 'RWMB_Select_Field' ) )
148
 
149
  return $html;
150
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
  }
31
  $field['field_name'],
32
  $field['id'],
33
  $field['size'],
34
+ $field['multiple'] ? ' multiple' : ''
35
  );
36
 
37
  $html .= self::options_html( $field, $meta );
41
  return $html;
42
  }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Save meta value
46
  * If field is cloneable, value is saved as a single entry in DB
47
  * Otherwise value is saved as multiple entries (for backward compatibility)
48
  *
 
 
49
  * @param $new
50
  * @param $old
51
  * @param $post_id
52
  * @param $field
53
+ *
54
+ * @return void
55
  */
56
  static function save( $new, $old, $post_id, $field )
57
  {
102
  $html = '';
103
  if ( $field['placeholder'] )
104
  {
105
+ $show_placeholder = ( 'select' === $field['type'] ) // Normal select field
106
+ || ( isset( $field['field_type'] ) && 'select' === $field['field_type'] ) // For 'post' field
107
+ || ( isset( $field['display_type'] ) && 'select' === $field['display_type'] ); // For 'taxonomy' field
108
+ $html = $show_placeholder ? "<option value=''>{$field['placeholder']}</option>" : '<option></option>';
109
  }
110
 
111
  $option = '<option value="%s"%s>%s</option>';
122
 
123
  return $html;
124
  }
125
+
126
+ /**
127
+ * Output the field value
128
+ * Display unordered list of option labels, not option values
129
+ *
130
+ * @param array $field Field parameters
131
+ * @param array $args Additional arguments. Not used for these fields.
132
+ * @param int|null $post_id Post ID. null for current post. Optional.
133
+ *
134
+ * @return string Link(s) to post
135
+ */
136
+ static function the_value( $field, $args = array(), $post_id = null )
137
+ {
138
+ $value = self::get_value( $field, $args, $post_id );
139
+ if ( ! $value )
140
+ return '';
141
+
142
+ $function = array( RW_Meta_Box::get_class_name( $field ), 'get_option_label' );
143
+
144
+ if ( $field['clone'] )
145
+ {
146
+ $output = '<ul>';
147
+ if ( $field['multiple'] )
148
+ {
149
+ foreach ( $value as $subvalue )
150
+ {
151
+ $output .= '<li>';
152
+ array_walk_recursive( $subvalue, $function, $field );
153
+ $output .= '<ul><li>' . implode( '</li><li>', $subvalue ) . '</li></ul>';
154
+ $output .= '</li>';
155
+ }
156
+ }
157
+ else
158
+ {
159
+ array_walk_recursive( $value, $function, $field );
160
+ $output = '<li>' . implode( '</li><li>', $value ) . '</li>';
161
+ }
162
+ $output .= '</ul>';
163
+ }
164
+ else
165
+ {
166
+ if ( $field['multiple'] )
167
+ {
168
+ array_walk_recursive( $value, $function, $field );
169
+ $output = '<ul><li>' . implode( '</li><li>', $value ) . '</li></ul>';
170
+ }
171
+ else
172
+ {
173
+ call_user_func_array( $function, array( &$value, 0, $field ) );
174
+ $output = $value;
175
+ }
176
+ }
177
+
178
+ return $output;
179
+ }
180
+
181
+ /**
182
+ * Get option label to display in the frontend
183
+ *
184
+ * @param int $value Option value
185
+ * @param int $index Array index
186
+ * @param array $field Field parameter
187
+ *
188
+ * @return string
189
+ */
190
+ static function get_option_label( &$value, $index, $field )
191
+ {
192
+ $value = $field['options'][$value];
193
+ }
194
  }
195
  }
inc/fields/slider.php CHANGED
@@ -38,7 +38,7 @@ if ( ! class_exists( 'RWMB_Slider_Field' ) )
38
  <span class="rwmb-slider-value-label">%s<span>%s</span>%s</span>
39
  <input type="hidden" name="%s" value="%s" class="rwmb-slider-value">
40
  </div>',
41
- $field['id'], esc_attr( json_encode( $field['js_options'] ) ),
42
  $field['prefix'], $meta, $field['suffix'],
43
  $field['field_name'], $meta
44
  );
38
  <span class="rwmb-slider-value-label">%s<span>%s</span>%s</span>
39
  <input type="hidden" name="%s" value="%s" class="rwmb-slider-value">
40
  </div>',
41
+ $field['id'], esc_attr( wp_json_encode( $field['js_options'] ) ),
42
  $field['prefix'], $meta, $field['suffix'],
43
  $field['field_name'], $meta
44
  );
inc/fields/taxonomy-advanced.php CHANGED
@@ -58,5 +58,37 @@ if ( ! class_exists( 'RWMB_Taxonomy_Advanced_Field' ) )
58
 
59
  return $meta;
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
  }
58
 
59
  return $meta;
60
  }
61
+
62
+ /**
63
+ * Get the field value
64
+ * Return list of post term objects
65
+ *
66
+ * @param array $field Field parameters
67
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
68
+ * @param int|null $post_id Post ID. null for current post. Optional.
69
+ *
70
+ * @return array List of post term objects
71
+ */
72
+ static function get_value( $field, $args = array(), $post_id = null )
73
+ {
74
+ if ( ! $post_id )
75
+ $post_id = get_the_ID();
76
+
77
+ $value = self::meta( $post_id, '', $field );
78
+
79
+ // Allow to pass more arguments to "get_terms"
80
+ $args = wp_parse_args( array(
81
+ 'include' => $value,
82
+ 'hide_empty' => false,
83
+ ), $args );
84
+ $value = get_terms( $field['options']['taxonomy'], $args );
85
+
86
+ // Get single value if necessary
87
+ if ( ! $field['clone'] && ! $field['multiple'] )
88
+ {
89
+ $value = reset( $value );
90
+ }
91
+ return $value;
92
+ }
93
  }
94
  }
inc/fields/taxonomy.php CHANGED
@@ -17,7 +17,7 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
17
  {
18
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
19
  wp_enqueue_style( 'rwmb-taxonomy', RWMB_CSS_URL . 'taxonomy.css', array(), RWMB_VER );
20
- wp_enqueue_script( 'rwmb-taxonomy', RWMB_JS_URL . 'taxonomy.js', array( 'jquery', 'rwmb-select-advanced', 'wp-ajax-response' ), RWMB_VER, true );
21
  }
22
 
23
  /**
@@ -88,7 +88,7 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
88
  $options = $field['options'];
89
  $terms = get_terms( $options['taxonomy'], $options['args'] );
90
 
91
- $field['options'] = self::get_options( $terms );
92
  $field['display_type'] = $options['type'];
93
 
94
  $html = '';
@@ -260,5 +260,105 @@ if ( ! class_exists( 'RWMB_Taxonomy_Field' ) )
260
 
261
  return $meta;
262
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  }
264
  }
17
  {
18
  RWMB_Select_Advanced_Field::admin_enqueue_scripts();
19
  wp_enqueue_style( 'rwmb-taxonomy', RWMB_CSS_URL . 'taxonomy.css', array(), RWMB_VER );
20
+ wp_enqueue_script( 'rwmb-taxonomy', RWMB_JS_URL . 'taxonomy.js', array( 'rwmb-select-advanced' ), RWMB_VER, true );
21
  }
22
 
23
  /**
88
  $options = $field['options'];
89
  $terms = get_terms( $options['taxonomy'], $options['args'] );
90
 
91
+ $field['options'] = self::get_options( $terms );
92
  $field['display_type'] = $options['type'];
93
 
94
  $html = '';
260
 
261
  return $meta;
262
  }
263
+
264
+ /**
265
+ * Get the field value
266
+ * Return list of post term objects
267
+ *
268
+ * @param array $field Field parameters
269
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
270
+ * @param int|null $post_id Post ID. null for current post. Optional.
271
+ *
272
+ * @return array List of post term objects
273
+ */
274
+ static function get_value( $field, $args = array(), $post_id = null )
275
+ {
276
+ if ( ! $post_id )
277
+ $post_id = get_the_ID();
278
+
279
+ $value = wp_get_post_terms( $post_id, $field['options']['taxonomy'] );
280
+
281
+ // Get single value if necessary
282
+ if ( ! $field['clone'] && ! $field['multiple'] )
283
+ {
284
+ $value = reset( $value );
285
+ }
286
+ return $value;
287
+ }
288
+
289
+ /**
290
+ * Output the field value
291
+ * Display unordered list of option labels, not option values
292
+ *
293
+ * @param array $field Field parameters
294
+ * @param array $args Additional arguments. Not used for these fields.
295
+ * @param int|null $post_id Post ID. null for current post. Optional.
296
+ *
297
+ * @return string Link(s) to post
298
+ */
299
+ static function the_value( $field, $args = array(), $post_id = null )
300
+ {
301
+ $class = RW_Meta_Box::get_class_name( $field );
302
+ $value = call_user_func( array( $class, 'get_value' ), $field, $args, $post_id );
303
+ if ( ! $value || is_wp_error( $value ) )
304
+ return '';
305
+
306
+ $function = array( $class, 'get_option_label' );
307
+
308
+ if ( $field['clone'] )
309
+ {
310
+ $output = '<ul>';
311
+ if ( $field['multiple'] )
312
+ {
313
+ foreach ( $value as $subvalue )
314
+ {
315
+ $output .= '<li>';
316
+ array_walk_recursive( $subvalue, $function, $field );
317
+ $output .= '<ul><li>' . implode( '</li><li>', $subvalue ) . '</li></ul>';
318
+ $output .= '</li>';
319
+ }
320
+ }
321
+ else
322
+ {
323
+ array_walk_recursive( $value, $function, $field );
324
+ $output = '<li>' . implode( '</li><li>', $value ) . '</li>';
325
+ }
326
+ $output .= '</ul>';
327
+ }
328
+ else
329
+ {
330
+ if ( $field['multiple'] )
331
+ {
332
+ array_walk_recursive( $value, $function, $field );
333
+ $output = '<ul><li>' . implode( '</li><li>', $value ) . '</li></ul>';
334
+ }
335
+ else
336
+ {
337
+ call_user_func_array( $function, array( &$value, 0, $field ) );
338
+ $output = $value;
339
+ }
340
+ }
341
+
342
+ return $output;
343
+ }
344
+
345
+ /**
346
+ * Get post link to display in the frontend
347
+ *
348
+ * @param object $value Option value, e.g. term object
349
+ * @param int $index Array index
350
+ * @param array $field Field parameter
351
+ *
352
+ * @return string
353
+ */
354
+ static function get_option_label( &$value, $index, $field )
355
+ {
356
+ $value = sprintf(
357
+ '<a href="%s" title="%s">%s</a>',
358
+ esc_url( get_term_link( $value ) ),
359
+ esc_attr( $value->name ),
360
+ $value->name
361
+ );
362
+ }
363
  }
364
  }
inc/fields/text-list.php CHANGED
@@ -4,7 +4,7 @@ defined( 'ABSPATH' ) || exit;
4
 
5
  if ( ! class_exists( 'RWMB_Text_List_Field' ) )
6
  {
7
- class RWMB_Text_List_Field extends RWMB_Field
8
  {
9
  /**
10
  * Get field HTML
@@ -16,92 +16,79 @@ if ( ! class_exists( 'RWMB_Text_List_Field' ) )
16
  */
17
  static function html( $meta, $field )
18
  {
19
- $html = '';
20
- $input = '<label><input type="text" class="rwmb-text-list" name="%s" id="%s" value="%s" placeholder="%s" /> %s</label>';
21
 
22
  $i = 0;
23
- foreach ( $field['options'] as $value => $label )
24
  {
25
- $html .= sprintf(
26
  $input,
27
  $field['field_name'],
28
- $field['id'],
29
  isset( $meta[$i] ) ? esc_attr( $meta[$i] ) : '',
30
- $value,
31
  $label
32
  );
33
  $i ++;
34
  }
35
 
36
- return $html;
37
  }
38
 
39
  /**
40
- * Get meta value
41
- * If field is cloneable, value is saved as a single entry in DB
42
- * Otherwise value is saved as multiple entries (for backward compatibility)
43
  *
44
- * @see "save" method for better understanding
 
 
45
  *
46
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
47
- *
48
- * @param $post_id
49
- * @param $saved
50
- * @param $field
51
- *
52
- * @return array
53
  */
54
- static function meta( $post_id, $saved, $field )
55
  {
56
- $single = $field['clone'] || ! $field['multiple'];
57
- $meta = get_post_meta( $post_id, $field['id'], $single );
58
- $meta = ( ! $saved && '' === $meta || array() === $meta ) ? $field['std'] : $meta;
59
 
60
- return $meta;
61
- }
62
-
63
- /**
64
- * Save meta value
65
- * If field is cloneable, value is saved as a single entry in DB
66
- * Otherwise value is saved as multiple entries (for backward compatibility)
67
- *
68
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
69
- *
70
- * @param $new
71
- * @param $old
72
- * @param $post_id
73
- * @param $field
74
- */
75
- static function save( $new, $old, $post_id, $field )
76
- {
77
- if ( ! $field['clone'] )
78
  {
79
- parent::save( $new, $old, $post_id, $field );
 
 
 
80
 
81
- return;
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
83
-
84
- if ( empty( $new ) )
85
- delete_post_meta( $post_id, $field['id'] );
86
  else
87
- update_post_meta( $post_id, $field['id'], $new );
88
- }
89
-
90
- /**
91
- * Normalize parameters for field
92
- *
93
- * @param array $field
94
- *
95
- * @return array
96
- */
97
- static function normalize_field( $field )
98
- {
99
- $field['multiple'] = true;
100
- $field['field_name'] = $field['id'];
101
- if ( ! $field['clone'] )
102
- $field['field_name'] .= '[]';
103
 
104
- return $field;
105
  }
106
  }
107
  }
4
 
5
  if ( ! class_exists( 'RWMB_Text_List_Field' ) )
6
  {
7
+ class RWMB_Text_List_Field extends RWMB_Field_Multiple_Values
8
  {
9
  /**
10
  * Get field HTML
16
  */
17
  static function html( $meta, $field )
18
  {
19
+ $html = array();
20
+ $input = '<label><input type="text" class="rwmb-text-list" name="%s" value="%s" placeholder="%s"> %s</label>';
21
 
22
  $i = 0;
23
+ foreach ( $field['options'] as $placeholder => $label )
24
  {
25
+ $html[] = sprintf(
26
  $input,
27
  $field['field_name'],
 
28
  isset( $meta[$i] ) ? esc_attr( $meta[$i] ) : '',
29
+ $placeholder,
30
  $label
31
  );
32
  $i ++;
33
  }
34
 
35
+ return implode( ' ', $html );
36
  }
37
 
38
  /**
39
+ * Output the field value
40
+ * Display option name instead of option value
 
41
  *
42
+ * @param array $field Field parameters
43
+ * @param array $args Additional arguments. Not used for these fields.
44
+ * @param int|null $post_id Post ID. null for current post. Optional.
45
  *
46
+ * @return mixed Field value
 
 
 
 
 
 
47
  */
48
+ static function the_value( $field, $args = array(), $post_id = null )
49
  {
50
+ $value = self::get_value( $field, $args, $post_id );
51
+ if ( ! $value )
52
+ return '';
53
 
54
+ $output = '<ul>';
55
+ if ( $field['clone'] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  {
57
+ foreach ( $value as $subvalue )
58
+ {
59
+ $output .= '<li>';
60
+ $output .= '<ul>';
61
 
62
+ $i = 0;
63
+ foreach ( $field['options'] as $placeholder => $label )
64
+ {
65
+ $output .= sprintf(
66
+ '<li><label>%s</label>: %s</li>',
67
+ $label,
68
+ isset( $subvalue[$i] ) ? $subvalue[$i] : ''
69
+ );
70
+ $i ++;
71
+ }
72
+ $output .= '</ul>';
73
+ $output .= '</li>';
74
+ }
75
  }
 
 
 
76
  else
77
+ {
78
+ $i = 0;
79
+ foreach ( $field['options'] as $placeholder => $label )
80
+ {
81
+ $output .= sprintf(
82
+ '<li><label>%s</label>: %s</li>',
83
+ $label,
84
+ isset( $value[$i] ) ? $value[$i] : ''
85
+ );
86
+ $i ++;
87
+ }
88
+ }
89
+ $output .= '</ul>';
 
 
 
90
 
91
+ return $output;
92
  }
93
  }
94
  }
inc/fields/textarea.php CHANGED
@@ -27,6 +27,18 @@ if ( ! class_exists( 'RWMB_Textarea_Field' ) )
27
  );
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Normalize parameters for field
32
  *
27
  );
28
  }
29
 
30
+ /**
31
+ * Escape meta for field output
32
+ *
33
+ * @param mixed $meta
34
+ *
35
+ * @return mixed
36
+ */
37
+ static function esc_meta( $meta )
38
+ {
39
+ return is_array( $meta ) ? array_map( 'esc_textarea', $meta ) : esc_textarea( $meta );
40
+ }
41
+
42
  /**
43
  * Normalize parameters for field
44
  *
inc/fields/time.php CHANGED
@@ -57,7 +57,7 @@ if ( ! class_exists( 'RWMB_Time_Field' ) )
57
  $meta,
58
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
59
  $field['size'],
60
- esc_attr( json_encode( $field['js_options'] ) )
61
  );
62
  }
63
 
57
  $meta,
58
  isset( $field['clone'] ) && $field['clone'] ? '' : $field['id'],
59
  $field['size'],
60
+ esc_attr( wp_json_encode( $field['js_options'] ) )
61
  );
62
  }
63
 
inc/fields/user.php CHANGED
@@ -7,18 +7,8 @@ require_once RWMB_FIELDS_DIR . 'select-advanced.php';
7
 
8
  if ( ! class_exists( 'RWMB_User_Field' ) )
9
  {
10
- class RWMB_User_Field extends RWMB_Field
11
  {
12
- /**
13
- * Enqueue scripts and styles
14
- *
15
- * @return void
16
- */
17
- static function admin_enqueue_scripts()
18
- {
19
- RWMB_Select_Advanced_Field::admin_enqueue_scripts();
20
- }
21
-
22
  /**
23
  * Get field HTML
24
  *
@@ -50,16 +40,13 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
50
  */
51
  static function normalize_field( $field )
52
  {
53
-
54
- $default_post_type = __( 'User', 'meta-box' );
55
-
56
  $field = wp_parse_args( $field, array(
57
  'field_type' => 'select_advanced',
58
  'parent' => false,
59
  'query_args' => array(),
60
  ) );
61
 
62
- $field['std'] = empty( $field['std'] ) ? sprintf( __( 'Select a %s', 'meta-box' ), $default_post_type ) : $field['std'];
63
 
64
  $field['query_args'] = wp_parse_args( $field['query_args'], array(
65
  'orderby' => 'display_name',
@@ -79,48 +66,6 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
79
  }
80
  }
81
 
82
- /**
83
- * Get meta value
84
- * If field is cloneable, value is saved as a single entry in DB
85
- * Otherwise value is saved as multiple entries (for backward compatibility)
86
- *
87
- * @see "save" method for better understanding
88
- *
89
- * @param $post_id
90
- * @param $saved
91
- * @param $field
92
- *
93
- * @return array
94
- */
95
- static function meta( $post_id, $saved, $field )
96
- {
97
- if ( isset( $field['parent'] ) && $field['parent'] )
98
- {
99
- $post = get_post( $post_id );
100
-
101
- return $post->post_parent;
102
- }
103
-
104
- return RWMB_Select_Field::meta( $post_id, $saved, $field );
105
- }
106
-
107
- /**
108
- * Save meta value
109
- * If field is cloneable, value is saved as a single entry in DB
110
- * Otherwise value is saved as multiple entries (for backward compatibility)
111
- *
112
- * TODO: A good way to ALWAYS save values in single entry in DB, while maintaining backward compatibility
113
- *
114
- * @param $new
115
- * @param $old
116
- * @param $post_id
117
- * @param $field
118
- */
119
- static function save( $new, $old, $post_id, $field )
120
- {
121
- return RWMB_Select_Field::save( $new, $old, $post_id, $field );
122
- }
123
-
124
  /**
125
  * Get users
126
  *
@@ -139,5 +84,20 @@ if ( ! class_exists( 'RWMB_User_Field' ) )
139
 
140
  return $options;
141
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
143
  }
7
 
8
  if ( ! class_exists( 'RWMB_User_Field' ) )
9
  {
10
+ class RWMB_User_Field extends RWMB_Select_Advanced_Field
11
  {
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Get field HTML
14
  *
40
  */
41
  static function normalize_field( $field )
42
  {
 
 
 
43
  $field = wp_parse_args( $field, array(
44
  'field_type' => 'select_advanced',
45
  'parent' => false,
46
  'query_args' => array(),
47
  ) );
48
 
49
+ $field['std'] = empty( $field['std'] ) ? __( 'Select an user', 'meta-box' ) : $field['std'];
50
 
51
  $field['query_args'] = wp_parse_args( $field['query_args'], array(
52
  'orderby' => 'display_name',
66
  }
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  /**
70
  * Get users
71
  *
84
 
85
  return $options;
86
  }
87
+
88
+ /**
89
+ * Get option label to display in the frontend
90
+ *
91
+ * @param int $value Option value
92
+ * @param int $index Array index
93
+ * @param array $field Field parameter
94
+ *
95
+ * @return string
96
+ */
97
+ static function get_option_label( &$value, $index, $field )
98
+ {
99
+ $user = get_userdata( $value );
100
+ $value = '<a href="' . get_author_posts_url( $value ) . '">' . $user->display_name . '</a>';
101
+ }
102
  }
103
  }
inc/fields/wysiwyg.php CHANGED
@@ -75,6 +75,18 @@ if ( ! class_exists( 'RWMB_Wysiwyg_Field' ) )
75
  return $editor;
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  /**
79
  * Normalize parameters for field
80
  *
@@ -102,7 +114,7 @@ if ( ! class_exists( 'RWMB_Wysiwyg_Field' ) )
102
 
103
  static function footer_scripts()
104
  {
105
- echo '<script> var rwmb_cloneable_editors = ' . json_encode( self::$cloneable_editors ) . ';</script>';
106
  }
107
  }
108
  }
75
  return $editor;
76
  }
77
 
78
+ /**
79
+ * Escape meta for field output
80
+ *
81
+ * @param mixed $meta
82
+ *
83
+ * @return mixed
84
+ */
85
+ static function esc_meta( $meta )
86
+ {
87
+ return $meta;
88
+ }
89
+
90
  /**
91
  * Normalize parameters for field
92
  *
114
 
115
  static function footer_scripts()
116
  {
117
+ echo '<script> var rwmb_cloneable_editors = ' . wp_json_encode( self::$cloneable_editors ) . ';</script>';
118
  }
119
  }
120
  }
inc/helpers.php CHANGED
@@ -15,110 +15,33 @@ if ( ! class_exists( 'RWMB_Helper' ) )
15
  class RWMB_Helper
16
  {
17
  /**
18
- * Do actions when class is loaded
 
 
19
  *
20
- * @return void
21
- */
22
- static function on_load()
23
- {
24
- add_shortcode( 'rwmb_meta', array( __CLASS__, 'shortcode' ) );
25
- }
26
-
27
- /**
28
- * Shortcode to display meta value
29
- *
30
- * @param $atts Array of shortcode attributes, same as meta() function, but has more "meta_key" parameter
31
  *
32
- * @see meta() function below
33
- *
34
- * @return string
35
  */
36
- static function shortcode( $atts )
37
  {
38
- $atts = wp_parse_args( $atts, array(
39
- 'type' => 'text',
40
- 'post_id' => get_the_ID(),
41
- ) );
42
- if ( empty( $atts['meta_key'] ) )
43
- return '';
44
 
45
- $meta = self::meta( $atts['meta_key'], $atts, $atts['post_id'] );
46
-
47
- // Get uploaded files info
48
- if ( in_array( $atts['type'], array( 'file', 'file_advanced' ) ) )
49
  {
50
- $content = '<ul>';
51
- foreach ( $meta as $file )
52
  {
53
- $content .= sprintf(
54
- '<li><a href="%s" title="%s">%s</a></li>',
55
- $file['url'],
56
- $file['title'],
57
- $file['name']
58
- );
59
- }
60
- $content .= '</ul>';
61
- }
62
-
63
- // Get uploaded images info
64
- elseif ( in_array( $atts['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
65
- {
66
- $content = '<ul>';
67
- foreach ( $meta as $image )
68
- {
69
- // Link thumbnail to full size image?
70
- if ( isset( $atts['link'] ) && $atts['link'] )
71
- {
72
- $content .= sprintf(
73
- '<li><a href="%s" title="%s"><img src="%s" alt="%s" title="%s" /></a></li>',
74
- $image['full_url'],
75
- $image['title'],
76
- $image['url'],
77
- $image['alt'],
78
- $image['title']
79
- );
80
- }
81
- else
82
  {
83
- $content .= sprintf(
84
- '<li><img src="%s" alt="%s" title="%s" /></li>',
85
- $image['url'],
86
- $image['alt'],
87
- $image['title']
88
- );
89
  }
90
  }
91
- $content .= '</ul>';
92
- }
93
-
94
- // Get post terms
95
- elseif ( 'taxonomy' == $atts['type'] )
96
- {
97
- $content = '<ul>';
98
- foreach ( $meta as $term )
99
- {
100
- $content .= sprintf(
101
- '<li><a href="%s" title="%s">%s</a></li>',
102
- get_term_link( $term, $atts['taxonomy'] ),
103
- $term->name,
104
- $term->name
105
- );
106
- }
107
- $content .= '</ul>';
108
- }
109
-
110
- // Normal multiple fields: checkbox_list, select with multiple values
111
- elseif ( is_array( $meta ) )
112
- {
113
- $content = '<ul><li>' . implode( '</li><li>', $meta ) . '</li></ul>';
114
- }
115
-
116
- else
117
- {
118
- $content = $meta;
119
  }
120
 
121
- return apply_filters( 'rwmb_shortcode', $content );
122
  }
123
 
124
  /**
@@ -133,14 +56,16 @@ if ( ! class_exists( 'RWMB_Helper' ) )
133
  static function meta( $key, $args = array(), $post_id = null )
134
  {
135
  $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
136
-
137
- $args = wp_parse_args( $args, array(
138
- 'type' => 'text',
139
  ) );
140
 
141
- // Set 'multiple' for fields based on 'type'
142
- if ( ! isset( $args['multiple'] ) )
143
- $args['multiple'] = in_array( $args['type'], array( 'checkbox_list', 'file', 'file_advanced', 'image', 'image_advanced', 'plupload_image', 'thickbox_image' ) );
 
 
144
 
145
  $meta = get_post_meta( $post_id, $key, ! $args['multiple'] );
146
 
@@ -155,24 +80,15 @@ if ( ! class_exists( 'RWMB_Helper' ) )
155
  // Get only info of existing attachments
156
  if ( get_attached_file( $id ) )
157
  {
158
- $files[$id] = self::file_info( $id );
159
  }
160
  }
161
  $meta = $files;
162
  }
163
  }
164
-
165
  // Get uploaded images info
166
  elseif ( in_array( $args['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
167
  {
168
- global $wpdb;
169
-
170
- $meta = $wpdb->get_col( $wpdb->prepare( "
171
- SELECT meta_value FROM $wpdb->postmeta
172
- WHERE post_id = %d AND meta_key = '%s'
173
- ORDER BY meta_id ASC
174
- ", $post_id, $key ) );
175
-
176
  if ( is_array( $meta ) && ! empty( $meta ) )
177
  {
178
  $images = array();
@@ -181,20 +97,18 @@ if ( ! class_exists( 'RWMB_Helper' ) )
181
  // Get only info of existing attachments
182
  if ( get_attached_file( $id ) )
183
  {
184
- $images[$id] = self::image_info( $id, $args );
185
  }
186
  }
187
  $meta = $images;
188
  }
189
  }
190
-
191
  // Get terms
192
  elseif ( 'taxonomy_advanced' == $args['type'] )
193
  {
194
  if ( ! empty( $args['taxonomy'] ) )
195
  {
196
  $term_ids = array_map( 'intval', array_filter( explode( ',', $meta . ',' ) ) );
197
-
198
  // Allow to pass more arguments to "get_terms"
199
  $func_args = wp_parse_args( array(
200
  'include' => $term_ids,
@@ -208,266 +122,140 @@ if ( ! class_exists( 'RWMB_Helper' ) )
208
  $meta = array();
209
  }
210
  }
211
-
212
  // Get post terms
213
  elseif ( 'taxonomy' == $args['type'] )
214
  {
215
  $meta = empty( $args['taxonomy'] ) ? array() : wp_get_post_terms( $post_id, $args['taxonomy'] );
216
  }
217
-
218
  // Get map
219
  elseif ( 'map' == $args['type'] )
220
  {
221
- $meta = self::map( $key, $args, $post_id );
 
 
 
 
 
222
  }
223
-
224
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
225
  }
 
 
226
 
227
- /**
228
- * Get uploaded file information
229
- *
230
- * @param int $id Attachment file ID (post ID). Required.
231
- *
232
- * @return array|bool False if file not found. Array of (id, name, path, url) on success
233
- */
234
- static function file_info( $id )
235
- {
236
- $path = get_attached_file( $id );
 
 
 
 
 
 
237
 
238
- return array(
239
- 'ID' => $id,
240
- 'name' => basename( $path ),
241
- 'path' => $path,
242
- 'url' => wp_get_attachment_url( $id ),
243
- 'title' => get_the_title( $id ),
244
- );
245
- }
 
 
 
 
 
 
 
 
 
 
246
 
247
  /**
248
- * Get uploaded image information
249
- *
250
- * @param int $id Attachment image ID (post ID). Required.
251
- * @param array $args Array of arguments (for size). Required.
252
  *
253
- * @return array|bool False if file not found. Array of (id, name, path, url) on success
 
 
 
254
  */
255
- static function image_info( $id, $args = array() )
256
- {
257
- $args = wp_parse_args( $args, array(
258
- 'size' => 'thumbnail',
259
- ) );
260
 
261
- $img_src = wp_get_attachment_image_src( $id, $args['size'] );
262
- if ( empty( $img_src ) )
263
- return false;
264
 
265
- $attachment = get_post( $id );
266
- $path = get_attached_file( $id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
- return array(
269
- 'ID' => $id,
270
- 'name' => basename( $path ),
271
- 'path' => $path,
272
- 'url' => $img_src[0],
273
- 'width' => $img_src[1],
274
- 'height' => $img_src[2],
275
- 'full_url' => wp_get_attachment_url( $id ),
276
- 'title' => $attachment->post_title,
277
- 'caption' => $attachment->post_excerpt,
278
- 'description' => $attachment->post_content,
279
- 'alt' => get_post_meta( $id, '_wp_attachment_image_alt', true ),
280
- );
281
- }
282
 
283
  /**
284
- * Display map using Google API
285
- *
286
- * @param string $key Meta key
287
- * @param array $args Map parameter
288
- * @param int|null $post_id Post ID
289
  *
290
- * @return string
 
 
 
291
  */
292
- static function map( $key, $args = array(), $post_id = null )
293
- {
294
- $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
295
- $loc = get_post_meta( $post_id, $key, true );
296
- if ( ! $loc )
297
- return '';
298
-
299
- $parts = array_map( 'trim', explode( ',', $loc ) );
300
-
301
- // No zoom entered, set it to 14 by default
302
- if ( count( $parts ) < 3 )
303
- $parts[2] = 14;
304
-
305
- // Map parameters
306
- $args = wp_parse_args( $args, array(
307
- 'width' => '640px',
308
- 'height' => '480px',
309
- 'marker' => true, // Display marker?
310
- 'marker_title' => '', // Marker title, when hover
311
- 'info_window' => '', // Content of info window (when click on marker). HTML allowed
312
- 'js_options' => array(),
313
- ) );
314
- $args['js_options'] = wp_parse_args( $args['js_options'], array(
315
- 'zoom' => $parts[2], // Default to 'zoom' level set in admin, but can be overwritten
316
- 'mapTypeId' => 'ROADMAP', // Map type, see https://developers.google.com/maps/documentation/javascript/reference#MapTypeId
317
- ) );
318
-
319
- // Counter to display multiple maps on same page
320
- static $counter = 0;
321
-
322
- $html = sprintf(
323
- '<div id="rwmb-map-canvas-%d" style="width:%s;height:%s"></div>',
324
- $counter,
325
- $args['width'],
326
- $args['height']
327
- );
328
-
329
- // Load Google Maps script only when needed
330
- $html .= '<script>if ( typeof google !== "object" || typeof google.maps !== "object" )
331
- document.write(\'<script src="//maps.google.com/maps/api/js?sensor=false"><\/script>\')</script>';
332
- $html .= '<script>
333
- ( function()
334
- {
335
- ';
336
-
337
- $html .= sprintf( '
338
- var center = new google.maps.LatLng( %s, %s ),
339
- mapOptions = %s,
340
- map;
341
-
342
- switch ( mapOptions.mapTypeId )
343
- {
344
- case "ROADMAP":
345
- mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
346
- break;
347
- case "SATELLITE":
348
- mapOptions.mapTypeId = google.maps.MapTypeId.SATELLITE;
349
- break;
350
- case "HYBRID":
351
- mapOptions.mapTypeId = google.maps.MapTypeId.HYBRID;
352
- break;
353
- case "TERRAIN":
354
- mapOptions.mapTypeId = google.maps.MapTypeId.TERRAIN;
355
- break;
356
- }
357
- mapOptions.center = center;
358
- map = new google.maps.Map( document.getElementById( "rwmb-map-canvas-%d" ), mapOptions );
359
- ',
360
- $parts[0], $parts[1],
361
- json_encode( $args['js_options'] ),
362
- $counter
363
- );
364
-
365
- if ( $args['marker'] )
366
- {
367
- $html .= sprintf( '
368
- var marker = new google.maps.Marker( {
369
- position: center,
370
- map: map%s
371
- } );',
372
- $args['marker_title'] ? ', title: "' . $args['marker_title'] . '"' : ''
373
- );
374
 
375
- if ( $args['info_window'] )
376
- {
377
- $html .= sprintf( '
378
- var infoWindow = new google.maps.InfoWindow( {
379
- content: "%s"
380
- } );
381
 
382
- google.maps.event.addListener( marker, "click", function()
383
- {
384
- infoWindow.open( map, marker );
385
- } );',
386
- $args['info_window']
387
- );
388
- }
389
- }
390
-
391
- $html .= '} )();
392
- </script>';
393
-
394
- $counter ++;
395
-
396
- return $html;
397
- }
398
  }
399
-
400
- RWMB_Helper::on_load();
401
  }
402
 
403
- /**
404
- * Get post meta
405
- *
406
- * @param string $key Meta key. Required.
407
- * @param int|null $post_id Post ID. null for current post. Optional
408
- * @param array $args Array of arguments. Optional.
409
- *
410
- * @return mixed
411
- */
412
- function rwmb_meta( $key, $args = array(), $post_id = null )
413
- {
414
- return RWMB_Helper::meta( $key, $args, $post_id );
415
- }
416
-
417
- /**
418
- * Get value of custom field.
419
- * This is used to replace old version of rwmb_meta key. rwmb_meta will be used internally only.
420
- *
421
- * @uses rwmb_meta()
422
- * @param string $key Meta key. Required.
423
- * @param int|null $post_id Post ID. null for current post. Optional.
424
- * @return mixed false if field doesn't exist. Field value otherwise.
425
- */
426
- function rwmb_get_field( $key, $post_id = null )
427
  {
428
  /**
429
- * Search all the registered meta box to find needed field
430
- * The field will have all needed parameters which we can pass to rwmb_meta function without
431
- * having users to manually set them (field type, multiple, ect.). So users only need to remember
432
- * field ID only.
 
 
 
433
  */
434
- $found = false;
435
- $meta_boxes = apply_filters( 'rwmb_meta_boxes', array() );
436
- foreach ( $meta_boxes as $meta_box )
437
  {
438
- foreach ( $meta_box['fields'] as $field )
439
- {
440
- if ( $key == $field['id'] )
441
- {
442
- $found = true;
443
- break;
444
- }
445
- }
446
- }
447
 
448
- // If field doesn't exist, return false
449
- if ( ! $found )
450
- {
451
- return false;
452
- }
453
 
454
- // Normalize field to make sure all params are set properly
455
- $field = wp_parse_args( $field, array(
456
- 'id' => '',
457
- 'multiple' => false,
458
- 'clone' => false,
459
- 'std' => '',
460
- 'desc' => '',
461
- 'format' => '',
462
- 'before' => '',
463
- 'after' => '',
464
- 'field_name' => isset( $field['id'] ) ? $field['id'] : '',
465
- 'required' => false,
466
- 'placeholder' => '',
467
- ) );
468
- $field = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'normalize_field' ), $field );
469
 
470
- // Get field value
471
- return RWMB_Helper::meta( $key, $field, $post_id );
472
  }
473
-
15
  class RWMB_Helper
16
  {
17
  /**
18
+ * Find field by field ID
19
+ * This function finds field in meta boxes registered by 'rwmb_meta_boxes' filter
20
+ * Note: if users use old code to add meta boxes, this function might not work properly
21
  *
22
+ * @param string $field_id Field ID
 
 
 
 
 
 
 
 
 
 
23
  *
24
+ * @return array|false Field params (array) if success. False otherwise.
 
 
25
  */
26
+ static function find_field( $field_id )
27
  {
28
+ // Get all meta boxes registered with 'rwmb_meta_boxes' hook
29
+ $meta_boxes = apply_filters( 'rwmb_meta_boxes', array() );
 
 
 
 
30
 
31
+ // Find field
32
+ foreach ( $meta_boxes as $meta_box )
 
 
33
  {
34
+ $meta_box = RW_Meta_Box::normalize( $meta_box );
35
+ foreach ( $meta_box['fields'] as $field )
36
  {
37
+ if ( $field_id == $field['id'] )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  {
39
+ return $field;
 
 
 
 
 
40
  }
41
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
 
44
+ return false;
45
  }
46
 
47
  /**
56
  static function meta( $key, $args = array(), $post_id = null )
57
  {
58
  $post_id = empty( $post_id ) ? get_the_ID() : $post_id;
59
+ $args = wp_parse_args( $args, array(
60
+ 'type' => 'text',
61
+ 'multiple' => false,
62
  ) );
63
 
64
+ // Always set 'multiple' true for following field types
65
+ if ( in_array( $args['type'], array( 'checkbox_list', 'file', 'file_advanced', 'image', 'image_advanced', 'plupload_image', 'thickbox_image' ) ) )
66
+ {
67
+ $args['multiple'] = true;
68
+ }
69
 
70
  $meta = get_post_meta( $post_id, $key, ! $args['multiple'] );
71
 
80
  // Get only info of existing attachments
81
  if ( get_attached_file( $id ) )
82
  {
83
+ $files[$id] = RWMB_File_Field::file_info( $id );
84
  }
85
  }
86
  $meta = $files;
87
  }
88
  }
 
89
  // Get uploaded images info
90
  elseif ( in_array( $args['type'], array( 'image', 'plupload_image', 'thickbox_image', 'image_advanced' ) ) )
91
  {
 
 
 
 
 
 
 
 
92
  if ( is_array( $meta ) && ! empty( $meta ) )
93
  {
94
  $images = array();
97
  // Get only info of existing attachments
98
  if ( get_attached_file( $id ) )
99
  {
100
+ $images[$id] = RWMB_Image_Field::file_info( $id, $args );
101
  }
102
  }
103
  $meta = $images;
104
  }
105
  }
 
106
  // Get terms
107
  elseif ( 'taxonomy_advanced' == $args['type'] )
108
  {
109
  if ( ! empty( $args['taxonomy'] ) )
110
  {
111
  $term_ids = array_map( 'intval', array_filter( explode( ',', $meta . ',' ) ) );
 
112
  // Allow to pass more arguments to "get_terms"
113
  $func_args = wp_parse_args( array(
114
  'include' => $term_ids,
122
  $meta = array();
123
  }
124
  }
 
125
  // Get post terms
126
  elseif ( 'taxonomy' == $args['type'] )
127
  {
128
  $meta = empty( $args['taxonomy'] ) ? array() : wp_get_post_terms( $post_id, $args['taxonomy'] );
129
  }
 
130
  // Get map
131
  elseif ( 'map' == $args['type'] )
132
  {
133
+ $field = array(
134
+ 'id' => $key,
135
+ 'multiple' => false,
136
+ 'clone' => false,
137
+ );
138
+ $meta = RWMB_Map_Field::the_value( $field, $args, $post_id );
139
  }
 
140
  return apply_filters( 'rwmb_meta', $meta, $key, $args, $post_id );
141
  }
142
+ }
143
+ }
144
 
145
+ if ( ! function_exists( 'rwmb_meta' ) )
146
+ {
147
+ /**
148
+ * Get post meta
149
+ *
150
+ * @param string $key Meta key. Required.
151
+ * @param int|null $post_id Post ID. null for current post. Optional
152
+ * @param array $args Array of arguments. Optional.
153
+ *
154
+ * @return mixed
155
+ */
156
+ function rwmb_meta( $key, $args = array(), $post_id = null )
157
+ {
158
+ return RWMB_Helper::meta( $key, $args, $post_id );
159
+ }
160
+ }
161
 
162
+ if ( ! function_exists( 'rwmb_get_field' ) )
163
+ {
164
+ /**
165
+ * Get value of custom field.
166
+ * This is used to replace old version of rwmb_meta key.
167
+ *
168
+ * @param string $field_id Field ID. Required.
169
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
170
+ * @param int|null $post_id Post ID. null for current post. Optional.
171
+ *
172
+ * @return mixed false if field doesn't exist. Field value otherwise.
173
+ */
174
+ function rwmb_get_field( $field_id, $args = array(), $post_id = null )
175
+ {
176
+ $field = RWMB_Helper::find_field( $field_id );
177
+
178
+ // Get field value
179
+ $value = $field ? call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'get_value' ), $field, $args, $post_id ) : false;
180
 
181
  /**
182
+ * Allow developers to change the returned value of field
 
 
 
183
  *
184
+ * @param mixed $value Field value
185
+ * @param array $field Field parameter
186
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
187
+ * @param int|null $post_id Post ID. null for current post. Optional.
188
  */
189
+ $value = apply_filters( 'rwmb_get_field', $value, $field, $args, $post_id );
 
 
 
 
190
 
191
+ return $value;
192
+ }
193
+ }
194
 
195
+ if ( ! function_exists( 'rwmb_the_field' ) )
196
+ {
197
+ /**
198
+ * Display the value of a field
199
+ *
200
+ * @param string $field_id Field ID. Required.
201
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
202
+ * @param int|null $post_id Post ID. null for current post. Optional.
203
+ * @param bool $echo Display field meta value? Default `true` which works in almost all cases. We use `false` for the [rwmb_meta] shortcode
204
+ *
205
+ * @return string
206
+ */
207
+ function rwmb_the_field( $field_id, $args = array(), $post_id = null, $echo = true )
208
+ {
209
+ // Find field
210
+ $field = RWMB_Helper::find_field( $field_id );
211
 
212
+ if ( ! $field )
213
+ return '';
214
+
215
+ $output = call_user_func( array( RW_Meta_Box::get_class_name( $field ), 'the_value' ), $field, $args, $post_id );
 
 
 
 
 
 
 
 
 
 
216
 
217
  /**
218
+ * Allow developers to change the returned value of field
 
 
 
 
219
  *
220
+ * @param mixed $value Field HTML output
221
+ * @param array $field Field parameter
222
+ * @param array $args Additional arguments. Rarely used. See specific fields for details
223
+ * @param int|null $post_id Post ID. null for current post. Optional.
224
  */
225
+ $output = apply_filters( 'rwmb_the_field', $output, $field, $args, $post_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
+ if ( $echo )
228
+ echo $output;
 
 
 
 
229
 
230
+ return $output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  }
 
 
232
  }
233
 
234
+ if ( ! function_exists( 'rwmb_meta_shortcode' ) )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  {
236
  /**
237
+ * Shortcode to display meta value
238
+ *
239
+ * @param $atts Array of shortcode attributes, same as meta() function, but has more "meta_key" parameter
240
+ *
241
+ * @see meta() function below
242
+ *
243
+ * @return string
244
  */
245
+ function rwmb_meta_shortcode( $atts )
 
 
246
  {
247
+ $atts = wp_parse_args( $atts, array(
248
+ 'post_id' => get_the_ID(),
249
+ ) );
250
+ if ( empty( $atts['meta_key'] ) )
251
+ return '';
 
 
 
 
252
 
253
+ $field_id = $atts['meta_key'];
254
+ $post_id = $atts['post_id'];
255
+ unset( $atts['meta_key'], $atts['post_id'] );
 
 
256
 
257
+ return rwmb_the_field( $field_id, $atts, $post_id, false );
258
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
+ add_shortcode( 'rwmb_meta', 'rwmb_meta_shortcode' );
 
261
  }
 
inc/meta-box.php CHANGED
@@ -302,9 +302,10 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
302
 
303
  foreach ( $this->fields as $field )
304
  {
305
- $name = $field['id'];
306
- $old = get_post_meta( $post_id, $name, ! $field['multiple'] );
307
- $new = isset( $_POST[$name] ) ? $_POST[$name] : ( $field['multiple'] ? array() : '' );
 
308
 
309
  // Allow field class change the value
310
  $new = call_user_func( array( self::get_class_name( $field ), 'value' ), $new, $old, $post_id, $field );
@@ -382,7 +383,7 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
382
  */
383
  static function normalize_fields( $fields )
384
  {
385
- foreach ( $fields as &$field )
386
  {
387
  $field = wp_parse_args( $field, array(
388
  'id' => '',
@@ -398,8 +399,17 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
398
  'placeholder' => '',
399
  ) );
400
 
 
 
 
 
 
 
 
 
 
401
  // Allow field class add/change default field values
402
- $field = call_user_func( array( self::get_class_name( $field ), 'normalize_field' ), $field );
403
 
404
  if ( isset( $field['fields'] ) )
405
  $field['fields'] = self::normalize_fields( $field['fields'] );
@@ -408,6 +418,8 @@ if ( ! class_exists( 'RW_Meta_Box' ) )
408
  $field = apply_filters( 'rwmb_normalize_field', $field );
409
  $field = apply_filters( "rwmb_normalize_{$field['type']}_field", $field );
410
  $field = apply_filters( "rwmb_normalize_{$field['id']}_field", $field );
 
 
411
  }
412
 
413
  return $fields;
302
 
303
  foreach ( $this->fields as $field )
304
  {
305
+ $name = $field['id'];
306
+ $single = $field['clone'] || ! $field['multiple'];
307
+ $old = get_post_meta( $post_id, $name, $single );
308
+ $new = isset( $_POST[$name] ) ? $_POST[$name] : ( $single ? '' : array() );
309
 
310
  // Allow field class change the value
311
  $new = call_user_func( array( self::get_class_name( $field ), 'value' ), $new, $old, $post_id, $field );
383
  */
384
  static function normalize_fields( $fields )
385
  {
386
+ foreach ( $fields as $k => $field )
387
  {
388
  $field = wp_parse_args( $field, array(
389
  'id' => '',
399
  'placeholder' => '',
400
  ) );
401
 
402
+ $class = self::get_class_name( $field );
403
+
404
+ // Make sure field has correct 'type', ignore warning error when users forget to set field type or set incorrect one
405
+ if ( false === $class )
406
+ {
407
+ unset( $fields[$k] );
408
+ continue;
409
+ }
410
+
411
  // Allow field class add/change default field values
412
+ $field = call_user_func( array( $class, 'normalize_field' ), $field );
413
 
414
  if ( isset( $field['fields'] ) )
415
  $field['fields'] = self::normalize_fields( $field['fields'] );
418
  $field = apply_filters( 'rwmb_normalize_field', $field );
419
  $field = apply_filters( "rwmb_normalize_{$field['type']}_field", $field );
420
  $field = apply_filters( "rwmb_normalize_{$field['id']}_field", $field );
421
+
422
+ $fields[$k] = $field;
423
  }
424
 
425
  return $fields;
js/autocomplete.js CHANGED
@@ -36,7 +36,7 @@ jQuery( function ( $ )
36
  {
37
  $result.append(
38
  '<div class="rwmb-autocomplete-result">' +
39
- '<div class="label">' + ui.item.label + '</div>' +
40
  '<div class="actions">' + RWMB_Autocomplete.delete + '</div>' +
41
  '<input type="hidden" class="rwmb-autocomplete-value" name="' + name + '" value="' + ui.item.value + '">' +
42
  '</div>'
36
  {
37
  $result.append(
38
  '<div class="rwmb-autocomplete-result">' +
39
+ '<div class="label">' + ( typeof ui.item.excerpt !== 'undefined' ? ui.item.excerpt : ui.item.label ) + '</div>' +
40
  '<div class="actions">' + RWMB_Autocomplete.delete + '</div>' +
41
  '<input type="hidden" class="rwmb-autocomplete-value" name="' + name + '" value="' + ui.item.value + '">' +
42
  '</div>'
js/clone.js CHANGED
@@ -9,7 +9,7 @@ jQuery( function ( $ )
9
  */
10
  function clone( $container )
11
  {
12
- var $clone_last = $container.find( '.rwmb-clone:last' ),
13
  $clone = $clone_last.clone(),
14
  $input;
15
 
@@ -216,13 +216,13 @@ jQuery( function ( $ )
216
 
217
 
218
  // Add more clones
219
- $( '.add-clone' ).on( 'click', function ( e )
220
  {
221
  e.preventDefault();
222
 
223
- var $input = $( this ).parents( '.rwmb-input' );
224
 
225
- if ( $( this ).parents( '.rwmb-field' ).hasClass( 'rwmb-wysiwyg-wrapper' ) )
226
  {
227
  cloneWYSIWYG( $input );
228
  }
@@ -240,7 +240,7 @@ jQuery( function ( $ )
240
  e.preventDefault();
241
 
242
  var $this = $( this ),
243
- $input = $this.parents( '.rwmb-input' );
244
 
245
  // Remove clone only if there're 2 or more of them
246
  if ( $input.find( '.rwmb-clone' ).length <= 1 )
9
  */
10
  function clone( $container )
11
  {
12
+ var $clone_last = $container.children( '.rwmb-clone:last' ),
13
  $clone = $clone_last.clone(),
14
  $input;
15
 
216
 
217
 
218
  // Add more clones
219
+ $( '#poststuff' ).on( 'click', '.add-clone', function ( e )
220
  {
221
  e.preventDefault();
222
 
223
+ var $input = $( this ).closest( '.rwmb-input' );
224
 
225
+ if ( $( this ).closest( '.rwmb-field' ).hasClass( 'rwmb-wysiwyg-wrapper' ) )
226
  {
227
  cloneWYSIWYG( $input );
228
  }
240
  e.preventDefault();
241
 
242
  var $this = $( this ),
243
+ $input = $this.closest( '.rwmb-input' );
244
 
245
  // Remove clone only if there're 2 or more of them
246
  if ( $input.find( '.rwmb-clone' ).length <= 1 )
js/map-frontend.js ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global google, jQuery */
2
+
3
+ jQuery( function ( $ )
4
+ {
5
+ 'use strict';
6
+
7
+ /**
8
+ * Callback function for Google Maps Lazy Load library to display map
9
+ *
10
+ * @return void
11
+ */
12
+ function displayMap()
13
+ {
14
+ var $container = $( this ),
15
+ options = $container.data( 'map_options' );
16
+
17
+ var mapOptions = options.js_options,
18
+ center = new google.maps.LatLng( options.latitude, options.longitude ),
19
+ map;
20
+
21
+ switch ( mapOptions.mapTypeId )
22
+ {
23
+ case 'ROADMAP':
24
+ mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
25
+ break;
26
+ case 'SATELLITE':
27
+ mapOptions.mapTypeId = google.maps.MapTypeId.SATELLITE;
28
+ break;
29
+ case 'HYBRID':
30
+ mapOptions.mapTypeId = google.maps.MapTypeId.HYBRID;
31
+ break;
32
+ case 'TERRAIN':
33
+ mapOptions.mapTypeId = google.maps.MapTypeId.TERRAIN;
34
+ break;
35
+ }
36
+ mapOptions.center = center;
37
+ map = new google.maps.Map( this, mapOptions );
38
+
39
+ // Set marker
40
+ if ( options.marker )
41
+ {
42
+ var marker = new google.maps.Marker( {
43
+ position: center,
44
+ map : map
45
+ } );
46
+
47
+ // Set marker title
48
+ if ( options.marker_title )
49
+ {
50
+ marker.setTitle( mapOptions.marker_title );
51
+ }
52
+ }
53
+
54
+ // Set info window
55
+ if ( options.info_window )
56
+ {
57
+ var infoWindow = new google.maps.InfoWindow( {
58
+ content : options.info_window,
59
+ minWidth: 200
60
+ } );
61
+
62
+ google.maps.event.addListener( marker, 'click', function ()
63
+ {
64
+ infoWindow.open( map, marker );
65
+ } );
66
+ }
67
+ }
68
+
69
+ // Loop through all map instances and display them
70
+ $( '.rwmb-map-canvas' ).each( displayMap );
71
+ } );
js/map.js CHANGED
@@ -91,6 +91,21 @@
91
  that.geocodeAddress();
92
  return false;
93
  } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  },
95
 
96
  // Autocomplete address
@@ -180,6 +195,7 @@
180
  field.init();
181
 
182
  $( this ).data( 'mapController', field );
 
183
  } );
184
 
185
  $( '.rwmb-input' ).on( 'clone', function ()
91
  that.geocodeAddress();
92
  return false;
93
  } );
94
+
95
+ /**
96
+ * Add a custom event that allows other scripts to refresh the maps when needed
97
+ * For example: when maps is in tabs or hidden div (this is known issue of Google Maps)
98
+ *
99
+ * @see https://developers.google.com/maps/documentation/javascript/reference
100
+ * ('resize' Event)
101
+ */
102
+ $( window ).on( 'rwmb_map_refresh', function()
103
+ {
104
+ if ( that.map )
105
+ {
106
+ google.maps.event.trigger( that.map, 'resize' );
107
+ }
108
+ } );
109
  },
110
 
111
  // Autocomplete address
195
  field.init();
196
 
197
  $( this ).data( 'mapController', field );
198
+
199
  } );
200
 
201
  $( '.rwmb-input' ).on( 'clone', function ()
lang/es.mo DELETED
Binary file
lang/es_ES.mo ADDED
Binary file
lang/fa_IR.mo ADDED
Binary file
meta-box.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Meta Box
4
  Plugin URI: http://metabox.io
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
- Version: 4.4.3
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
@@ -13,7 +13,7 @@ License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
- define( 'RWMB_VER', '4.4.2' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
@@ -30,6 +30,7 @@ define( 'RWMB_FIELDS_DIR', trailingslashit( RWMB_INC_DIR . 'fields' ) );
30
 
31
  require_once RWMB_INC_DIR . 'common.php';
32
  require_once RWMB_INC_DIR . 'field.php';
 
33
 
34
  // Field classes
35
  foreach ( glob( RWMB_FIELDS_DIR . '*.php' ) as $file )
3
  Plugin Name: Meta Box
4
  Plugin URI: http://metabox.io
5
  Description: Create meta box for editing pages in WordPress. Compatible with custom post types since WP 3.0
6
+ Version: 4.5.3
7
  Author: Rilwis
8
  Author URI: http://www.deluxeblogtips.com
9
  License: GPL2+
13
  defined( 'ABSPATH' ) || exit;
14
 
15
  // Script version, used to add version for scripts and styles
16
+ define( 'RWMB_VER', '4.5.3' );
17
 
18
  // Define plugin URLs, for fast enqueuing scripts and styles
19
  if ( ! defined( 'RWMB_URL' ) )
30
 
31
  require_once RWMB_INC_DIR . 'common.php';
32
  require_once RWMB_INC_DIR . 'field.php';
33
+ require_once RWMB_INC_DIR . 'field-multiple-values.php';
34
 
35
  // Field classes
36
  foreach ( glob( RWMB_FIELDS_DIR . '*.php' ) as $file )
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Meta Box ===
2
- Contributors: rilwis, franz-josef-kaiser, Omnicia, funkedgeek, PerWiklander, ruanmer
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
- Tested up to: 4.1
7
- Stable tag: 4.4.2
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
@@ -60,10 +60,41 @@ To getting started with the plugin API, please read [this tutorial](http://metab
60
  == Frequently Asked Questions ==
61
 
62
  == Screenshots ==
63
- 1. Supported fields
 
 
 
 
 
64
 
65
  == Changelog ==
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  = 4.4.3 =
68
  * Fix: Incorrect path to loader image for `plupload_image`
69
  * Fix: Missing placeholder for `post` field when `field_type` = `select`
@@ -71,7 +102,6 @@ To getting started with the plugin API, please read [this tutorial](http://metab
71
  * Improvement: Add filter for add/remove clone buttons text
72
  * Improvement: Add French translation
73
 
74
-
75
  = 4.4.2 =
76
  * Fix: Values of text_list field not showing correctly
77
  * Fix: Time picker field cannot select hour > 22, time > 58
1
  === Meta Box ===
2
+ Contributors: rilwis, fitwp, f-j-kaiser, Omnicia, funkedgeek, PerWiklander, ruanmer
3
  Donate link: http://www.deluxeblogtips.com/donate
4
  Tags: meta-box, custom-fields, custom-field, meta, meta-boxes
5
  Requires at least: 3.5
6
+ Tested up to: 4.2.2
7
+ Stable tag: 4.5.3
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a complete tool to create meta box and custom fields in WordPress: lightweight, powerful and easy-to-use.
60
  == Frequently Asked Questions ==
61
 
62
  == Screenshots ==
63
+ 1. Text Fields
64
+ 1. Basic Fields
65
+ 1. Advanced Fields
66
+ 1. File Image Upload Fields
67
+ 1. Media Fields
68
+ 1. Post Taxonomy Fields
69
 
70
  == Changelog ==
71
 
72
+ = 4.5.3 =
73
+ * Improvement: Use `wp_json_encode` instead of `json_encode`. Thank Sam Ford.
74
+ * Fix: Escape value for cloneable fields
75
+ * Fix: Notice for missing parameters for `rwmb_meta` field for `map`
76
+
77
+
78
+ = 4.5.2 =
79
+ * Improvement: Add Persian (Farsi) language. Thank Ahmad Azimi.
80
+ * Improvement: Update Spanish translation. Thank David Perez.
81
+ * Fix: Cloning text fields
82
+ * Fix: rwmb_meta works incorrectly for image fields if multiple=false
83
+
84
+ = 4.5.1 =
85
+ * Improvement: Add ability to use multiple post types for `post` field
86
+ * Fix: Duplicated description for `checkbox` field
87
+ * Fix: Blank gallery for image fields
88
+
89
+ = 4.5 =
90
+ * Improvement: Separate `esc_meta` method
91
+ * Improvement: Add ability to use URL to retrieve options for autocomplete field
92
+ * Improvement: Add `rwmb_get_field` and `rwmb_the_field` functions to get and display field values in the frontend
93
+ * Improvement: Add field type `custom_html` to display any HTML in the meta box
94
+ * Improvement: Add field type `key_value` which allows users to add any number of key-value pairs
95
+ * Improvement: Use single JS file to display Google Maps in the frontend. No more inline Javascript.
96
+ * Improvement: Code refactor
97
+
98
  = 4.4.3 =
99
  * Fix: Incorrect path to loader image for `plupload_image`
100
  * Fix: Missing placeholder for `post` field when `field_type` = `select`
102
  * Improvement: Add filter for add/remove clone buttons text
103
  * Improvement: Add French translation
104
 
 
105
  = 4.4.2 =
106
  * Fix: Values of text_list field not showing correctly
107
  * Fix: Time picker field cannot select hour > 22, time > 58