Meta Box - Version 5.6.9

Version Description

  • 2022-12-05 =
  • Improve accessibility for form controls, especially when using on the front end
  • Use all admin themes for switch and button group
  • Add filter 'rwmb_validation_message_string' for validation message
  • Display field label description even if no label
  • Fix not displaying the language according to user preference
  • Fix not setting post parent for the uploaded images on the front end for image_upload fields
  • Fix warning when using file_info helper function
  • Modernize code for PHP 7
Download this release

Release Info

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

Code changes from version 5.6.8 to 5.6.9

css/button-group.css CHANGED
@@ -70,3 +70,85 @@
70
  border-top-right-radius: 3px;
71
  border-bottom-right-radius: 3px;
72
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  border-top-right-radius: 3px;
71
  border-bottom-right-radius: 3px;
72
  }
73
+
74
+ /* Admin color schemes */
75
+ .admin-color-blue .rwmb-button-input-list li label.selected {
76
+ border-color: #e1a948;
77
+ background: #e1a948;
78
+ }
79
+ .admin-color-blue .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
80
+ border-bottom-color: #e1a948
81
+ }
82
+ .admin-color-blue .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
83
+ border-right-color: #e1a948
84
+ }
85
+ .admin-color-coffee .rwmb-button-input-list li label.selected {
86
+ border-color: #c7a589;
87
+ background: #c7a589;
88
+ }
89
+ .admin-color-coffee .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
90
+ border-bottom-color: #c7a589;
91
+ }
92
+ .admin-color-coffee .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
93
+ border-right-color: #c7a589;
94
+ }
95
+ .admin-color-ectoplasm .rwmb-button-input-list li label.selected {
96
+ border-color: #a3b745;
97
+ background: #a3b745;
98
+ }
99
+ .admin-color-ectoplasm .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
100
+ border-bottom-color: #a3b745;
101
+ }
102
+ .admin-color-ectoplasm .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
103
+ border-right-color: #a3b745;
104
+ }
105
+ .admin-color-light .rwmb-button-input-list li label.selected {
106
+ border-color: #04a4cc;
107
+ background: #04a4cc;
108
+ }
109
+ .admin-color-light .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
110
+ border-bottom-color: #04a4cc
111
+ }
112
+ .admin-color-light .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
113
+ border-right-color: #04a4cc
114
+ }
115
+ .admin-color-midnight .rwmb-button-input-list li label.selected {
116
+ border-color: #e14d43;
117
+ background: #e14d43;
118
+ }
119
+ .admin-color-midnight .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
120
+ border-bottom-color: #e14d43
121
+ }
122
+ .admin-color-midnight .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
123
+ border-right-color: #e14d43
124
+ }
125
+ .admin-color-modern .rwmb-button-input-list li label.selected {
126
+ border-color: #3858e9;
127
+ background: #3858e9;
128
+ }
129
+ .admin-color-modern .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
130
+ border-bottom-color: #3858e9
131
+ }
132
+ .admin-color-modern .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
133
+ border-right-color: #3858e9
134
+ }
135
+ .admin-color-ocean .rwmb-button-input-list li label.selected {
136
+ border-color: #9ebaa0;
137
+ background: #9ebaa0;
138
+ }
139
+ .admin-color-ocean .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
140
+ border-bottom-color: #9ebaa0
141
+ }
142
+ .admin-color-ocean .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
143
+ border-right-color: #9ebaa0
144
+ }
145
+ .admin-color-sunrise .rwmb-button-input-list li label.selected {
146
+ border-color: #dd823b;
147
+ background: #dd823b;
148
+ }
149
+ .admin-color-sunrise .rwmb-button-input-list:not(.rwmb-inline) li:last-child label.selected {
150
+ border-bottom-color: #dd823b
151
+ }
152
+ .admin-color-sunrise .rwmb-button-input-list.rwmb-inline li:last-child label.selected {
153
+ border-right-color: #dd823b
154
+ }
css/input-list.css CHANGED
@@ -2,22 +2,17 @@
2
  margin-top: 0;
3
  }
4
  .rwmb-input-list {
5
- margin: 0;
6
  line-height: 1.8;
7
  }
8
  .rwmb-input-list .rwmb-input-list {
9
  margin-left: 20px;
10
  }
11
- .rwmb-input-list li {
12
- list-style: none;
13
- margin-bottom: 0;
14
  }
15
  .rwmb-input-list.rwmb-inline {
16
  line-height: inherit;
17
- }
18
- .rwmb-input-list.rwmb-inline li {
19
- display: inline-block;
20
- }
21
- .rwmb-input-list.rwmb-inline li:not(:last-child) {
22
- margin-right: 20px;
23
  }
2
  margin-top: 0;
3
  }
4
  .rwmb-input-list {
 
5
  line-height: 1.8;
6
  }
7
  .rwmb-input-list .rwmb-input-list {
8
  margin-left: 20px;
9
  }
10
+ .rwmb-input-list > label {
11
+ display: block;
 
12
  }
13
  .rwmb-input-list.rwmb-inline {
14
  line-height: inherit;
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ gap: 20px;
 
 
 
18
  }
css/switch.css CHANGED
@@ -106,10 +106,18 @@
106
  background-color: #a3b745;
107
  box-shadow: 0 0 1px #a3b745;
108
  }
 
 
 
 
109
  .admin-color-midnight .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
110
  background-color: #e14d43;
111
  box-shadow: 0 0 1px #e14d43;
112
  }
 
 
 
 
113
  .admin-color-ocean .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
114
  background-color: #9ebaa0;
115
  box-shadow: 0 0 1px #9ebaa0;
@@ -117,4 +125,4 @@
117
  .admin-color-sunrise .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
118
  background-color: #dd823b;
119
  box-shadow: 0 0 1px #dd823b;
120
- }
106
  background-color: #a3b745;
107
  box-shadow: 0 0 1px #a3b745;
108
  }
109
+ .admin-color-light .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
110
+ background-color: #04a4cc;
111
+ box-shadow: 0 0 1px #04a4cc;
112
+ }
113
  .admin-color-midnight .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
114
  background-color: #e14d43;
115
  box-shadow: 0 0 1px #e14d43;
116
  }
117
+ .admin-color-modern .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
118
+ background-color: #3858e9;
119
+ box-shadow: 0 0 1px #3858e9;
120
+ }
121
  .admin-color-ocean .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
122
  background-color: #9ebaa0;
123
  box-shadow: 0 0 1px #9ebaa0;
125
  .admin-color-sunrise .rwmb-switch:checked + .rwmb-switch-status .rwmb-switch-slider {
126
  background-color: #dd823b;
127
  box-shadow: 0 0 1px #dd823b;
128
+ }
inc/about/sections/extensions.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Extensions section.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <div id="extensions" class="gt-tab-pane">
10
  <p class="about-description">
11
  <?php esc_html_e( 'Extend custom fields in WordPress well beyond what others would ever consider ordinary!', 'meta-box' ); ?><br>
 
 
 
 
 
 
 
 
1
  <div id="extensions" class="gt-tab-pane">
2
  <p class="about-description">
3
  <?php esc_html_e( 'Extend custom fields in WordPress well beyond what others would ever consider ordinary!', 'meta-box' ); ?><br>
inc/about/sections/getting-started.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Getting started section.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <div id="getting-started" class="gt-tab-pane gt-is-active">
10
  <div class="two">
11
  <div class="col">
 
 
 
 
 
 
 
 
1
  <div id="getting-started" class="gt-tab-pane gt-is-active">
2
  <div class="two">
3
  <div class="col">
inc/about/sections/products.php CHANGED
@@ -1,12 +1,3 @@
1
- <?php
2
- /**
3
- * Newsletter form
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
-
10
  <div class="postbox">
11
  <h3 class="hndle">
12
  <span><?php esc_html_e( 'Our WordPress Products', 'meta-box' ) ?></span>
@@ -14,6 +5,7 @@
14
  <div class="inside">
15
  <p><?php esc_html_e( 'Like this plugin? Check out our other WordPress products:', 'meta-box' ) ?></p>
16
  <p><a href="https://wpslimseo.com?utm_source=WordPress&utm_medium=link&utm_campaign=meta-box" target="_blank" rel="noopenner noreferrer">Slim SEO</a> - <?php esc_html_e( 'Automated & fast SEO plugin for WordPress', 'meta-box' ) ?></p>
17
- <p><a href="https://gretathemes.com/wordpress-themes/estar/?utm_source=WordPress&utm_medium=link&utm_campaign=meta-box" target="_blank" rel="noopenner noreferrer">eStar</a> - <?php esc_html_e( 'A super fast, lightweight and highly customizable WordPress theme', 'meta-box' ) ?></p>
 
18
  </div>
19
  </div>
 
 
 
 
 
 
 
 
 
1
  <div class="postbox">
2
  <h3 class="hndle">
3
  <span><?php esc_html_e( 'Our WordPress Products', 'meta-box' ) ?></span>
5
  <div class="inside">
6
  <p><?php esc_html_e( 'Like this plugin? Check out our other WordPress products:', 'meta-box' ) ?></p>
7
  <p><a href="https://wpslimseo.com?utm_source=WordPress&utm_medium=link&utm_campaign=meta-box" target="_blank" rel="noopenner noreferrer">Slim SEO</a> - <?php esc_html_e( 'Automated & fast SEO plugin for WordPress', 'meta-box' ) ?></p>
8
+ <p><a href="https://wpslimseo.com/slim-seo-schema/?utm_source=WordPress&utm_medium=link&utm_campaign=meta-box" target="_blank" rel="noopenner noreferrer">Slim SEO Schema</a> - <?php esc_html_e( 'The best schema plugin for WordPress', 'meta-box' ) ?></p>
9
+ <p><a href="https://gretathemes.com?utm_source=WordPress&utm_medium=link&utm_campaign=meta-box" target="_blank" rel="noopenner noreferrer">GretaThemes</a> - <?php esc_html_e( 'Simple, elegant and clean WordPress themes', 'meta-box' ) ?></p>
10
  </div>
11
  </div>
inc/about/sections/support.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Support section.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <div id="support" class="gt-tab-pane">
10
  <p class="about-description">
11
  <?php
 
 
 
 
 
 
 
 
1
  <div id="support" class="gt-tab-pane">
2
  <p class="about-description">
3
  <?php
inc/about/sections/tabs.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Tabs navigation.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <h2 class="nav-tab-wrapper">
10
  <a href="#getting-started" class="nav-tab nav-tab-active"><?php esc_html_e( 'Getting Started', 'meta-box' ); ?></a>
11
  <?php do_action( 'rwmb_about_tabs' ); ?>
 
 
 
 
 
 
 
 
1
  <h2 class="nav-tab-wrapper">
2
  <a href="#getting-started" class="nav-tab nav-tab-active"><?php esc_html_e( 'Getting Started', 'meta-box' ); ?></a>
3
  <?php do_action( 'rwmb_about_tabs' ); ?>
inc/about/sections/upgrade.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Upgrade notice
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <div class="upgrade">
10
  <h3><span class="dashicons dashicons-awards"></span> <?php esc_html_e( 'Upgrade to Meta Box PRO', 'meta-box' ); ?></h3>
11
  <p><?php esc_html_e( 'Please upgrade to the PRO plan to unlock more awesome features.', 'meta-box' ); ?></p>
 
 
 
 
 
 
 
 
1
  <div class="upgrade">
2
  <h3><span class="dashicons dashicons-awards"></span> <?php esc_html_e( 'Upgrade to Meta Box PRO', 'meta-box' ); ?></h3>
3
  <p><?php esc_html_e( 'Please upgrade to the PRO plan to unlock more awesome features.', 'meta-box' ); ?></p>
inc/about/sections/welcome.php CHANGED
@@ -1,11 +1,3 @@
1
- <?php
2
- /**
3
- * Welcome section.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- ?>
9
  <h1>
10
  <?php
11
  $plugin_data = get_plugin_data( RWMB_DIR . 'meta-box.php', false, false );
@@ -18,7 +10,7 @@
18
  <a target="_blank" class="wp-badge" href="https://metabox.io/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php echo esc_html( $plugin_data['Name'] ); ?></a>
19
  <p class="about-buttons">
20
  <a target="_blank" class="button" href="https://docs.metabox.io?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Documentation', 'meta-box' ); ?></a>
21
- <a target="_blank" class="button" href="https://metabox.io/support/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Support', 'meta-box' ); ?></a>
22
  <a target="_blank" class="button" href="http://facebook.com/groups/metaboxusers"><?php esc_html_e( 'Facebook Group', 'meta-box' ); ?></a>
23
  <a target="_blank" class="button" href="https://www.youtube.com/c/MetaBoxWP"><?php esc_html_e( 'Youtube Channel', 'meta-box' ); ?></a>
24
  </p>
 
 
 
 
 
 
 
 
1
  <h1>
2
  <?php
3
  $plugin_data = get_plugin_data( RWMB_DIR . 'meta-box.php', false, false );
10
  <a target="_blank" class="wp-badge" href="https://metabox.io/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php echo esc_html( $plugin_data['Name'] ); ?></a>
11
  <p class="about-buttons">
12
  <a target="_blank" class="button" href="https://docs.metabox.io?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Documentation', 'meta-box' ); ?></a>
13
+ <a target="_blank" class="button" href="https://support.metabox.io/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin"><?php esc_html_e( 'Support', 'meta-box' ); ?></a>
14
  <a target="_blank" class="button" href="http://facebook.com/groups/metaboxusers"><?php esc_html_e( 'Facebook Group', 'meta-box' ); ?></a>
15
  <a target="_blank" class="button" href="https://www.youtube.com/c/MetaBoxWP"><?php esc_html_e( 'Youtube Channel', 'meta-box' ); ?></a>
16
  </p>
inc/autoloader.php CHANGED
@@ -1,20 +1,9 @@
1
  <?php
2
  /**
3
  * Autoload plugin classes.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Autoload class
10
  */
11
  class RWMB_Autoloader {
12
- /**
13
- * List of directories to load classes.
14
- *
15
- * @var array
16
- */
17
- protected $dirs = array();
18
 
19
  /**
20
  * Adds a base directory for a class name prefix and/or suffix.
@@ -23,19 +12,19 @@ class RWMB_Autoloader {
23
  * @param string $prefix The class name prefix.
24
  * @param string $suffix The class name suffix.
25
  */
26
- public function add( $dir, $prefix, $suffix = '' ) {
27
- $this->dirs[] = array(
28
  'dir' => trailingslashit( $dir ),
29
  'prefix' => $prefix,
30
  'suffix' => $suffix,
31
- );
32
  }
33
 
34
  /**
35
  * Register autoloader for plugin classes.
36
  */
37
  public function register() {
38
- spl_autoload_register( array( $this, 'autoload' ) );
39
  }
40
 
41
  /**
@@ -43,7 +32,7 @@ class RWMB_Autoloader {
43
  *
44
  * @param string $class Class name.
45
  */
46
- public function autoload( $class ) {
47
  foreach ( $this->dirs as $dir ) {
48
  if (
49
  ( $dir['prefix'] && 0 !== strpos( $class, $dir['prefix'] ) )
@@ -55,7 +44,7 @@ class RWMB_Autoloader {
55
  if ( $dir['suffix'] && strlen( $file ) > strlen( $dir['suffix'] ) ) {
56
  $file = substr( $file, 0, - strlen( $dir['suffix'] ) );
57
  }
58
- if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
59
  $file = mb_strtolower( str_replace( '_', '-', $file ), mb_detect_encoding( $file ) ) . '.php';
60
  } else {
61
  $file = strtolower( str_replace( '_', '-', $file ) ) . '.php';
@@ -65,11 +54,6 @@ class RWMB_Autoloader {
65
  }
66
  }
67
 
68
- /**
69
- * If a file exists, require it from the file system.
70
- *
71
- * @param string $file The file to require.
72
- */
73
  protected function require_file( $file ) {
74
  if ( file_exists( $file ) ) {
75
  require_once $file;
1
  <?php
2
  /**
3
  * Autoload plugin classes.
 
 
 
 
 
 
4
  */
5
  class RWMB_Autoloader {
6
+ protected $dirs = [];
 
 
 
 
 
7
 
8
  /**
9
  * Adds a base directory for a class name prefix and/or suffix.
12
  * @param string $prefix The class name prefix.
13
  * @param string $suffix The class name suffix.
14
  */
15
+ public function add( string $dir, string $prefix, string $suffix = '' ) {
16
+ $this->dirs[] = [
17
  'dir' => trailingslashit( $dir ),
18
  'prefix' => $prefix,
19
  'suffix' => $suffix,
20
+ ];
21
  }
22
 
23
  /**
24
  * Register autoloader for plugin classes.
25
  */
26
  public function register() {
27
+ spl_autoload_register( [ $this, 'autoload' ] );
28
  }
29
 
30
  /**
32
  *
33
  * @param string $class Class name.
34
  */
35
+ public function autoload( string $class ) {
36
  foreach ( $this->dirs as $dir ) {
37
  if (
38
  ( $dir['prefix'] && 0 !== strpos( $class, $dir['prefix'] ) )
44
  if ( $dir['suffix'] && strlen( $file ) > strlen( $dir['suffix'] ) ) {
45
  $file = substr( $file, 0, - strlen( $dir['suffix'] ) );
46
  }
47
+ if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
48
  $file = mb_strtolower( str_replace( '_', '-', $file ), mb_detect_encoding( $file ) ) . '.php';
49
  } else {
50
  $file = strtolower( str_replace( '_', '-', $file ) ) . '.php';
54
  }
55
  }
56
 
 
 
 
 
 
57
  protected function require_file( $file ) {
58
  if ( file_exists( $file ) ) {
59
  require_once $file;
inc/clone.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
  * The clone module, allowing users to clone (duplicate) fields.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * The clone class.
10
  */
11
  class RWMB_Clone {
12
  /**
@@ -39,7 +33,7 @@ class RWMB_Clone {
39
  }
40
  }
41
 
42
- if ( in_array( $sub_field['type'], array( 'file', 'image' ), true ) ) {
43
  $sub_field['input_name'] = '_file_' . uniqid();
44
  $sub_field['index_name'] .= "[{$index}]";
45
  } elseif ( $field['multiple'] ) {
@@ -81,14 +75,14 @@ class RWMB_Clone {
81
  */
82
  public static function value( $new, $old, $object_id, $field ) {
83
  if ( ! is_array( $new ) ) {
84
- $new = array();
85
  }
86
 
87
- if ( in_array( $field['type'], array( 'file', 'image' ), true ) ) {
88
  $new = RWMB_File_Field::clone_value( $new, $old, $object_id, $field );
89
  } else {
90
  foreach ( $new as $key => $value ) {
91
- $old_value = isset( $old[ $key ] ) ? $old[ $key ] : null;
92
  $value = RWMB_Field::call( $field, 'value', $value, $old_value, $object_id );
93
  $new[ $key ] = RWMB_Field::filter( 'sanitize', $value, $field, $old_value, $object_id );
94
  }
@@ -103,13 +97,7 @@ class RWMB_Clone {
103
  return $new;
104
  }
105
 
106
- /**
107
- * Add clone button.
108
- *
109
- * @param array $field Field parameters.
110
- * @return string $html
111
- */
112
- public static function add_clone_button( $field ) {
113
  if ( ! $field['clone'] ) {
114
  return '';
115
  }
@@ -117,13 +105,7 @@ class RWMB_Clone {
117
  return '<a href="#" class="rwmb-button button-primary add-clone">' . esc_html( $text ) . '</a>';
118
  }
119
 
120
- /**
121
- * Remove clone button.
122
- *
123
- * @param array $field Field parameters.
124
- * @return string $html
125
- */
126
- public static function remove_clone_button( $field ) {
127
  $text = RWMB_Field::filter( 'remove_clone_button_text', '<span class="dashicons dashicons-dismiss"></span>', $field );
128
  return '<a href="#" class="rwmb-button remove-clone">' . $text . '</a>';
129
  }
1
  <?php
2
  /**
3
  * The clone module, allowing users to clone (duplicate) fields.
 
 
 
 
 
 
4
  */
5
  class RWMB_Clone {
6
  /**
33
  }
34
  }
35
 
36
+ if ( in_array( $sub_field['type'], [ 'file', 'image' ], true ) ) {
37
  $sub_field['input_name'] = '_file_' . uniqid();
38
  $sub_field['index_name'] .= "[{$index}]";
39
  } elseif ( $field['multiple'] ) {
75
  */
76
  public static function value( $new, $old, $object_id, $field ) {
77
  if ( ! is_array( $new ) ) {
78
+ $new = [];
79
  }
80
 
81
+ if ( in_array( $field['type'], [ 'file', 'image' ], true ) ) {
82
  $new = RWMB_File_Field::clone_value( $new, $old, $object_id, $field );
83
  } else {
84
  foreach ( $new as $key => $value ) {
85
+ $old_value = $old[ $key ] ?? null;
86
  $value = RWMB_Field::call( $field, 'value', $value, $old_value, $object_id );
87
  $new[ $key ] = RWMB_Field::filter( 'sanitize', $value, $field, $old_value, $object_id );
88
  }
97
  return $new;
98
  }
99
 
100
+ public static function add_clone_button( array $field ) : string {
 
 
 
 
 
 
101
  if ( ! $field['clone'] ) {
102
  return '';
103
  }
105
  return '<a href="#" class="rwmb-button button-primary add-clone">' . esc_html( $text ) . '</a>';
106
  }
107
 
108
+ public static function remove_clone_button( array $field ) : string {
 
 
 
 
 
 
109
  $text = RWMB_Field::filter( 'remove_clone_button_text', '<span class="dashicons dashicons-dismiss"></span>', $field );
110
  return '<a href="#" class="rwmb-button remove-clone">' . $text . '</a>';
111
  }
inc/core.php CHANGED
@@ -1,52 +1,31 @@
1
  <?php
2
- /**
3
- * The plugin core class which initialize plugin's code.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * The Meta Box core class.
10
- *
11
- * @package Meta Box
12
- */
13
  class RWMB_Core {
14
- /**
15
- * Initialization.
16
- */
17
  public function init() {
18
- load_plugin_textdomain( 'meta-box', false, plugin_basename( RWMB_DIR ) . '/languages/' );
19
 
20
- add_filter( 'plugin_action_links_meta-box/meta-box.php', array( $this, 'plugin_links' ), 20 );
21
 
22
  // Uses priority 20 to support custom port types registered using the default priority.
23
- add_action( 'init', array( $this, 'register_meta_boxes' ), 20 );
24
- add_action( 'edit_page_form', array( $this, 'fix_page_template' ) );
25
  $this->add_context_hooks();
26
  }
27
 
 
 
 
 
 
28
  /**
29
- * Add links to Documentation and Extensions in plugin's list of action links.
30
- *
31
- * @since 4.3.11
32
- *
33
- * @param array $links Array of plugin links.
34
- *
35
- * @return array
36
  */
37
- public function plugin_links( $links ) {
38
  $links[] = '<a href="https://docs.metabox.io">' . esc_html__( 'Docs', 'meta-box' ) . '</a>';
39
  return $links;
40
  }
41
 
42
- /**
43
- * Register meta boxes.
44
- * Advantages:
45
- * - prevents incorrect hook.
46
- * - no need to check for class existences.
47
- */
48
  public function register_meta_boxes() {
49
- $configs = apply_filters( 'rwmb_meta_boxes', array() );
50
  $registry = rwmb_get_registry( 'meta_box' );
51
 
52
  foreach ( $configs as $config ) {
@@ -57,12 +36,8 @@ class RWMB_Core {
57
 
58
  /**
59
  * WordPress will prevent post data saving if a page template has been selected that does not exist.
60
- * This is especially a problem when switching to our theme, and old page templates are in the post data.
61
  * Unset the page template if the page does not exist to allow the post to save.
62
- *
63
- * @param WP_Post $post Post object.
64
- *
65
- * @since 4.3.10
66
  */
67
  public function fix_page_template( WP_Post $post ) {
68
  $template = get_post_meta( $post->ID, '_wp_page_template', true );
@@ -76,38 +51,27 @@ class RWMB_Core {
76
 
77
  /**
78
  * Get registered meta boxes via a filter.
79
- *
80
  * @deprecated No longer used. Keep for backward-compatibility with extensions.
81
- *
82
- * @return array
83
  */
84
- public static function get_meta_boxes() {
85
  $meta_boxes = rwmb_get_registry( 'meta_box' )->all();
86
  return wp_list_pluck( $meta_boxes, 'meta_box' );
87
  }
88
 
89
- /**
90
- * Add hooks for extra contexts.
91
- */
92
  public function add_context_hooks() {
93
- $hooks = array(
94
  'edit_form_top',
95
  'edit_form_after_title',
96
  'edit_form_after_editor',
97
  'edit_form_before_permalink',
98
- );
99
 
100
  foreach ( $hooks as $hook ) {
101
- add_action( $hook, array( $this, 'add_context' ) );
102
  }
103
  }
104
 
105
- /**
106
- * Add new meta box context.
107
- *
108
- * @param WP_Post $post The current post object.
109
- */
110
- public function add_context( $post ) {
111
  $hook = current_filter();
112
  $context = 'edit_form_top' === $hook ? 'form_top' : substr( $hook, 10 );
113
  do_meta_boxes( null, $context, $post );
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
2
  class RWMB_Core {
 
 
 
3
  public function init() {
4
+ add_action( 'init', [ $this, 'load_textdomain' ] );
5
 
6
+ add_filter( 'plugin_action_links_meta-box/meta-box.php', [ $this, 'plugin_links' ], 20 );
7
 
8
  // Uses priority 20 to support custom port types registered using the default priority.
9
+ add_action( 'init', [ $this, 'register_meta_boxes' ], 20 );
10
+ add_action( 'edit_page_form', [ $this, 'fix_page_template' ] );
11
  $this->add_context_hooks();
12
  }
13
 
14
+ public function load_textdomain() {
15
+ unload_textdomain( 'meta-box' );
16
+ load_plugin_textdomain( 'meta-box', false, plugin_basename( RWMB_DIR ) . '/languages/' );
17
+ }
18
+
19
  /**
20
+ * Add links to Documentation in plugin's list of action links.
 
 
 
 
 
 
21
  */
22
+ public function plugin_links( array $links ) : array {
23
  $links[] = '<a href="https://docs.metabox.io">' . esc_html__( 'Docs', 'meta-box' ) . '</a>';
24
  return $links;
25
  }
26
 
 
 
 
 
 
 
27
  public function register_meta_boxes() {
28
+ $configs = apply_filters( 'rwmb_meta_boxes', [] );
29
  $registry = rwmb_get_registry( 'meta_box' );
30
 
31
  foreach ( $configs as $config ) {
36
 
37
  /**
38
  * WordPress will prevent post data saving if a page template has been selected that does not exist.
39
+ * This is especially a problem when switching themes, and old page templates are in the post data.
40
  * Unset the page template if the page does not exist to allow the post to save.
 
 
 
 
41
  */
42
  public function fix_page_template( WP_Post $post ) {
43
  $template = get_post_meta( $post->ID, '_wp_page_template', true );
51
 
52
  /**
53
  * Get registered meta boxes via a filter.
 
54
  * @deprecated No longer used. Keep for backward-compatibility with extensions.
 
 
55
  */
56
+ public static function get_meta_boxes() : array {
57
  $meta_boxes = rwmb_get_registry( 'meta_box' )->all();
58
  return wp_list_pluck( $meta_boxes, 'meta_box' );
59
  }
60
 
 
 
 
61
  public function add_context_hooks() {
62
+ $hooks = [
63
  'edit_form_top',
64
  'edit_form_after_title',
65
  'edit_form_after_editor',
66
  'edit_form_before_permalink',
67
+ ];
68
 
69
  foreach ( $hooks as $hook ) {
70
+ add_action( $hook, [ $this, 'render_meta_boxes_for_context' ] );
71
  }
72
  }
73
 
74
+ public function render_meta_boxes_for_context( WP_Post $post ) {
 
 
 
 
 
75
  $hook = current_filter();
76
  $context = 'edit_form_top' === $hook ? 'form_top' : substr( $hook, 10 );
77
  do_meta_boxes( null, $context, $post );
inc/field-registry.php CHANGED
@@ -2,20 +2,10 @@
2
  /**
3
  * A registry for storing all fields.
4
  *
5
- * @link https://designpatternsphp.readthedocs.io/en/latest/Structural/Registry/README.html
6
- * @package Meta Box
7
- */
8
-
9
- /**
10
- * Field registry class.
11
  */
12
  class RWMB_Field_Registry {
13
- /**
14
- * Internal data storage.
15
- *
16
- * @var array
17
- */
18
- private $data = array();
19
 
20
  /**
21
  * Add a single field to the registry.
@@ -24,16 +14,16 @@ class RWMB_Field_Registry {
24
  * @param string $type Post type|Taxonomy|'user'|Setting page which the field belongs to.
25
  * @param string $object_type Object type which the field belongs to.
26
  */
27
- public function add( $field, $type, $object_type = 'post' ) {
28
  if ( ! isset( $field['id'] ) ) {
29
  return;
30
  }
31
 
32
  if ( empty( $this->data[ $object_type ] ) ) {
33
- $this->data[ $object_type ] = array();
34
  }
35
  if ( empty( $this->data[ $object_type ][ $type ] ) ) {
36
- $this->data[ $object_type ][ $type ] = array();
37
  }
38
  $this->data[ $object_type ][ $type ][ $field['id'] ] = $field;
39
 
@@ -50,7 +40,7 @@ class RWMB_Field_Registry {
50
  * @return bool|array False or field configuration.
51
  */
52
  public function get( $id, $type, $object_type = 'post' ) {
53
- return isset( $this->data[ $object_type ][ $type ][ $id ] ) ? $this->data[ $object_type ][ $type ][ $id ] : false;
54
  }
55
 
56
  /**
@@ -60,7 +50,7 @@ class RWMB_Field_Registry {
60
  *
61
  * @return array List of fields.
62
  */
63
- public function get_by_object_type( $object_type = 'post' ) {
64
- return isset( $this->data[ $object_type ] ) ? $this->data[ $object_type ] : array();
65
  }
66
  }
2
  /**
3
  * A registry for storing all fields.
4
  *
5
+ * @link https://designpatternsphp.readthedocs.io/en/latest/Structural/Registry/README.html
 
 
 
 
 
6
  */
7
  class RWMB_Field_Registry {
8
+ private $data = [];
 
 
 
 
 
9
 
10
  /**
11
  * Add a single field to the registry.
14
  * @param string $type Post type|Taxonomy|'user'|Setting page which the field belongs to.
15
  * @param string $object_type Object type which the field belongs to.
16
  */
17
+ public function add( array $field, string $type, string $object_type = 'post' ) {
18
  if ( ! isset( $field['id'] ) ) {
19
  return;
20
  }
21
 
22
  if ( empty( $this->data[ $object_type ] ) ) {
23
+ $this->data[ $object_type ] = [];
24
  }
25
  if ( empty( $this->data[ $object_type ][ $type ] ) ) {
26
+ $this->data[ $object_type ][ $type ] = [];
27
  }
28
  $this->data[ $object_type ][ $type ][ $field['id'] ] = $field;
29
 
40
  * @return bool|array False or field configuration.
41
  */
42
  public function get( $id, $type, $object_type = 'post' ) {
43
+ return $this->data[ $object_type ][ $type ][ $id ] ?? false;
44
  }
45
 
46
  /**
50
  *
51
  * @return array List of fields.
52
  */
53
+ public function get_by_object_type( string $object_type = 'post' ) : array {
54
+ return $this->data[ $object_type ] ?? [];
55
  }
56
  }
inc/field.php CHANGED
@@ -49,7 +49,7 @@ abstract class RWMB_Field {
49
  $field_html = self::filter( 'html', $field_html, $field, $meta );
50
  }
51
 
52
- $end = self::call( $field, 'end_html', $meta );
53
  $end = self::filter( 'end_html', $end, $field, $meta );
54
 
55
  $html = self::filter( 'wrapper_html', "$begin$field_html$end", $field, $meta );
@@ -91,20 +91,23 @@ abstract class RWMB_Field {
91
  * @return string
92
  */
93
  public static function begin_html( $meta, $field ) {
94
- $field_label = '';
95
- if ( $field['name'] ) {
96
- // Change "for" attribute in label
97
- $field_label = sprintf(
98
- '<div class="rwmb-label">
99
- <label for="%s">%s%s</label>
100
- %s
101
- </div>',
102
- ( isset( $field['attributes']['id'] ) ) ? esc_attr( $field['attributes']['id'] ) : esc_attr( $field['id'] ),
103
- $field['name'],
104
- $field['required'] || ! empty( $field['attributes']['required'] ) ? '<span class="rwmb-required">*</span>' : '',
105
- self::label_description( $field )
106
- );
107
- }
 
 
 
108
 
109
  $data_min_clone = is_numeric( $field['min_clone'] ) && $field['min_clone'] > 1 ? ' data-min-clone=' . $field['min_clone'] : '';
110
  $data_max_clone = is_numeric( $field['max_clone'] ) && $field['max_clone'] > 1 ? ' data-max-clone=' . $field['max_clone'] : '';
@@ -115,19 +118,14 @@ abstract class RWMB_Field {
115
  $data_max_clone
116
  );
117
 
118
- return $field_label . $input_open;
119
  }
120
 
121
  /**
122
  * Show end HTML markup for fields.
123
- *
124
- * @param mixed $meta Meta value.
125
- * @param array $field Field parameters.
126
- *
127
- * @return string
128
  */
129
- public static function end_html( $meta, $field ) {
130
- return RWMB_Clone::add_clone_button( $field ) . self::call( 'input_description', $field ) . '</div>';
131
  }
132
 
133
  /**
@@ -161,7 +159,7 @@ abstract class RWMB_Field {
161
  *
162
  * @return mixed
163
  */
164
- public static function raw_meta( $object_id, $field, $args = array() ) {
165
  if ( empty( $field['id'] ) ) {
166
  return '';
167
  }
@@ -216,7 +214,7 @@ abstract class RWMB_Field {
216
 
217
  // Ensure $meta is an array with values so that the foreach loop in self::show() runs properly.
218
  if ( empty( $meta ) ) {
219
- $meta = array( '' );
220
  }
221
 
222
  if ( $field['multiple'] ) {
@@ -224,7 +222,7 @@ abstract class RWMB_Field {
224
 
225
  // If users set std for a cloneable checkbox list field in the Builder, they can only set [value1, value2]. We need to transform it to [[value1, value2]].
226
  // In other cases, make sure each value is an array.
227
- $meta = is_array( $first ) ? array_map( 'RWMB_Helpers_Array::ensure', $meta ) : array( $meta );
228
  }
229
  } elseif ( $field['multiple'] ) {
230
  $meta = RWMB_Helpers_Array::ensure( $meta );
@@ -319,45 +317,42 @@ abstract class RWMB_Field {
319
  public static function normalize( $field ) {
320
  // Quick define text fields with "name" attribute only.
321
  if ( is_string( $field ) ) {
322
- $field = array(
323
  'name' => $field,
324
  'id' => sanitize_key( $field ),
325
- );
326
- }
327
- $field = wp_parse_args(
328
- $field,
329
- array(
330
- 'id' => '',
331
- 'name' => '',
332
- 'type' => 'text',
333
- 'label_description' => '',
334
- 'multiple' => false,
335
- 'std' => '',
336
- 'desc' => '',
337
- 'format' => '',
338
- 'before' => '',
339
- 'after' => '',
340
- 'field_name' => isset( $field['id'] ) ? $field['id'] : '',
341
- 'placeholder' => '',
342
- 'save_field' => true,
343
-
344
- 'clone' => false,
345
- 'min_clone' => 0,
346
- 'max_clone' => 0,
347
- 'sort_clone' => false,
348
- 'add_button' => __( '+ Add more', 'meta-box' ),
349
- 'clone_default' => false,
350
- 'clone_as_multiple' => false,
351
-
352
- 'class' => '',
353
- 'disabled' => false,
354
- 'required' => false,
355
- 'autofocus' => false,
356
- 'attributes' => array(),
357
-
358
- 'sanitize_callback' => null,
359
- )
360
- );
361
 
362
  // Store the original ID to run correct filters for the clonable field.
363
  if ( $field['clone'] ) {
@@ -365,13 +360,10 @@ abstract class RWMB_Field {
365
  }
366
 
367
  if ( $field['clone_default'] ) {
368
- $field['attributes'] = wp_parse_args(
369
- $field['attributes'],
370
- array(
371
- 'data-default' => $field['std'],
372
- 'data-clone-default' => 'true',
373
- )
374
- );
375
  }
376
 
377
  if ( 1 === $field['max_clone'] ) {
@@ -390,19 +382,24 @@ abstract class RWMB_Field {
390
  * @return array
391
  */
392
  public static function get_attributes( $field, $value = null ) {
393
- $attributes = wp_parse_args(
394
- $field['attributes'],
395
- array(
396
- 'disabled' => $field['disabled'],
397
- 'autofocus' => $field['autofocus'],
398
- 'required' => $field['required'],
399
- 'id' => $field['id'],
400
- 'class' => '',
401
- 'name' => $field['field_name'],
402
- )
403
- );
404
 
405
- $attributes['class'] = trim( implode( ' ', array_merge( array( "rwmb-{$field['type']}" ), (array) $attributes['class'] ) ) );
 
 
 
 
 
 
 
 
406
 
407
  return $attributes;
408
  }
@@ -444,7 +441,7 @@ abstract class RWMB_Field {
444
  *
445
  * @return mixed Field value
446
  */
447
- public static function get_value( $field, $args = array(), $post_id = null ) {
448
  // Some fields does not have ID like heading, custom HTML, etc.
449
  if ( empty( $field['id'] ) ) {
450
  return '';
@@ -459,7 +456,7 @@ abstract class RWMB_Field {
459
 
460
  // Make sure meta value is an array for cloneable and multiple fields.
461
  if ( $field['clone'] || $field['multiple'] ) {
462
- $value = is_array( $value ) && $value ? $value : array();
463
  }
464
 
465
  return $value;
@@ -482,7 +479,7 @@ abstract class RWMB_Field {
482
  *
483
  * @return string HTML output of the field
484
  */
485
- public static function the_value( $field, $args = array(), $post_id = null ) {
486
  $value = self::call( 'get_value', $field, $args, $post_id );
487
 
488
  if ( false === $value ) {
@@ -570,7 +567,7 @@ abstract class RWMB_Field {
570
 
571
  if ( 'raw_meta' === $method ) {
572
  // Add field param after object id.
573
- array_splice( $args, 1, 0, array( $field ) );
574
  } else {
575
  $args[] = $field; // Add field as last param.
576
  }
@@ -578,10 +575,10 @@ abstract class RWMB_Field {
578
 
579
  $class = RWMB_Helpers_Field::get_class( $field );
580
  if ( method_exists( $class, $method ) ) {
581
- return call_user_func_array( array( $class, $method ), $args );
582
- } else {
583
- _deprecated_function( "$class::$method", '5.4.8' );
584
  }
 
 
585
  }
586
 
587
  /**
@@ -602,10 +599,10 @@ abstract class RWMB_Field {
602
  $field = array_shift( $args );
603
 
604
  // List of filters.
605
- $filters = array(
606
  'rwmb_' . $name,
607
  'rwmb_' . $field['type'] . '_' . $name,
608
- );
609
  if ( $field['id'] ) {
610
  $field_id = $field['clone'] ? $field['_original_id'] : $field['id'];
611
  $filters[] = 'rwmb_' . $field_id . '_' . $name;
49
  $field_html = self::filter( 'html', $field_html, $field, $meta );
50
  }
51
 
52
+ $end = static::end_html( $field );
53
  $end = self::filter( 'end_html', $end, $field, $meta );
54
 
55
  $html = self::filter( 'wrapper_html', "$begin$field_html$end", $field, $meta );
91
  * @return string
92
  */
93
  public static function begin_html( $meta, $field ) {
94
+ $id = $field['attributes']['id'] ?? $field['id'];
95
+ $required = $field['required'] || ! empty( $field['attributes']['required'] );
96
+
97
+ $label = $field['name'] ? sprintf(
98
+ '<label for="%s">%s%s</label>',
99
+ esc_attr( $id ),
100
+ $field['name'],
101
+ $required ? '<span class="rwmb-required">*</span>' : ''
102
+ ) : '';
103
+
104
+ $label .= static::label_description( $field );
105
+
106
+ $label = $label ? sprintf(
107
+ '<div class="rwmb-label" id="%s-label">%s</div>',
108
+ esc_attr( $id ),
109
+ $label
110
+ ) : '';
111
 
112
  $data_min_clone = is_numeric( $field['min_clone'] ) && $field['min_clone'] > 1 ? ' data-min-clone=' . $field['min_clone'] : '';
113
  $data_max_clone = is_numeric( $field['max_clone'] ) && $field['max_clone'] > 1 ? ' data-max-clone=' . $field['max_clone'] : '';
118
  $data_max_clone
119
  );
120
 
121
+ return $label . $input_open;
122
  }
123
 
124
  /**
125
  * Show end HTML markup for fields.
 
 
 
 
 
126
  */
127
+ public static function end_html( array $field ) : string {
128
+ return RWMB_Clone::add_clone_button( $field ) . static::input_description( $field ) . '</div>';
129
  }
130
 
131
  /**
159
  *
160
  * @return mixed
161
  */
162
+ public static function raw_meta( $object_id, $field, $args = [] ) {
163
  if ( empty( $field['id'] ) ) {
164
  return '';
165
  }
214
 
215
  // Ensure $meta is an array with values so that the foreach loop in self::show() runs properly.
216
  if ( empty( $meta ) ) {
217
+ $meta = [ '' ];
218
  }
219
 
220
  if ( $field['multiple'] ) {
222
 
223
  // If users set std for a cloneable checkbox list field in the Builder, they can only set [value1, value2]. We need to transform it to [[value1, value2]].
224
  // In other cases, make sure each value is an array.
225
+ $meta = is_array( $first ) ? array_map( 'RWMB_Helpers_Array::ensure', $meta ) : [ $meta ];
226
  }
227
  } elseif ( $field['multiple'] ) {
228
  $meta = RWMB_Helpers_Array::ensure( $meta );
317
  public static function normalize( $field ) {
318
  // Quick define text fields with "name" attribute only.
319
  if ( is_string( $field ) ) {
320
+ $field = [
321
  'name' => $field,
322
  'id' => sanitize_key( $field ),
323
+ ];
324
+ }
325
+ $field = wp_parse_args( $field, [
326
+ 'id' => '',
327
+ 'name' => '',
328
+ 'type' => 'text',
329
+ 'label_description' => '',
330
+ 'multiple' => false,
331
+ 'std' => '',
332
+ 'desc' => '',
333
+ 'format' => '',
334
+ 'before' => '',
335
+ 'after' => '',
336
+ 'field_name' => $field['id'] ?? '',
337
+ 'placeholder' => '',
338
+ 'save_field' => true,
339
+
340
+ 'clone' => false,
341
+ 'min_clone' => 0,
342
+ 'max_clone' => 0,
343
+ 'sort_clone' => false,
344
+ 'add_button' => __( '+ Add more', 'meta-box' ),
345
+ 'clone_default' => false,
346
+ 'clone_as_multiple' => false,
347
+
348
+ 'class' => '',
349
+ 'disabled' => false,
350
+ 'required' => false,
351
+ 'autofocus' => false,
352
+ 'attributes' => [],
353
+
354
+ 'sanitize_callback' => null,
355
+ ] );
 
 
 
356
 
357
  // Store the original ID to run correct filters for the clonable field.
358
  if ( $field['clone'] ) {
360
  }
361
 
362
  if ( $field['clone_default'] ) {
363
+ $field['attributes'] = wp_parse_args( $field['attributes'], [
364
+ 'data-default' => $field['std'],
365
+ 'data-clone-default' => 'true',
366
+ ] );
 
 
 
367
  }
368
 
369
  if ( 1 === $field['max_clone'] ) {
382
  * @return array
383
  */
384
  public static function get_attributes( $field, $value = null ) {
385
+ $attributes = wp_parse_args( $field['attributes'], [
386
+ 'disabled' => $field['disabled'],
387
+ 'autofocus' => $field['autofocus'],
388
+ 'required' => $field['required'],
389
+ 'id' => $field['id'],
390
+ 'class' => '',
391
+ 'name' => $field['field_name'],
392
+ ] );
 
 
 
393
 
394
+ $attributes['class'] = trim( implode( ' ', array_merge( [ "rwmb-{$field['type']}" ], (array) $attributes['class'] ) ) );
395
+
396
+ $id = $attributes['id'] ?: $field['id'];
397
+ if ( $field['name'] || $field['label_description'] ) {
398
+ $attributes['aria-labelledby'] = "$id-label";
399
+ }
400
+ if ( $field['desc'] ) {
401
+ $attributes['aria-describedby'] = "$id-description";
402
+ }
403
 
404
  return $attributes;
405
  }
441
  *
442
  * @return mixed Field value
443
  */
444
+ public static function get_value( $field, $args = [], $post_id = null ) {
445
  // Some fields does not have ID like heading, custom HTML, etc.
446
  if ( empty( $field['id'] ) ) {
447
  return '';
456
 
457
  // Make sure meta value is an array for cloneable and multiple fields.
458
  if ( $field['clone'] || $field['multiple'] ) {
459
+ $value = is_array( $value ) && $value ? $value : [];
460
  }
461
 
462
  return $value;
479
  *
480
  * @return string HTML output of the field
481
  */
482
+ public static function the_value( $field, $args = [], $post_id = null ) {
483
  $value = self::call( 'get_value', $field, $args, $post_id );
484
 
485
  if ( false === $value ) {
567
 
568
  if ( 'raw_meta' === $method ) {
569
  // Add field param after object id.
570
+ array_splice( $args, 1, 0, [ $field ] );
571
  } else {
572
  $args[] = $field; // Add field as last param.
573
  }
575
 
576
  $class = RWMB_Helpers_Field::get_class( $field );
577
  if ( method_exists( $class, $method ) ) {
578
+ return call_user_func_array( [ $class, $method ], $args );
 
 
579
  }
580
+
581
+ _deprecated_function( esc_html( "$class::$method" ), '5.4.8' );
582
  }
583
 
584
  /**
599
  $field = array_shift( $args );
600
 
601
  // List of filters.
602
+ $filters = [
603
  'rwmb_' . $name,
604
  'rwmb_' . $field['type'] . '_' . $name,
605
+ ];
606
  if ( $field['id'] ) {
607
  $field_id = $field['clone'] ? $field['_original_id'] : $field['id'];
608
  $filters[] = 'rwmb_' . $field_id . '_' . $name;
inc/fields/datetime.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
  * The date and time picker field which allows users to select both date and time via jQueryUI datetime picker.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Datetime field class.
10
  */
11
  class RWMB_Datetime_Field extends RWMB_Input_Field {
12
  /**
@@ -16,7 +10,7 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
16
  *
17
  * @var array
18
  */
19
- protected static $date_formats = array(
20
  'd' => 'j',
21
  'dd' => 'd',
22
  'oo' => 'z',
@@ -29,7 +23,7 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
29
  'y' => 'y',
30
  'yy' => 'Y',
31
  'o' => 'z',
32
- );
33
 
34
  /**
35
  * Translate time format from jQuery UI time picker to PHP date().
@@ -38,7 +32,7 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
38
  *
39
  * @var array
40
  */
41
- protected static $time_formats = array(
42
  'H' => 'G',
43
  'HH' => 'H',
44
  'h' => 'g',
@@ -48,38 +42,38 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
48
  'l' => 'u',
49
  'tt' => 'a',
50
  'TT' => 'A',
51
- );
52
 
53
  public static function register_assets() {
54
  // jQueryUI base theme: https://github.com/jquery/jquery-ui/tree/1.12.1/themes/base
55
  $url = RWMB_CSS_URL . 'jqueryui';
56
  wp_register_style( 'jquery-ui-core', "$url/core.css", [], '1.12.1' );
57
  wp_register_style( 'jquery-ui-theme', "$url/theme.css", [], '1.12.1' );
58
- wp_register_style( 'jquery-ui-datepicker', "$url/datepicker.css", ['jquery-ui-core', 'jquery-ui-theme'], '1.12.1' );
59
- wp_register_style( 'jquery-ui-slider', "$url/slider.css", ['jquery-ui-core', 'jquery-ui-theme'], '1.12.1' );
60
 
61
  // jQueryUI timepicker addon: https://github.com/trentrichardson/jQuery-Timepicker-Addon
62
- wp_register_style( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.css", ['rwmb-date', 'jquery-ui-slider'], '1.6.3' );
63
 
64
- wp_register_style( 'rwmb-date', RWMB_CSS_URL . 'date.css', ['jquery-ui-datepicker'], RWMB_VER );
65
 
66
  // Scripts.
67
  $url = RWMB_JS_URL . 'jqueryui';
68
- wp_register_script( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.js", ['jquery-ui-datepicker', 'jquery-ui-slider'], '1.6.3', true );
69
- wp_register_script( 'jquery-ui-timepicker-slider', "$url/jquery-ui-sliderAccess.js", ['jquery-ui-datepicker', 'jquery-ui-slider'], '0.3', true );
70
- wp_register_script( 'jquery-ui-timepicker-i18n', "$url/jquery-ui-timepicker-addon-i18n.min.js", ['jquery-ui-timepicker'], '1.6.3', true );
71
 
72
- wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', ['jquery-ui-datepicker', 'jquery-ui-timepicker-i18n', 'underscore', 'jquery-ui-button', 'jquery-ui-timepicker-slider'], RWMB_VER, true );
73
- wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', ['jquery-ui-datepicker', 'underscore'], RWMB_VER, true );
74
- wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', ['jquery-ui-timepicker-i18n', 'jquery-ui-button', 'jquery-ui-timepicker-slider'], RWMB_VER, true );
75
 
76
- $handles = ['datetime', 'time'];
77
  $locale = str_replace( '_', '-', get_locale() );
78
  $locale_short = substr( $locale, 0, 2 );
79
- $data = array(
80
  'locale' => $locale,
81
  'localeShort' => $locale_short,
82
- );
83
  foreach ( $handles as $handle ) {
84
  RWMB_Helpers_Field::localize_script_once( "rwmb-$handle", 'RWMB_' . ucfirst( $handle ), $data );
85
  }
@@ -107,12 +101,7 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
107
 
108
  if ( $field['timestamp'] ) {
109
  $name = $field['field_name'];
110
- $field = wp_parse_args(
111
- array(
112
- 'field_name' => $name . '[formatted]',
113
- ),
114
- $field
115
- );
116
  $output .= sprintf(
117
  '<input type="hidden" name="%s" class="rwmb-datetime-timestamp" value="%s">',
118
  esc_attr( $name . '[timestamp]' ),
@@ -144,7 +133,8 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
144
  if ( $field['timestamp'] ) {
145
  if ( is_array( $new ) ) {
146
  return $new['timestamp'];
147
- } elseif ( ! is_numeric( $new ) ) {
 
148
  return strtotime( $new );
149
  }
150
  return $new;
@@ -188,11 +178,11 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
188
  * @param array $field Field parameters.
189
  * @return array
190
  */
191
- public static function from_timestamp( $meta, $field ) {
192
- return array(
193
- 'timestamp' => $meta ? $meta : null,
194
  'formatted' => $meta ? gmdate( $field['php_format'], intval( $meta ) ) : '',
195
- );
196
  }
197
 
198
  /**
@@ -214,46 +204,35 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
214
  * @return array
215
  */
216
  public static function normalize( $field ) {
217
- $field = wp_parse_args(
218
- $field,
219
- array(
220
- 'timestamp' => false,
221
- 'inline' => false,
222
- 'js_options' => array(),
223
- 'save_format' => '',
224
- 'autocomplete' => 'off',
225
- )
226
- );
227
 
228
  // Deprecate 'format', but keep it for backward compatible.
229
  // Use 'js_options' instead.
230
- $field['js_options'] = wp_parse_args(
231
- $field['js_options'],
232
- array(
233
- 'timeFormat' => 'HH:mm',
234
- 'separator' => ' ',
235
- 'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
236
- 'showButtonPanel' => true,
237
- 'changeYear' => true,
238
- 'yearRange' => '-100:+100',
239
- 'changeMonth' => true,
240
- 'showButtonPanel' => true,
241
- 'oneLine' => true,
242
- 'controlType' => 'select', // select or slider
243
- 'addSliderAccess' => true,
244
- 'sliderAccessArgs' => [
245
- 'touchonly' => true, // To show sliderAccess only on touch devices
246
- ],
247
- )
248
- );
249
 
250
  if ( $field['inline'] ) {
251
- $field['js_options'] = wp_parse_args(
252
- $field['js_options'],
253
- array(
254
- 'altFieldTimeOnly' => false,
255
- )
256
- );
257
  }
258
 
259
  $field['php_format'] = static::get_php_format( $field['js_options'] );
@@ -273,12 +252,7 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
273
  */
274
  public static function get_attributes( $field, $value = null ) {
275
  $attributes = parent::get_attributes( $field, $value );
276
- $attributes = wp_parse_args(
277
- $attributes,
278
- array(
279
- 'data-options' => wp_json_encode( $field['js_options'] ),
280
- )
281
- );
282
  $attributes['type'] = 'text';
283
 
284
  return $attributes;
@@ -312,10 +286,10 @@ class RWMB_Datetime_Field extends RWMB_Input_Field {
312
  if ( $field['timestamp'] ) {
313
  $value = self::from_timestamp( $value, $field );
314
  } else {
315
- $value = array(
316
  'timestamp' => strtotime( $value ),
317
  'formatted' => $value,
318
- );
319
  }
320
  return empty( $args['format'] ) ? $value['formatted'] : gmdate( $args['format'], $value['timestamp'] );
321
  }
1
  <?php
2
  /**
3
  * The date and time picker field which allows users to select both date and time via jQueryUI datetime picker.
 
 
 
 
 
 
4
  */
5
  class RWMB_Datetime_Field extends RWMB_Input_Field {
6
  /**
10
  *
11
  * @var array
12
  */
13
+ protected static $date_formats = [
14
  'd' => 'j',
15
  'dd' => 'd',
16
  'oo' => 'z',
23
  'y' => 'y',
24
  'yy' => 'Y',
25
  'o' => 'z',
26
+ ];
27
 
28
  /**
29
  * Translate time format from jQuery UI time picker to PHP date().
32
  *
33
  * @var array
34
  */
35
+ protected static $time_formats = [
36
  'H' => 'G',
37
  'HH' => 'H',
38
  'h' => 'g',
42
  'l' => 'u',
43
  'tt' => 'a',
44
  'TT' => 'A',
45
+ ];
46
 
47
  public static function register_assets() {
48
  // jQueryUI base theme: https://github.com/jquery/jquery-ui/tree/1.12.1/themes/base
49
  $url = RWMB_CSS_URL . 'jqueryui';
50
  wp_register_style( 'jquery-ui-core', "$url/core.css", [], '1.12.1' );
51
  wp_register_style( 'jquery-ui-theme', "$url/theme.css", [], '1.12.1' );
52
+ wp_register_style( 'jquery-ui-datepicker', "$url/datepicker.css", [ 'jquery-ui-core', 'jquery-ui-theme' ], '1.12.1' );
53
+ wp_register_style( 'jquery-ui-slider', "$url/slider.css", [ 'jquery-ui-core', 'jquery-ui-theme' ], '1.12.1' );
54
 
55
  // jQueryUI timepicker addon: https://github.com/trentrichardson/jQuery-Timepicker-Addon
56
+ wp_register_style( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.css", [ 'rwmb-date', 'jquery-ui-slider' ], '1.6.3' );
57
 
58
+ wp_register_style( 'rwmb-date', RWMB_CSS_URL . 'date.css', [ 'jquery-ui-datepicker' ], RWMB_VER );
59
 
60
  // Scripts.
61
  $url = RWMB_JS_URL . 'jqueryui';
62
+ wp_register_script( 'jquery-ui-timepicker', "$url/jquery-ui-timepicker-addon.min.js", [ 'jquery-ui-datepicker', 'jquery-ui-slider' ], '1.6.3', true );
63
+ wp_register_script( 'jquery-ui-timepicker-slider', "$url/jquery-ui-sliderAccess.js", [ 'jquery-ui-datepicker', 'jquery-ui-slider' ], '0.3', true );
64
+ wp_register_script( 'jquery-ui-timepicker-i18n', "$url/jquery-ui-timepicker-addon-i18n.min.js", [ 'jquery-ui-timepicker' ], '1.6.3', true );
65
 
66
+ wp_register_script( 'rwmb-datetime', RWMB_JS_URL . 'datetime.js', [ 'jquery-ui-datepicker', 'jquery-ui-timepicker-i18n', 'underscore', 'jquery-ui-button', 'jquery-ui-timepicker-slider' ], RWMB_VER, true );
67
+ wp_register_script( 'rwmb-date', RWMB_JS_URL . 'date.js', [ 'jquery-ui-datepicker', 'underscore' ], RWMB_VER, true );
68
+ wp_register_script( 'rwmb-time', RWMB_JS_URL . 'time.js', [ 'jquery-ui-timepicker-i18n', 'jquery-ui-button', 'jquery-ui-timepicker-slider' ], RWMB_VER, true );
69
 
70
+ $handles = [ 'datetime', 'time' ];
71
  $locale = str_replace( '_', '-', get_locale() );
72
  $locale_short = substr( $locale, 0, 2 );
73
+ $data = [
74
  'locale' => $locale,
75
  'localeShort' => $locale_short,
76
+ ];
77
  foreach ( $handles as $handle ) {
78
  RWMB_Helpers_Field::localize_script_once( "rwmb-$handle", 'RWMB_' . ucfirst( $handle ), $data );
79
  }
101
 
102
  if ( $field['timestamp'] ) {
103
  $name = $field['field_name'];
104
+ $field = wp_parse_args( [ 'field_name' => $name . '[formatted]' ], $field );
 
 
 
 
 
105
  $output .= sprintf(
106
  '<input type="hidden" name="%s" class="rwmb-datetime-timestamp" value="%s">',
107
  esc_attr( $name . '[timestamp]' ),
133
  if ( $field['timestamp'] ) {
134
  if ( is_array( $new ) ) {
135
  return $new['timestamp'];
136
+ }
137
+ if ( ! is_numeric( $new ) ) {
138
  return strtotime( $new );
139
  }
140
  return $new;
178
  * @param array $field Field parameters.
179
  * @return array
180
  */
181
+ public static function from_timestamp( $meta, array $field ) : array {
182
+ return [
183
+ 'timestamp' => $meta ?: null,
184
  'formatted' => $meta ? gmdate( $field['php_format'], intval( $meta ) ) : '',
185
+ ];
186
  }
187
 
188
  /**
204
  * @return array
205
  */
206
  public static function normalize( $field ) {
207
+ $field = wp_parse_args( $field, [
208
+ 'timestamp' => false,
209
+ 'inline' => false,
210
+ 'js_options' => [],
211
+ 'save_format' => '',
212
+ 'autocomplete' => 'off',
213
+ ] );
 
 
 
214
 
215
  // Deprecate 'format', but keep it for backward compatible.
216
  // Use 'js_options' instead.
217
+ $field['js_options'] = wp_parse_args( $field['js_options'], [
218
+ 'timeFormat' => 'HH:mm',
219
+ 'separator' => ' ',
220
+ 'dateFormat' => empty( $field['format'] ) ? 'yy-mm-dd' : $field['format'],
221
+ 'showButtonPanel' => true,
222
+ 'changeYear' => true,
223
+ 'yearRange' => '-100:+100',
224
+ 'changeMonth' => true,
225
+ 'showButtonPanel' => true,
226
+ 'oneLine' => true,
227
+ 'controlType' => 'select', // select or slider
228
+ 'addSliderAccess' => true,
229
+ 'sliderAccessArgs' => [
230
+ 'touchonly' => true, // To show sliderAccess only on touch devices
231
+ ],
232
+ ] );
 
 
 
233
 
234
  if ( $field['inline'] ) {
235
+ $field['js_options'] = wp_parse_args( $field['js_options'], [ 'altFieldTimeOnly' => false ] );
 
 
 
 
 
236
  }
237
 
238
  $field['php_format'] = static::get_php_format( $field['js_options'] );
252
  */
253
  public static function get_attributes( $field, $value = null ) {
254
  $attributes = parent::get_attributes( $field, $value );
255
+ $attributes = wp_parse_args( $attributes, [ 'data-options' => wp_json_encode( $field['js_options'] ) ] );
 
 
 
 
 
256
  $attributes['type'] = 'text';
257
 
258
  return $attributes;
286
  if ( $field['timestamp'] ) {
287
  $value = self::from_timestamp( $value, $field );
288
  } else {
289
+ $value = [
290
  'timestamp' => strtotime( $value ),
291
  'formatted' => $value,
292
+ ];
293
  }
294
  return empty( $args['format'] ) ? $value['formatted'] : gmdate( $args['format'], $value['timestamp'] );
295
  }
inc/fields/divider.php CHANGED
@@ -1,19 +1,10 @@
1
  <?php
2
  /**
3
  * The divider field which displays a simple horizontal line.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Divider field class.
10
  */
11
  class RWMB_Divider_Field extends RWMB_Field {
12
- /**
13
- * Enqueue scripts and styles.
14
- */
15
  public static function admin_enqueue_scripts() {
16
- wp_enqueue_style( 'rwmb-divider', RWMB_CSS_URL . 'divider.css', array(), RWMB_VER );
17
  }
18
 
19
  /**
@@ -31,13 +22,8 @@ class RWMB_Divider_Field extends RWMB_Field {
31
 
32
  /**
33
  * Show end HTML markup for fields.
34
- *
35
- * @param mixed $meta Meta value.
36
- * @param array $field Field parameters.
37
- *
38
- * @return string
39
  */
40
- public static function end_html( $meta, $field ) {
41
  return '';
42
  }
43
  }
1
  <?php
2
  /**
3
  * The divider field which displays a simple horizontal line.
 
 
 
 
 
 
4
  */
5
  class RWMB_Divider_Field extends RWMB_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
+ wp_enqueue_style( 'rwmb-divider', RWMB_CSS_URL . 'divider.css', [], RWMB_VER );
8
  }
9
 
10
  /**
22
 
23
  /**
24
  * Show end HTML markup for fields.
 
 
 
 
 
25
  */
26
+ public static function end_html( array $field ) : string {
27
  return '';
28
  }
29
  }
inc/fields/file.php CHANGED
@@ -1,66 +1,44 @@
1
  <?php
2
  /**
3
  * The file upload file which allows users to upload files via the default HTML <input type="file">.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * File field class which uses HTML <input type="file"> to upload file.
10
  */
11
  class RWMB_File_Field extends RWMB_Field {
12
- /**
13
- * Enqueue scripts and styles.
14
- */
15
  public static function admin_enqueue_scripts() {
16
- wp_enqueue_style( 'rwmb-file', RWMB_CSS_URL . 'file.css', array(), RWMB_VER );
17
- wp_enqueue_script( 'rwmb-file', RWMB_JS_URL . 'file.js', array( 'jquery-ui-sortable' ), RWMB_VER, true );
18
-
19
- RWMB_Helpers_Field::localize_script_once(
20
- 'rwmb-file',
21
- 'rwmbFile',
22
- array(
23
- // Translators: %d is the number of files in singular form.
24
- 'maxFileUploadsSingle' => __( 'You may only upload maximum %d file', 'meta-box' ),
25
- // Translators: %d is the number of files in plural form.
26
- 'maxFileUploadsPlural' => __( 'You may only upload maximum %d files', 'meta-box' ),
27
- )
28
- );
29
  }
30
 
31
- /**
32
- * Add custom actions.
33
- */
34
  public static function add_actions() {
35
- add_action( 'post_edit_form_tag', array( __CLASS__, 'post_edit_form_tag' ) );
36
- add_action( 'wp_ajax_rwmb_delete_file', array( __CLASS__, 'ajax_delete_file' ) );
37
  }
38
 
39
- /**
40
- * Add data encoding type for file uploading
41
- */
42
- public static function post_edit_form_tag() {
43
  echo ' enctype="multipart/form-data"';
44
  }
45
 
46
- /**
47
- * Ajax callback for deleting files.
48
- */
49
  public static function ajax_delete_file() {
50
- $request = rwmb_request();
51
  $field_id = (string) $request->filter_post( 'field_id' );
52
- $type = false !== strpos( $request->filter_post( 'field_name' ), '[' ) ? 'child' : 'top';
53
  check_ajax_referer( "rwmb-delete-file_{$field_id}" );
54
 
55
  if ( 'child' === $type ) {
56
  $field_group = explode( '[', $request->filter_post( 'field_name' ) );
57
- $field_id = $field_group[0]; //this is top parent field_id
58
  }
59
  // Make sure the file to delete is in the custom field.
60
  $attachment = $request->post( 'attachment_id' );
61
  $object_id = $request->filter_post( 'object_id' );
62
  $object_type = (string) $request->filter_post( 'object_type' );
63
- $field = rwmb_get_field_settings( $field_id, array( 'object_type' => $object_type ), $object_id );
64
  $field_value = self::raw_meta( $object_id, $field );
65
 
66
  if ( ! self::in_array_r( $attachment, $field_value ) ) {
@@ -82,10 +60,8 @@ class RWMB_File_Field extends RWMB_Field {
82
 
83
  /**
84
  * Recursively search needle in haystack
85
- *
86
- * @return boolean
87
  */
88
- protected static function in_array_r( $needle, $haystack, $strict = false ) {
89
  foreach ( $haystack as $item ) {
90
  if ( ( $strict ? $item === $needle : $item == $needle ) || ( is_array( $item ) && self::in_array_r( $needle, $item, $strict ) ) ) {
91
  return true;
@@ -153,13 +129,13 @@ class RWMB_File_Field extends RWMB_Field {
153
  * @return string
154
  */
155
  protected static function get_uploaded_files( $files, $field ) {
156
- $delete_nonce = wp_create_nonce( "rwmb-delete-file_{$field['id']}" );
157
- $output = '';
158
 
159
  foreach ( (array) $files as $k => $file ) {
160
  // Ignore deleted files (if users accidentally deleted files or uses `force_delete` without saving post).
161
  if ( get_attached_file( $file ) || $field['upload_dir'] ) {
162
- $output .= self::call( $field, 'file_html', $file, $k );
163
  }
164
  }
165
 
@@ -196,7 +172,7 @@ class RWMB_File_Field extends RWMB_Field {
196
  $data = self::file_info_custom_dir( $file, $field );
197
  } else {
198
  $data = [
199
- 'icon' => wp_get_attachment_image( $file, [48, 64], true ),
200
  'name' => basename( get_attached_file( $file ) ),
201
  'url' => wp_get_attachment_url( $file ),
202
  'title' => get_the_title( $file ),
@@ -234,25 +210,18 @@ class RWMB_File_Field extends RWMB_Field {
234
  );
235
  }
236
 
237
- /**
238
- * Get file data uploaded to custom directory.
239
- *
240
- * @param string $file URL to uploaded file.
241
- * @param array $field Field settings.
242
- * @return string
243
- */
244
- protected static function file_info_custom_dir( $file, $field ) {
245
  $path = wp_normalize_path( trailingslashit( $field['upload_dir'] ) . basename( $file ) );
246
  $ext = pathinfo( $path, PATHINFO_EXTENSION );
247
  $icon_url = wp_mime_type_icon( wp_ext2type( $ext ) );
248
- $data = array(
249
  'icon' => '<img width="48" height="64" src="' . esc_url( $icon_url ) . '" alt="">',
250
  'name' => basename( $path ),
251
  'path' => $path,
252
  'url' => $file,
253
  'title' => preg_replace( '/\.[^.]+$/', '', basename( $path ) ),
254
  'edit_link' => '',
255
- );
256
  return $data;
257
  }
258
 
@@ -267,7 +236,7 @@ class RWMB_File_Field extends RWMB_Field {
267
  * @return array|mixed
268
  */
269
  public static function value( $new, $old, $post_id, $field ) {
270
- $input = isset( $field['index'] ) ? $field['index'] : $field['input_name'];
271
 
272
  // @codingStandardsIgnoreLine
273
  if ( empty( $input ) || empty( $_FILES[ $input ] ) ) {
@@ -304,13 +273,12 @@ class RWMB_File_Field extends RWMB_Field {
304
  $data_source = $_POST;
305
  }
306
 
307
- // @codingStandardsIgnoreLine
308
- $indexes = isset( $data_source[ "_index_{$field['id']}" ] ) ? $data_source[ "_index_{$field['id']}" ] : array();
309
  foreach ( $indexes as $key => $index ) {
310
  $field['index'] = $index;
311
 
312
- $old_value = isset( $old[ $key ] ) ? $old[ $key ] : array();
313
- $value = isset( $new[ $key ] ) ? $new[ $key ] : array();
314
  $value = self::value( $value, $old_value, $object_id, $field );
315
  $new[ $key ] = self::filter( 'sanitize', $value, $field, $old_value, $object_id );
316
  }
@@ -345,7 +313,7 @@ class RWMB_File_Field extends RWMB_Field {
345
  foreach ( $list as $index => $value ) {
346
  $file_key = "{$input_name}_{$index}";
347
  if ( ! isset( $_FILES[ $file_key ] ) ) {
348
- $_FILES[ $file_key ] = array();
349
  }
350
  $_FILES[ $file_key ][ $key ] = $value;
351
  }
@@ -388,14 +356,14 @@ class RWMB_File_Field extends RWMB_Field {
388
  *
389
  * @return mixed Full info of uploaded files
390
  */
391
- public static function get_value( $field, $args = array(), $post_id = null ) {
392
  $value = parent::get_value( $field, $args, $post_id );
393
  if ( ! $field['clone'] ) {
394
- $value = self::call( 'files_info', $field, $value, $args );
395
  } else {
396
- $return = array();
397
  foreach ( $value as $subvalue ) {
398
- $return[] = self::call( 'files_info', $field, $subvalue, $args );
399
  }
400
  $value = $return;
401
  }
@@ -414,9 +382,9 @@ class RWMB_File_Field extends RWMB_Field {
414
  * @return array
415
  */
416
  public static function files_info( $field, $files, $args ) {
417
- $return = array();
418
  foreach ( (array) $files as $file ) {
419
- $info = self::call( $field, 'file_info', $file, $args );
420
  if ( $info ) {
421
  $return[ $file ] = $info;
422
  }
@@ -433,8 +401,8 @@ class RWMB_File_Field extends RWMB_Field {
433
  *
434
  * @return array|bool False if file not found. Array of (id, name, path, url) on success.
435
  */
436
- public static function file_info( $file, $args = array(), $field = array() ) {
437
- if ( $field['upload_dir'] ) {
438
  return self::file_info_custom_dir( $file, $field );
439
  }
440
 
@@ -444,13 +412,13 @@ class RWMB_File_Field extends RWMB_Field {
444
  }
445
 
446
  return wp_parse_args(
447
- array(
448
  'ID' => $file,
449
  'name' => basename( $path ),
450
  'path' => $path,
451
  'url' => wp_get_attachment_url( $file ),
452
  'title' => get_the_title( $file ),
453
- ),
454
  wp_get_attachment_metadata( $file )
455
  );
456
  }
@@ -514,13 +482,7 @@ class RWMB_File_Field extends RWMB_Field {
514
  return empty( $file_info['url'] ) ? null : $file_info['url'];
515
  }
516
 
517
- /**
518
- * Convert a path to an URL.
519
- *
520
- * @param string $path Full path to a file or a directory.
521
- * @return string URL to the file or directory.
522
- */
523
- public static function convert_path_to_url( $path ) {
524
  $path = wp_normalize_path( untrailingslashit( $path ) );
525
  $root = wp_normalize_path( untrailingslashit( ABSPATH ) );
526
  $relative_path = str_replace( $root, '', $path );
1
  <?php
2
  /**
3
  * The file upload file which allows users to upload files via the default HTML <input type="file">.
 
 
 
 
 
 
4
  */
5
  class RWMB_File_Field extends RWMB_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
+ wp_enqueue_style( 'rwmb-file', RWMB_CSS_URL . 'file.css', [], RWMB_VER );
8
+ wp_enqueue_script( 'rwmb-file', RWMB_JS_URL . 'file.js', [ 'jquery-ui-sortable' ], RWMB_VER, true );
9
+
10
+ RWMB_Helpers_Field::localize_script_once( 'rwmb-file', 'rwmbFile', [
11
+ // Translators: %d is the number of files in singular form.
12
+ 'maxFileUploadsSingle' => __( 'You may only upload maximum %d file', 'meta-box' ),
13
+ // Translators: %d is the number of files in plural form.
14
+ 'maxFileUploadsPlural' => __( 'You may only upload maximum %d files', 'meta-box' ),
15
+ ] );
 
 
 
 
16
  }
17
 
 
 
 
18
  public static function add_actions() {
19
+ add_action( 'post_edit_form_tag', [ __CLASS__, 'add_form_enctype' ] );
20
+ add_action( 'wp_ajax_rwmb_delete_file', [ __CLASS__, 'ajax_delete_file' ] );
21
  }
22
 
23
+ public static function add_form_enctype() {
 
 
 
24
  echo ' enctype="multipart/form-data"';
25
  }
26
 
 
 
 
27
  public static function ajax_delete_file() {
28
+ $request = rwmb_request();
29
  $field_id = (string) $request->filter_post( 'field_id' );
30
+ $type = false !== strpos( $request->filter_post( 'field_name' ), '[' ) ? 'child' : 'top';
31
  check_ajax_referer( "rwmb-delete-file_{$field_id}" );
32
 
33
  if ( 'child' === $type ) {
34
  $field_group = explode( '[', $request->filter_post( 'field_name' ) );
35
+ $field_id = $field_group[0]; // This is top parent field_id.
36
  }
37
  // Make sure the file to delete is in the custom field.
38
  $attachment = $request->post( 'attachment_id' );
39
  $object_id = $request->filter_post( 'object_id' );
40
  $object_type = (string) $request->filter_post( 'object_type' );
41
+ $field = rwmb_get_field_settings( $field_id, [ 'object_type' => $object_type ], $object_id );
42
  $field_value = self::raw_meta( $object_id, $field );
43
 
44
  if ( ! self::in_array_r( $attachment, $field_value ) ) {
60
 
61
  /**
62
  * Recursively search needle in haystack
 
 
63
  */
64
+ protected static function in_array_r( $needle, $haystack, $strict = false ) : bool {
65
  foreach ( $haystack as $item ) {
66
  if ( ( $strict ? $item === $needle : $item == $needle ) || ( is_array( $item ) && self::in_array_r( $needle, $item, $strict ) ) ) {
67
  return true;
129
  * @return string
130
  */
131
  protected static function get_uploaded_files( $files, $field ) {
132
+ $delete_nonce = wp_create_nonce( "rwmb-delete-file_{$field['id']}" );
133
+ $output = '';
134
 
135
  foreach ( (array) $files as $k => $file ) {
136
  // Ignore deleted files (if users accidentally deleted files or uses `force_delete` without saving post).
137
  if ( get_attached_file( $file ) || $field['upload_dir'] ) {
138
+ $output .= static::file_html( $file, $k, $field );
139
  }
140
  }
141
 
172
  $data = self::file_info_custom_dir( $file, $field );
173
  } else {
174
  $data = [
175
+ 'icon' => wp_get_attachment_image( $file, [ 48, 64 ], true ),
176
  'name' => basename( get_attached_file( $file ) ),
177
  'url' => wp_get_attachment_url( $file ),
178
  'title' => get_the_title( $file ),
210
  );
211
  }
212
 
213
+ protected static function file_info_custom_dir( string $file, array $field ) : array {
 
 
 
 
 
 
 
214
  $path = wp_normalize_path( trailingslashit( $field['upload_dir'] ) . basename( $file ) );
215
  $ext = pathinfo( $path, PATHINFO_EXTENSION );
216
  $icon_url = wp_mime_type_icon( wp_ext2type( $ext ) );
217
+ $data = [
218
  'icon' => '<img width="48" height="64" src="' . esc_url( $icon_url ) . '" alt="">',
219
  'name' => basename( $path ),
220
  'path' => $path,
221
  'url' => $file,
222
  'title' => preg_replace( '/\.[^.]+$/', '', basename( $path ) ),
223
  'edit_link' => '',
224
+ ];
225
  return $data;
226
  }
227
 
236
  * @return array|mixed
237
  */
238
  public static function value( $new, $old, $post_id, $field ) {
239
+ $input = $field['index'] ?? $field['input_name'];
240
 
241
  // @codingStandardsIgnoreLine
242
  if ( empty( $input ) || empty( $_FILES[ $input ] ) ) {
273
  $data_source = $_POST;
274
  }
275
 
276
+ $indexes = $data_source[ "_index_{$field['id']}" ] ?? [];
 
277
  foreach ( $indexes as $key => $index ) {
278
  $field['index'] = $index;
279
 
280
+ $old_value = $old[ $key ] ?? [];
281
+ $value = $new[ $key ] ?? [];
282
  $value = self::value( $value, $old_value, $object_id, $field );
283
  $new[ $key ] = self::filter( 'sanitize', $value, $field, $old_value, $object_id );
284
  }
313
  foreach ( $list as $index => $value ) {
314
  $file_key = "{$input_name}_{$index}";
315
  if ( ! isset( $_FILES[ $file_key ] ) ) {
316
+ $_FILES[ $file_key ] = [];
317
  }
318
  $_FILES[ $file_key ][ $key ] = $value;
319
  }
356
  *
357
  * @return mixed Full info of uploaded files
358
  */
359
+ public static function get_value( $field, $args = [], $post_id = null ) {
360
  $value = parent::get_value( $field, $args, $post_id );
361
  if ( ! $field['clone'] ) {
362
+ $value = static::files_info( $field, $value, $args );
363
  } else {
364
+ $return = [];
365
  foreach ( $value as $subvalue ) {
366
+ $return[] = static::files_info( $field, $subvalue, $args );
367
  }
368
  $value = $return;
369
  }
382
  * @return array
383
  */
384
  public static function files_info( $field, $files, $args ) {
385
+ $return = [];
386
  foreach ( (array) $files as $file ) {
387
+ $info = static::file_info( $file, $args, $field );
388
  if ( $info ) {
389
  $return[ $file ] = $info;
390
  }
401
  *
402
  * @return array|bool False if file not found. Array of (id, name, path, url) on success.
403
  */
404
+ public static function file_info( $file, $args = [], $field = [] ) {
405
+ if ( ! empty( $field['upload_dir'] ) ) {
406
  return self::file_info_custom_dir( $file, $field );
407
  }
408
 
412
  }
413
 
414
  return wp_parse_args(
415
+ [
416
  'ID' => $file,
417
  'name' => basename( $path ),
418
  'path' => $path,
419
  'url' => wp_get_attachment_url( $file ),
420
  'title' => get_the_title( $file ),
421
+ ],
422
  wp_get_attachment_metadata( $file )
423
  );
424
  }
482
  return empty( $file_info['url'] ) ? null : $file_info['url'];
483
  }
484
 
485
+ public static function convert_path_to_url( string $path ) : string {
 
 
 
 
 
 
486
  $path = wp_normalize_path( untrailingslashit( $path ) );
487
  $root = wp_normalize_path( untrailingslashit( ABSPATH ) );
488
  $relative_path = str_replace( $root, '', $path );
inc/fields/heading.php CHANGED
@@ -1,19 +1,10 @@
1
  <?php
2
  /**
3
  * The heading field which displays a simple heading text.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Heading field class.
10
  */
11
  class RWMB_Heading_Field extends RWMB_Field {
12
- /**
13
- * Enqueue scripts and styles.
14
- */
15
  public static function admin_enqueue_scripts() {
16
- wp_enqueue_style( 'rwmb-heading', RWMB_CSS_URL . 'heading.css', array(), RWMB_VER );
17
  }
18
 
19
  /**
@@ -31,13 +22,8 @@ class RWMB_Heading_Field extends RWMB_Field {
31
 
32
  /**
33
  * Show end HTML markup for fields.
34
- *
35
- * @param mixed $meta Meta value.
36
- * @param array $field Field parameters.
37
- *
38
- * @return string
39
  */
40
- public static function end_html( $meta, $field ) {
41
  return self::input_description( $field );
42
  }
43
  }
1
  <?php
2
  /**
3
  * The heading field which displays a simple heading text.
 
 
 
 
 
 
4
  */
5
  class RWMB_Heading_Field extends RWMB_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
+ wp_enqueue_style( 'rwmb-heading', RWMB_CSS_URL . 'heading.css', [], RWMB_VER );
8
  }
9
 
10
  /**
22
 
23
  /**
24
  * Show end HTML markup for fields.
 
 
 
 
 
25
  */
26
+ public static function end_html( array $field ) : string {
27
  return self::input_description( $field );
28
  }
29
  }
inc/fields/input-list.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
  /**
3
  * The input list field which displays choices in a list of inputs.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Input list field class.
10
  */
11
  class RWMB_Input_List_Field extends RWMB_Choice_Field {
12
- /**
13
- * Enqueue scripts and styles
14
- */
15
  public static function admin_enqueue_scripts() {
16
- wp_enqueue_style( 'rwmb-input-list', RWMB_CSS_URL . 'input-list.css', array(), RWMB_VER );
17
- wp_enqueue_script( 'rwmb-input-list', RWMB_JS_URL . 'input-list.js', array(), RWMB_VER, true );
18
  }
19
 
20
  /**
@@ -29,12 +20,12 @@ class RWMB_Input_List_Field extends RWMB_Choice_Field {
29
  $walker = new RWMB_Walker_Input_List( $field, $meta );
30
  $output = self::get_select_all_html( $field );
31
  $output .= sprintf(
32
- '<ul class="rwmb-input-list%s%s">',
33
  $field['collapse'] ? ' rwmb-collapse' : '',
34
  $field['inline'] ? ' rwmb-inline' : ''
35
  );
36
  $output .= $walker->walk( $options, $field['flatten'] ? -1 : 0 );
37
- $output .= '</ul>';
38
 
39
  return $output;
40
  }
@@ -49,14 +40,11 @@ class RWMB_Input_List_Field extends RWMB_Choice_Field {
49
  $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field;
50
  $field = RWMB_Input_Field::normalize( $field );
51
  $field = parent::normalize( $field );
52
- $field = wp_parse_args(
53
- $field,
54
- array(
55
- 'collapse' => true,
56
- 'inline' => null,
57
- 'select_all_none' => false,
58
- )
59
- );
60
 
61
  $field['flatten'] = $field['multiple'] ? $field['flatten'] : true;
62
  $field['inline'] = ! $field['multiple'] && ! isset( $field['inline'] ) ? true : $field['inline'];
1
  <?php
2
  /**
3
  * The input list field which displays choices in a list of inputs.
 
 
 
 
 
 
4
  */
5
  class RWMB_Input_List_Field extends RWMB_Choice_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
+ wp_enqueue_style( 'rwmb-input-list', RWMB_CSS_URL . 'input-list.css', [], RWMB_VER );
8
+ wp_enqueue_script( 'rwmb-input-list', RWMB_JS_URL . 'input-list.js', [], RWMB_VER, true );
9
  }
10
 
11
  /**
20
  $walker = new RWMB_Walker_Input_List( $field, $meta );
21
  $output = self::get_select_all_html( $field );
22
  $output .= sprintf(
23
+ '<fieldset class="rwmb-input-list%s%s">',
24
  $field['collapse'] ? ' rwmb-collapse' : '',
25
  $field['inline'] ? ' rwmb-inline' : ''
26
  );
27
  $output .= $walker->walk( $options, $field['flatten'] ? -1 : 0 );
28
+ $output .= '</fieldset>';
29
 
30
  return $output;
31
  }
40
  $field = $field['multiple'] ? RWMB_Multiple_Values_Field::normalize( $field ) : $field;
41
  $field = RWMB_Input_Field::normalize( $field );
42
  $field = parent::normalize( $field );
43
+ $field = wp_parse_args( $field, [
44
+ 'collapse' => true,
45
+ 'inline' => null,
46
+ 'select_all_none' => false,
47
+ ] );
 
 
 
48
 
49
  $field['flatten'] = $field['multiple'] ? $field['flatten'] : true;
50
  $field['inline'] = ! $field['multiple'] && ! isset( $field['inline'] ) ? true : $field['inline'];
inc/fields/input.php CHANGED
@@ -1,17 +1,8 @@
1
  <?php
2
  /**
3
  * The abstract input field which is used for all <input> fields.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Abstract input field class.
10
  */
11
  abstract class RWMB_Input_Field extends RWMB_Field {
12
- /**
13
- * Enqueue scripts and styles.
14
- */
15
  public static function admin_enqueue_scripts() {
16
  wp_enqueue_style( 'rwmb-input', RWMB_CSS_URL . 'input.css', '', RWMB_VER );
17
  }
@@ -34,11 +25,11 @@ abstract class RWMB_Input_Field extends RWMB_Field {
34
  $output .= '<span class="rwmb-input-group-text">' . $field['prepend'] . '</span>';
35
  }
36
 
37
- $attributes = self::call( 'get_attributes', $field, $meta );
38
  $output .= sprintf( '<input %s>%s', self::render_attributes( $attributes ), self::datalist( $field ) );
39
 
40
  if ( $field['append'] ) {
41
- $output .= '<span class="rwmb-input-group-text">' . $field['append']. '</span>';
42
  }
43
 
44
  if ( $field['prepend'] || $field['append'] ) {
@@ -56,27 +47,21 @@ abstract class RWMB_Input_Field extends RWMB_Field {
56
  */
57
  public static function normalize( $field ) {
58
  $field = parent::normalize( $field );
59
- $field = wp_parse_args(
60
- $field,
61
- array(
62
- 'autocomplete' => false,
63
- 'datalist' => false,
64
- 'readonly' => false,
65
- 'maxlength' => false,
66
- 'minlength' => false,
67
- 'pattern' => false,
68
- 'prepend' => '',
69
- 'append' => '',
70
- )
71
- );
72
  if ( $field['datalist'] ) {
73
- $field['datalist'] = wp_parse_args(
74
- $field['datalist'],
75
- array(
76
- 'id' => $field['id'] . '_list',
77
- 'options' => array(),
78
- )
79
- );
80
  }
81
  return $field;
82
  }
@@ -90,20 +75,17 @@ abstract class RWMB_Input_Field extends RWMB_Field {
90
  */
91
  public static function get_attributes( $field, $value = null ) {
92
  $attributes = parent::get_attributes( $field, $value );
93
- $attributes = wp_parse_args(
94
- $attributes,
95
- array(
96
- 'autocomplete' => $field['autocomplete'],
97
- 'list' => $field['datalist'] ? $field['datalist']['id'] : false,
98
- 'readonly' => $field['readonly'],
99
- 'maxlength' => $field['maxlength'],
100
- 'minlength' => $field['minlength'],
101
- 'pattern' => $field['pattern'],
102
- 'value' => $value,
103
- 'placeholder' => $field['placeholder'],
104
- 'type' => $field['type'],
105
- )
106
- );
107
  if ( isset( $field['size'] ) ) {
108
  $attributes['size'] = $field['size'];
109
  }
@@ -111,13 +93,7 @@ abstract class RWMB_Input_Field extends RWMB_Field {
111
  return $attributes;
112
  }
113
 
114
- /**
115
- * Create datalist, if any.
116
- *
117
- * @param array $field Field parameters.
118
- * @return string
119
- */
120
- protected static function datalist( $field ) {
121
  if ( empty( $field['datalist'] ) ) {
122
  return '';
123
  }
1
  <?php
2
  /**
3
  * The abstract input field which is used for all <input> fields.
 
 
 
 
 
 
4
  */
5
  abstract class RWMB_Input_Field extends RWMB_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
  wp_enqueue_style( 'rwmb-input', RWMB_CSS_URL . 'input.css', '', RWMB_VER );
8
  }
25
  $output .= '<span class="rwmb-input-group-text">' . $field['prepend'] . '</span>';
26
  }
27
 
28
+ $attributes = static::get_attributes( $field, $meta );
29
  $output .= sprintf( '<input %s>%s', self::render_attributes( $attributes ), self::datalist( $field ) );
30
 
31
  if ( $field['append'] ) {
32
+ $output .= '<span class="rwmb-input-group-text">' . $field['append'] . '</span>';
33
  }
34
 
35
  if ( $field['prepend'] || $field['append'] ) {
47
  */
48
  public static function normalize( $field ) {
49
  $field = parent::normalize( $field );
50
+ $field = wp_parse_args( $field, [
51
+ 'autocomplete' => false,
52
+ 'datalist' => false,
53
+ 'readonly' => false,
54
+ 'maxlength' => false,
55
+ 'minlength' => false,
56
+ 'pattern' => false,
57
+ 'prepend' => '',
58
+ 'append' => '',
59
+ ] );
 
 
 
60
  if ( $field['datalist'] ) {
61
+ $field['datalist'] = wp_parse_args( $field['datalist'], [
62
+ 'id' => $field['id'] . '_list',
63
+ 'options' => [],
64
+ ] );
 
 
 
65
  }
66
  return $field;
67
  }
75
  */
76
  public static function get_attributes( $field, $value = null ) {
77
  $attributes = parent::get_attributes( $field, $value );
78
+ $attributes = wp_parse_args( $attributes, [
79
+ 'autocomplete' => $field['autocomplete'],
80
+ 'list' => $field['datalist'] ? $field['datalist']['id'] : false,
81
+ 'readonly' => $field['readonly'],
82
+ 'maxlength' => $field['maxlength'],
83
+ 'minlength' => $field['minlength'],
84
+ 'pattern' => $field['pattern'],
85
+ 'value' => $value,
86
+ 'placeholder' => $field['placeholder'],
87
+ 'type' => $field['type'],
88
+ ] );
 
 
 
89
  if ( isset( $field['size'] ) ) {
90
  $attributes['size'] = $field['size'];
91
  }
93
  return $attributes;
94
  }
95
 
96
+ protected static function datalist( array $field ) : string {
 
 
 
 
 
 
97
  if ( empty( $field['datalist'] ) ) {
98
  return '';
99
  }
inc/fields/media.php CHANGED
@@ -1,54 +1,36 @@
1
  <?php
2
  /**
3
  * Media field class which users WordPress media popup to upload and select files.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * The media field class.
10
  */
11
  class RWMB_Media_Field extends RWMB_File_Field {
12
- /**
13
- * Enqueue scripts and styles.
14
- */
15
  public static function admin_enqueue_scripts() {
16
  parent::admin_enqueue_scripts();
17
 
18
  wp_enqueue_media();
19
  if ( ! is_admin() ) {
20
- wp_register_script( 'media-grid', includes_url( 'js/media-grid.min.js' ), array( 'media-editor' ), '4.9.7', true );
21
  }
22
- wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', array(), RWMB_VER );
23
- wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', array( 'jquery-ui-sortable', 'underscore', 'backbone', 'media-grid' ), RWMB_VER, true );
24
-
25
- RWMB_Helpers_Field::localize_script_once(
26
- 'rwmb-media',
27
- 'i18nRwmbMedia',
28
- array(
29
- 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ),
30
- 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ),
31
- 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ),
32
- 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ),
33
- 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ),
34
- 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ),
35
- 'noTitle' => _x( 'No Title', 'media', 'meta-box' ),
36
- 'loadingUrl' => admin_url( 'images/spinner.gif' ),
37
- 'extensions' => self::get_mime_extensions(),
38
- 'select' => apply_filters( 'rwmb_media_select_string', _x( 'Select Files', 'media', 'meta-box' ) ),
39
- 'or' => apply_filters( 'rwmb_media_or_string', _x( 'or', 'media', 'meta-box' ) ),
40
- 'uploadInstructions' => apply_filters( 'rwmb_media_upload_instructions_string', _x( 'Drop files here to upload', 'media', 'meta-box' ) ),
41
- )
42
- );
43
  }
44
 
45
- /**
46
- * Add actions.
47
- */
48
  public static function add_actions() {
49
- $args = func_get_args();
50
- $field = reset( $args );
51
- add_action( 'print_media_templates', array( RWMB_Helpers_Field::get_class( $field ), 'print_templates' ) );
52
  }
53
 
54
  /**
@@ -89,7 +71,7 @@ class RWMB_Media_Field extends RWMB_File_Field {
89
  * @return string
90
  */
91
  public static function html( $meta, $field ) {
92
- $attributes = self::call( 'get_attributes', $field, $meta );
93
 
94
  $html = sprintf(
95
  '<input %s data-options="%s">',
@@ -109,29 +91,23 @@ class RWMB_Media_Field extends RWMB_File_Field {
109
  */
110
  public static function normalize( $field ) {
111
  $field = parent::normalize( $field );
112
- $field = wp_parse_args(
113
- $field,
114
- array(
115
- 'std' => array(),
116
- 'mime_type' => '',
117
- 'max_file_uploads' => 0,
118
- 'force_delete' => false,
119
- 'max_status' => true,
120
- 'js_options' => array(),
121
- 'add_to' => 'end',
122
- )
123
- );
124
-
125
- $field['js_options'] = wp_parse_args(
126
- $field['js_options'],
127
- array(
128
- 'mimeType' => $field['mime_type'],
129
- 'maxFiles' => $field['max_file_uploads'],
130
- 'forceDelete' => $field['force_delete'] ? true : false,
131
- 'maxStatus' => $field['max_status'],
132
- 'addTo' => $field['add_to'],
133
- )
134
- );
135
 
136
  $field['multiple'] = true;
137
 
@@ -157,10 +133,10 @@ class RWMB_Media_Field extends RWMB_File_Field {
157
  $attributes['class'] .= ' rwmb-media';
158
 
159
  // Add attachment details.
160
- $attachments = array();
161
  foreach ( $value as $media ) {
162
  $media = wp_prepare_attachment_for_js( $media );
163
- // Some themes/plugins add HTML, shortcodes to "compat" attrbute which break JSON validity.
164
  if ( isset( $media['compat'] ) ) {
165
  unset( $media['compat'] );
166
  }
@@ -169,26 +145,21 @@ class RWMB_Media_Field extends RWMB_File_Field {
169
  }
170
  }
171
  $attachments = array_values( $attachments );
172
- $attributes['data-attachments'] = json_encode( $attachments );
173
 
174
  return $attributes;
175
  }
176
 
177
- /**
178
- * Get supported mime extensions.
179
- *
180
- * @return array
181
- */
182
- protected static function get_mime_extensions() {
183
  $mime_types = wp_get_mime_types();
184
- $extensions = array();
185
  foreach ( $mime_types as $ext => $mime ) {
186
  $ext = explode( '|', $ext );
187
  $extensions[ $mime ] = $ext;
188
 
189
  $mime_parts = explode( '/', $mime );
190
  if ( empty( $extensions[ $mime_parts[0] ] ) ) {
191
- $extensions[ $mime_parts[0] ] = array();
192
  }
193
  $extensions[ $mime_parts[0] ] = array_merge( $extensions[ $mime_parts[0] ], $ext );
194
  $extensions[ $mime_parts[0] . '/*' ] = $extensions[ $mime_parts[0] ];
@@ -209,7 +180,14 @@ class RWMB_Media_Field extends RWMB_File_Field {
209
  */
210
  public static function value( $new, $old, $post_id, $field ) {
211
  $new = RWMB_Helpers_Array::from_csv( $new );
212
- return array_filter( array_unique( array_map( 'absint', $new ) ) );
 
 
 
 
 
 
 
213
  }
214
 
215
  /**
@@ -226,7 +204,7 @@ class RWMB_Media_Field extends RWMB_File_Field {
226
  }
227
  $storage = $field['storage'];
228
  $storage->delete( $post_id, $field['id'] );
229
- parent::save( $new, array(), $post_id, $field );
230
  }
231
 
232
  /**
1
  <?php
2
  /**
3
  * Media field class which users WordPress media popup to upload and select files.
 
 
 
 
 
 
4
  */
5
  class RWMB_Media_Field extends RWMB_File_Field {
 
 
 
6
  public static function admin_enqueue_scripts() {
7
  parent::admin_enqueue_scripts();
8
 
9
  wp_enqueue_media();
10
  if ( ! is_admin() ) {
11
+ wp_register_script( 'media-grid', includes_url( 'js/media-grid.min.js' ), [ 'media-editor' ], '4.9.7', true );
12
  }
13
+ wp_enqueue_style( 'rwmb-media', RWMB_CSS_URL . 'media.css', [], RWMB_VER );
14
+ wp_enqueue_script( 'rwmb-media', RWMB_JS_URL . 'media.js', [ 'jquery-ui-sortable', 'underscore', 'backbone', 'media-grid' ], RWMB_VER, true );
15
+
16
+ RWMB_Helpers_Field::localize_script_once( 'rwmb-media', 'i18nRwmbMedia', [
17
+ 'add' => apply_filters( 'rwmb_media_add_string', _x( '+ Add Media', 'media', 'meta-box' ) ),
18
+ 'single' => apply_filters( 'rwmb_media_single_files_string', _x( ' file', 'media', 'meta-box' ) ),
19
+ 'multiple' => apply_filters( 'rwmb_media_multiple_files_string', _x( ' files', 'media', 'meta-box' ) ),
20
+ 'remove' => apply_filters( 'rwmb_media_remove_string', _x( 'Remove', 'media', 'meta-box' ) ),
21
+ 'edit' => apply_filters( 'rwmb_media_edit_string', _x( 'Edit', 'media', 'meta-box' ) ),
22
+ 'view' => apply_filters( 'rwmb_media_view_string', _x( 'View', 'media', 'meta-box' ) ),
23
+ 'noTitle' => _x( 'No Title', 'media', 'meta-box' ),
24
+ 'loadingUrl' => admin_url( 'images/spinner.gif' ),
25
+ 'extensions' => static::get_mime_extensions(),
26
+ 'select' => apply_filters( 'rwmb_media_select_string', _x( 'Select Files', 'media', 'meta-box' ) ),
27
+ 'or' => apply_filters( 'rwmb_media_or_string', _x( 'or', 'media', 'meta-box' ) ),
28
+ 'uploadInstructions' => apply_filters( 'rwmb_media_upload_instructions_string', _x( 'Drop files here to upload', 'media', 'meta-box' ) ),
29
+ ] );
 
 
 
 
30
  }
31
 
 
 
 
32
  public static function add_actions() {
33
+ add_action( 'print_media_templates', [ get_called_class(), 'print_templates' ] );
 
 
34
  }
35
 
36
  /**
71
  * @return string
72
  */
73
  public static function html( $meta, $field ) {
74
+ $attributes = static::get_attributes( $field, $meta );
75
 
76
  $html = sprintf(
77
  '<input %s data-options="%s">',
91
  */
92
  public static function normalize( $field ) {
93
  $field = parent::normalize( $field );
94
+ $field = wp_parse_args( $field, [
95
+ 'std' => [],
96
+ 'mime_type' => '',
97
+ 'max_file_uploads' => 0,
98
+ 'force_delete' => false,
99
+ 'max_status' => true,
100
+ 'js_options' => [],
101
+ 'add_to' => 'end',
102
+ ] );
103
+
104
+ $field['js_options'] = wp_parse_args( $field['js_options'], [
105
+ 'mimeType' => $field['mime_type'],
106
+ 'maxFiles' => $field['max_file_uploads'],
107
+ 'forceDelete' => $field['force_delete'],
108
+ 'maxStatus' => $field['max_status'],
109
+ 'addTo' => $field['add_to'],
110
+ ] );
 
 
 
 
 
 
111
 
112
  $field['multiple'] = true;
113
 
133
  $attributes['class'] .= ' rwmb-media';
134
 
135
  // Add attachment details.
136
+ $attachments = [];
137
  foreach ( $value as $media ) {
138
  $media = wp_prepare_attachment_for_js( $media );
139
+ // Some themes/plugins add HTML, shortcodes to "compat" attribute which break JSON validity.
140
  if ( isset( $media['compat'] ) ) {
141
  unset( $media['compat'] );
142
  }
145
  }
146
  }
147
  $attachments = array_values( $attachments );
148
+ $attributes['data-attachments'] = wp_json_encode( $attachments );
149
 
150
  return $attributes;
151
  }
152
 
153
+ protected static function get_mime_extensions() : array {
 
 
 
 
 
154
  $mime_types = wp_get_mime_types();
155
+ $extensions = [];
156
  foreach ( $mime_types as $ext => $mime ) {
157
  $ext = explode( '|', $ext );
158
  $extensions[ $mime ] = $ext;
159
 
160
  $mime_parts = explode( '/', $mime );
161
  if ( empty( $extensions[ $mime_parts[0] ] ) ) {
162
+ $extensions[ $mime_parts[0] ] = [];
163
  }
164
  $extensions[ $mime_parts[0] ] = array_merge( $extensions[ $mime_parts[0] ], $ext );
165
  $extensions[ $mime_parts[0] . '/*' ] = $extensions[ $mime_parts[0] ];
180
  */
181
  public static function value( $new, $old, $post_id, $field ) {
182
  $new = RWMB_Helpers_Array::from_csv( $new );
183
+ $new = array_filter( array_unique( array_map( 'absint', $new ) ) );
184
+
185
+ // Attach the uploaded images to the post if needed.
186
+ global $wpdb;
187
+ $ids = implode( ',', $new );
188
+ $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent=%d WHERE post_parent=0 AND ID IN ($ids)", $post_id ) );
189
+
190
+ return $new;
191
  }
192
 
193
  /**
204
  }
205
  $storage = $field['storage'];
206
  $storage->delete( $post_id, $field['id'] );
207
+ parent::save( $new, [], $post_id, $field );
208
  }
209
 
210
  /**
inc/fields/object-choice.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
- * The object choice class which allows users to select specific objects in WordPress.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Abstract field to select an object: post, user, taxonomy, etc.
10
  */
11
  abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
12
  /**
@@ -19,17 +13,21 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
19
  */
20
  public static function show( $field, $saved, $post_id = 0 ) {
21
  // Get unique saved IDs for ajax fields.
22
- $meta = self::call( $field, 'meta', $post_id, $saved );
23
  $meta = self::filter( 'field_meta', $meta, $field, $saved );
24
  $meta = RWMB_Helpers_Array::flatten( (array) $meta );
25
  $meta = array_unique( array_filter( array_map( 'absint', $meta ) ) );
26
  sort( $meta );
27
 
28
- $field['options'] = self::call( $field, 'query', $meta );
29
 
30
  parent::show( $field, $saved, $post_id );
31
  }
32
 
 
 
 
 
33
  /**
34
  * Get field HTML.
35
  *
@@ -38,10 +36,10 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
38
  * @return string
39
  */
40
  public static function html( $meta, $field ) {
41
- $html = call_user_func( array( self::get_type_class( $field ), 'html' ), $meta, $field );
42
 
43
  if ( $field['add_new'] ) {
44
- $html .= self::call( 'add_new_form', $field );
45
  }
46
 
47
  return $html;
@@ -66,16 +64,13 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
66
  */
67
  public static function normalize( $field ) {
68
  $field = parent::normalize( $field );
69
- $field = wp_parse_args(
70
- $field,
71
- array(
72
- 'flatten' => true,
73
- 'query_args' => array(),
74
- 'field_type' => 'select_advanced',
75
- 'add_new' => false,
76
- 'ajax' => true,
77
- )
78
- );
79
  if ( 'select_advanced' !== $field['field_type'] ) {
80
  $field['ajax'] = false;
81
  }
@@ -86,7 +81,7 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
86
  if ( 'radio_list' === $field['field_type'] ) {
87
  $field['field_type'] = 'radio';
88
  }
89
- $field = call_user_func( array( self::get_type_class( $field ), 'normalize' ), $field );
90
 
91
  return $field;
92
  }
@@ -102,22 +97,22 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
102
  }
103
 
104
  if ( empty( $field['js_options']['ajax'] ) ) {
105
- $field['js_options']['ajax'] = array();
106
  }
107
  $field['js_options']['ajax'] = wp_parse_args(
108
- array(
109
  'url' => admin_url( 'admin-ajax.php' ),
110
- ),
111
  $field['js_options']['ajax']
112
  );
113
- $field['js_options']['ajax_data'] = array(
114
- 'field' => array(
115
  'id' => $field['id'],
116
  'type' => $field['type'],
117
  'query_args' => $field['query_args'],
118
- ),
119
  '_wpnonce' => wp_create_nonce( 'query' ),
120
- );
121
  }
122
 
123
  /**
@@ -129,7 +124,7 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
129
  * @return array
130
  */
131
  public static function get_attributes( $field, $value = null ) {
132
- $attributes = call_user_func( array( self::get_type_class( $field ), 'get_attributes' ), $field, $value );
133
  if ( 'select_advanced' === $field['field_type'] ) {
134
  $attributes['class'] .= ' rwmb-select_advanced';
135
  } elseif ( 'select' === $field['field_type'] ) {
@@ -138,9 +133,6 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
138
  return $attributes;
139
  }
140
 
141
- /**
142
- * Enqueue scripts and styles.
143
- */
144
  public static function admin_enqueue_scripts() {
145
  RWMB_Input_List_Field::admin_enqueue_scripts();
146
  RWMB_Select_Field::admin_enqueue_scripts();
@@ -150,15 +142,8 @@ abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
150
 
151
  /**
152
  * Get correct rendering class for the field.
153
- *
154
- * @param array $field Field parameters.
155
- * @return string
156
  */
157
- protected static function get_type_class( $field ) {
158
- return RWMB_Helpers_Field::get_class(
159
- array(
160
- 'type' => $field['field_type'],
161
- )
162
- );
163
  }
164
  }
1
  <?php
2
  /**
3
+ * The object choice class which allows users to select specific objects (post, user, taxonomy) in WordPress.
 
 
 
 
 
 
4
  */
5
  abstract class RWMB_Object_Choice_Field extends RWMB_Choice_Field {
6
  /**
13
  */
14
  public static function show( $field, $saved, $post_id = 0 ) {
15
  // Get unique saved IDs for ajax fields.
16
+ $meta = static::meta( $post_id, $saved, $field );
17
  $meta = self::filter( 'field_meta', $meta, $field, $saved );
18
  $meta = RWMB_Helpers_Array::flatten( (array) $meta );
19
  $meta = array_unique( array_filter( array_map( 'absint', $meta ) ) );
20
  sort( $meta );
21
 
22
+ $field['options'] = static::query( $meta, $field );
23
 
24
  parent::show( $field, $saved, $post_id );
25
  }
26
 
27
+ public static function query( $meta, $field ) {
28
+ return [];
29
+ }
30
+
31
  /**
32
  * Get field HTML.
33
  *
36
  * @return string
37
  */
38
  public static function html( $meta, $field ) {
39
+ $html = call_user_func( [ self::get_type_class( $field ), 'html' ], $meta, $field );
40
 
41
  if ( $field['add_new'] ) {
42
+ $html .= static::add_new_form( $field );
43
  }
44
 
45
  return $html;
64
  */
65
  public static function normalize( $field ) {
66
  $field = parent::normalize( $field );
67
+ $field = wp_parse_args( $field, [
68
+ 'flatten' => true,
69
+ 'query_args' => [],
70
+ 'field_type' => 'select_advanced',
71
+ 'add_new' => false,
72
+ 'ajax' => true,
73
+ ] );
 
 
 
74
  if ( 'select_advanced' !== $field['field_type'] ) {
75
  $field['ajax'] = false;
76
  }
81
  if ( 'radio_list' === $field['field_type'] ) {
82
  $field['field_type'] = 'radio';
83
  }
84
+ $field = call_user_func( [ self::get_type_class( $field ), 'normalize' ], $field );
85
 
86
  return $field;
87
  }
97
  }
98
 
99
  if ( empty( $field['js_options']['ajax'] ) ) {
100
+ $field['js_options']['ajax'] = [];
101
  }
102
  $field['js_options']['ajax'] = wp_parse_args(
103
+ [
104
  'url' => admin_url( 'admin-ajax.php' ),
105
+ ],
106
  $field['js_options']['ajax']
107
  );
108
+ $field['js_options']['ajax_data'] = [
109
+ 'field' => [
110
  'id' => $field['id'],
111
  'type' => $field['type'],
112
  'query_args' => $field['query_args'],
113
+ ],
114
  '_wpnonce' => wp_create_nonce( 'query' ),
115
+ ];
116
  }
117
 
118
  /**
124
  * @return array
125
  */
126
  public static function get_attributes( $field, $value = null ) {
127
+ $attributes = call_user_func( [ self::get_type_class( $field ), 'get_attributes' ], $field, $value );
128
  if ( 'select_advanced' === $field['field_type'] ) {
129
  $attributes['class'] .= ' rwmb-select_advanced';
130
  } elseif ( 'select' === $field['field_type'] ) {
133
  return $attributes;
134
  }
135
 
 
 
 
136
  public static function admin_enqueue_scripts() {
137
  RWMB_Input_List_Field::admin_enqueue_scripts();
138
  RWMB_Select_Field::admin_enqueue_scripts();
142
 
143
  /**
144
  * Get correct rendering class for the field.
 
 
 
145
  */
146
+ protected static function get_type_class( array $field ) : string {
147
+ return RWMB_Helpers_Field::get_class( [ 'type' => $field['field_type'] ] );
 
 
 
 
148
  }
149
  }
inc/fields/radio.php CHANGED
@@ -1,20 +1,8 @@
1
  <?php
2
  /**
3
  * The radio field.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Radio field class.
10
  */
11
  class RWMB_Radio_Field extends RWMB_Input_List_Field {
12
- /**
13
- * Normalize parameters for field.
14
- *
15
- * @param array $field Field parameters.
16
- * @return array
17
- */
18
  public static function normalize( $field ) {
19
  $field['multiple'] = false;
20
  $field = parent::normalize( $field );
1
  <?php
2
  /**
3
  * The radio field.
 
 
 
 
 
 
4
  */
5
  class RWMB_Radio_Field extends RWMB_Input_List_Field {
 
 
 
 
 
 
6
  public static function normalize( $field ) {
7
  $field['multiple'] = false;
8
  $field = parent::normalize( $field );
inc/fields/taxonomy-advanced.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
  * Taxonomy advanced field which saves terms' IDs in the post meta in CSV format.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * The taxonomy advanced field class.
10
  */
11
  class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field {
12
  /**
@@ -47,16 +41,15 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field {
47
  *
48
  * @return mixed
49
  */
50
- public static function raw_meta( $object_id, $field, $args = array() ) {
51
  $args['single'] = true;
52
  $meta = RWMB_Field::raw_meta( $object_id, $field, $args );
53
 
54
  if ( empty( $meta ) ) {
55
- return $field['multiple'] ? array() : '';
56
  }
57
 
58
  $meta = $field['clone'] ? array_map( 'wp_parse_id_list', $meta ) : wp_parse_id_list( $meta );
59
-
60
  $meta = array_filter( $meta );
61
 
62
  return $meta;
@@ -72,19 +65,17 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field {
72
  *
73
  * @return array List of post term objects.
74
  */
75
- public static function get_value( $field, $args = array(), $post_id = null ) {
76
  $value = RWMB_Field::get_value( $field, $args, $post_id );
77
  if ( ! $field['clone'] ) {
78
- $value = self::call( 'terms_info', $field, $value, $args );
79
- } else {
80
- $return = array();
81
- foreach ( $value as $subvalue ) {
82
- $return[] = self::call( 'terms_info', $field, $subvalue, $args );
83
- }
84
- $value = $return;
85
  }
86
 
87
- return $value;
 
 
 
 
88
  }
89
 
90
  /**
@@ -98,18 +89,15 @@ class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field {
98
  */
99
  public static function terms_info( $field, $term_ids, $args ) {
100
  if ( empty( $term_ids ) ) {
101
- return array();
102
  }
103
- $args = wp_parse_args(
104
- array(
105
- 'include' => $term_ids,
106
- 'hide_empty' => false,
107
- ),
108
- $args
109
- );
110
 
111
  $info = get_terms( $field['taxonomy'], $args );
112
- $info = is_array( $info ) ? $info : array();
113
  return $field['multiple'] ? $info : reset( $info );
114
  }
115
  }
1
  <?php
2
  /**
3
  * Taxonomy advanced field which saves terms' IDs in the post meta in CSV format.
 
 
 
 
 
 
4
  */
5
  class RWMB_Taxonomy_Advanced_Field extends RWMB_Taxonomy_Field {
6
  /**
41
  *
42
  * @return mixed
43
  */
44
+ public static function raw_meta( $object_id, $field, $args = [] ) {
45
  $args['single'] = true;
46
  $meta = RWMB_Field::raw_meta( $object_id, $field, $args );
47
 
48
  if ( empty( $meta ) ) {
49
+ return $field['multiple'] ? [] : '';
50
  }
51
 
52
  $meta = $field['clone'] ? array_map( 'wp_parse_id_list', $meta ) : wp_parse_id_list( $meta );
 
53
  $meta = array_filter( $meta );
54
 
55
  return $meta;
65
  *
66
  * @return array List of post term objects.
67
  */
68
+ public static function get_value( $field, $args = [], $post_id = null ) {
69
  $value = RWMB_Field::get_value( $field, $args, $post_id );
70
  if ( ! $field['clone'] ) {
71
+ return static::terms_info( $field, $value, $args );
 
 
 
 
 
 
72
  }
73
 
74
+ $return = [];
75
+ foreach ( $value as $subvalue ) {
76
+ $return[] = static::terms_info( $field, $subvalue, $args );
77
+ }
78
+ return $return;
79
  }
80
 
81
  /**
89
  */
90
  public static function terms_info( $field, $term_ids, $args ) {
91
  if ( empty( $term_ids ) ) {
92
+ return [];
93
  }
94
+ $args = wp_parse_args( [
95
+ 'include' => $term_ids,
96
+ 'hide_empty' => false,
97
+ ], $args );
 
 
 
98
 
99
  $info = get_terms( $field['taxonomy'], $args );
100
+ $info = is_array( $info ) ? $info : [];
101
  return $field['multiple'] ? $info : reset( $info );
102
  }
103
  }
inc/loader.php CHANGED
@@ -3,24 +3,13 @@
3
  * Load plugin's files with check for installing it as a standalone plugin or
4
  * a module of a theme / plugin. If standalone plugin is already installed, it
5
  * will take higher priority.
6
- *
7
- * @package Meta Box
8
- */
9
-
10
- /**
11
- * Plugin loader class.
12
- *
13
- * @package Meta Box
14
  */
15
  class RWMB_Loader {
16
- /**
17
- * Define plugin constants.
18
- */
19
  protected function constants() {
20
  // Script version, used to add version for scripts and styles.
21
- define( 'RWMB_VER', '5.6.7' );
22
 
23
- list( $path, $url ) = self::get_path( dirname( dirname( __FILE__ ) ) );
24
 
25
  // Plugin URLs, for fast enqueuing scripts and styles.
26
  define( 'RWMB_URL', $url );
@@ -40,7 +29,7 @@ class RWMB_Loader {
40
  * @param string $path Base folder path.
41
  * @return array Path and URL.
42
  */
43
- public static function get_path( $path = '' ) {
44
  // Plugin base path.
45
  $path = wp_normalize_path( untrailingslashit( $path ) );
46
  $themes_dir = wp_normalize_path( untrailingslashit( dirname( get_stylesheet_directory() ) ) );
@@ -61,7 +50,7 @@ class RWMB_Loader {
61
  $path = trailingslashit( $path );
62
  $url = trailingslashit( $url );
63
 
64
- return array( $path, $url );
65
  }
66
 
67
  /**
@@ -117,11 +106,11 @@ class RWMB_Loader {
117
  $about = new RWMB_About( $update_checker );
118
  $about->init();
119
 
120
- new RWMB_Dashboard( 'http://feeds.feedburner.com/metaboxio', 'https://metabox.io/blog/', array(
121
  'title' => 'Meta Box',
122
  'dismiss_tooltip' => esc_html__( 'Dismiss all Meta Box news', 'meta-box' ),
123
  'dismiss_confirm' => esc_html__( 'Are you sure to dismiss all Meta Box news?', 'meta-box' ),
124
- ) );
125
  }
126
 
127
  // Public functions.
3
  * Load plugin's files with check for installing it as a standalone plugin or
4
  * a module of a theme / plugin. If standalone plugin is already installed, it
5
  * will take higher priority.
 
 
 
 
 
 
 
 
6
  */
7
  class RWMB_Loader {
 
 
 
8
  protected function constants() {
9
  // Script version, used to add version for scripts and styles.
10
+ define( 'RWMB_VER', '5.6.8' );
11
 
12
+ list( $path, $url ) = self::get_path( dirname( __DIR__ ) );
13
 
14
  // Plugin URLs, for fast enqueuing scripts and styles.
15
  define( 'RWMB_URL', $url );
29
  * @param string $path Base folder path.
30
  * @return array Path and URL.
31
  */
32
+ public static function get_path( string $path = '' ) : array {
33
  // Plugin base path.
34
  $path = wp_normalize_path( untrailingslashit( $path ) );
35
  $themes_dir = wp_normalize_path( untrailingslashit( dirname( get_stylesheet_directory() ) ) );
50
  $path = trailingslashit( $path );
51
  $url = trailingslashit( $url );
52
 
53
+ return [ $path, $url ];
54
  }
55
 
56
  /**
106
  $about = new RWMB_About( $update_checker );
107
  $about->init();
108
 
109
+ new RWMB_Dashboard( 'http://feeds.feedburner.com/metaboxio', 'https://metabox.io/blog/', [
110
  'title' => 'Meta Box',
111
  'dismiss_tooltip' => esc_html__( 'Dismiss all Meta Box news', 'meta-box' ),
112
  'dismiss_confirm' => esc_html__( 'Are you sure to dismiss all Meta Box news?', 'meta-box' ),
113
+ ] );
114
  }
115
 
116
  // Public functions.
inc/meta-box-registry.php CHANGED
@@ -2,20 +2,10 @@
2
  /**
3
  * A registry for storing all meta boxes.
4
  *
5
- * @link https://designpatternsphp.readthedocs.io/en/latest/Structural/Registry/README.html
6
- * @package Meta Box
7
- */
8
-
9
- /**
10
- * Meta box registry class.
11
  */
12
  class RWMB_Meta_Box_Registry {
13
- /**
14
- * Internal data storage.
15
- *
16
- * @var array
17
- */
18
- private $data = array();
19
 
20
  /**
21
  * Create a meta box object.
@@ -23,7 +13,7 @@ class RWMB_Meta_Box_Registry {
23
  * @param array $settings Meta box settings.
24
  * @return \RW_Meta_Box
25
  */
26
- public function make( $settings ) {
27
  $class_name = apply_filters( 'rwmb_meta_box_class_name', 'RW_Meta_Box', $settings );
28
 
29
  $meta_box = new $class_name( $settings );
@@ -31,34 +21,20 @@ class RWMB_Meta_Box_Registry {
31
  return $meta_box;
32
  }
33
 
34
- /**
35
- * Add a meta box to the registry.
36
- *
37
- * @param RW_Meta_Box $meta_box Meta box instance.
38
- */
39
  public function add( RW_Meta_Box $meta_box ) {
40
  $this->data[ $meta_box->id ] = $meta_box;
41
  }
42
 
43
- /**
44
- * Retrieve a meta box by id.
45
- *
46
- * @param string $id Meta box id.
47
- *
48
- * @return RW_Meta_Box|bool False or meta box object.
49
- */
50
  public function get( $id ) {
51
- return isset( $this->data[ $id ] ) ? $this->data[ $id ] : false;
52
  }
53
 
54
  /**
55
  * Get meta boxes under some conditions.
56
  *
57
  * @param array $args Custom argument to get meta boxes by.
58
- *
59
- * @return array
60
  */
61
- public function get_by( $args ) {
62
  $meta_boxes = $this->data;
63
  foreach ( $meta_boxes as $index => $meta_box ) {
64
  foreach ( $args as $key => $value ) {
@@ -73,11 +49,6 @@ class RWMB_Meta_Box_Registry {
73
  return $meta_boxes;
74
  }
75
 
76
- /**
77
- * Retrieve all meta boxes.
78
- *
79
- * @return array
80
- */
81
  public function all() {
82
  return $this->data;
83
  }
2
  /**
3
  * A registry for storing all meta boxes.
4
  *
5
+ * @link https://designpatternsphp.readthedocs.io/en/latest/Structural/Registry/README.html
 
 
 
 
 
6
  */
7
  class RWMB_Meta_Box_Registry {
8
+ private $data = [];
 
 
 
 
 
9
 
10
  /**
11
  * Create a meta box object.
13
  * @param array $settings Meta box settings.
14
  * @return \RW_Meta_Box
15
  */
16
+ public function make( array $settings ) {
17
  $class_name = apply_filters( 'rwmb_meta_box_class_name', 'RW_Meta_Box', $settings );
18
 
19
  $meta_box = new $class_name( $settings );
21
  return $meta_box;
22
  }
23
 
 
 
 
 
 
24
  public function add( RW_Meta_Box $meta_box ) {
25
  $this->data[ $meta_box->id ] = $meta_box;
26
  }
27
 
 
 
 
 
 
 
 
28
  public function get( $id ) {
29
+ return $this->data[ $id ] ?? false;
30
  }
31
 
32
  /**
33
  * Get meta boxes under some conditions.
34
  *
35
  * @param array $args Custom argument to get meta boxes by.
 
 
36
  */
37
+ public function get_by( array $args ) : array {
38
  $meta_boxes = $this->data;
39
  foreach ( $meta_boxes as $index => $meta_box ) {
40
  foreach ( $args as $key => $value ) {
49
  return $meta_boxes;
50
  }
51
 
 
 
 
 
 
52
  public function all() {
53
  return $this->data;
54
  }
inc/request.php CHANGED
@@ -5,33 +5,11 @@
5
  *
6
  * @link https://github.com/laravel/framework/blob/6.x/src/Illuminate/Http/Request.php
7
  * @link https://github.com/symfony/symfony/blob/4.4/src/Symfony/Component/HttpFoundation/ParameterBag.php
8
- *
9
- * @package Meta Box
10
- */
11
-
12
- /**
13
- * A very simple request class that handles form inputs.
14
- *
15
- * @package Meta Box
16
  */
17
  class RWMB_Request {
18
- /**
19
- * GET data.
20
- *
21
- * @var array
22
- */
23
- private $get_data = array();
24
 
25
- /**
26
- * POST data.
27
- *
28
- * @var array
29
- */
30
- private $post_data = array();
31
-
32
- /**
33
- * Constructor.
34
- */
35
  public function __construct() {
36
  // @codingStandardsIgnoreLine
37
  $this->get_data = $_GET;
@@ -39,44 +17,20 @@ class RWMB_Request {
39
  $this->post_data = $_POST;
40
  }
41
 
42
- /**
43
- * Set GET data.
44
- *
45
- * @param array $get_data Data.
46
- */
47
- public function set_get_data( $get_data ) {
48
- $this->get_data = array_merge( $this->get_data, $get_data );
49
  }
50
 
51
- /**
52
- * Set POST data.
53
- *
54
- * @param array $post_data Data.
55
- */
56
- public function set_post_data( $post_data ) {
57
- $this->post_data = array_merge( $this->post_data, $post_data );
58
  }
59
 
60
- /**
61
- * Return a GET parameter by name.
62
- *
63
- * @param string $name Parameter name.
64
- * @param mixed $default Default value.
65
- * @return mixed
66
- */
67
- public function get( $name, $default = null ) {
68
- return isset( $this->get_data[ $name ] ) ? $this->get_data[ $name ] : $default;
69
  }
70
 
71
- /**
72
- * Return a POST parameter by name.
73
- *
74
- * @param string $name Parameter name.
75
- * @param mixed $default Default value.
76
- * @return mixed
77
- */
78
- public function post( $name, $default = null ) {
79
- return isset( $this->post_data[ $name ] ) ? $this->post_data[ $name ] : $default;
80
  }
81
 
82
  /**
@@ -88,7 +42,7 @@ class RWMB_Request {
88
  *
89
  * @return mixed
90
  */
91
- public function filter_get( $name, $filter = FILTER_DEFAULT, $options = array() ) {
92
  $value = $this->get( $name );
93
  return filter_var( $value, $filter, $options );
94
  }
@@ -102,7 +56,7 @@ class RWMB_Request {
102
  *
103
  * @return mixed
104
  */
105
- public function filter_post( $name, $filter = FILTER_DEFAULT, $options = array() ) {
106
  $value = $this->post( $name );
107
  return filter_var( $value, $filter, $options );
108
  }
5
  *
6
  * @link https://github.com/laravel/framework/blob/6.x/src/Illuminate/Http/Request.php
7
  * @link https://github.com/symfony/symfony/blob/4.4/src/Symfony/Component/HttpFoundation/ParameterBag.php
 
 
 
 
 
 
 
 
8
  */
9
  class RWMB_Request {
10
+ private $get_data = [];
11
+ private $post_data = [];
 
 
 
 
12
 
 
 
 
 
 
 
 
 
 
 
13
  public function __construct() {
14
  // @codingStandardsIgnoreLine
15
  $this->get_data = $_GET;
17
  $this->post_data = $_POST;
18
  }
19
 
20
+ public function set_get_data( array $data ) {
21
+ $this->get_data = array_merge( $this->get_data, $data );
 
 
 
 
 
22
  }
23
 
24
+ public function set_post_data( array $data ) {
25
+ $this->post_data = array_merge( $this->post_data, $data );
 
 
 
 
 
26
  }
27
 
28
+ public function get( string $name, $default = null ) {
29
+ return $this->get_data[ $name ] ?? $default;
 
 
 
 
 
 
 
30
  }
31
 
32
+ public function post( string $name, $default = null ) {
33
+ return $this->post_data[ $name ] ?? $default;
 
 
 
 
 
 
 
34
  }
35
 
36
  /**
42
  *
43
  * @return mixed
44
  */
45
+ public function filter_get( string $name, $filter = FILTER_DEFAULT, $options = [] ) {
46
  $value = $this->get( $name );
47
  return filter_var( $value, $filter, $options );
48
  }
56
  *
57
  * @return mixed
58
  */
59
+ public function filter_post( string $name, $filter = FILTER_DEFAULT, $options = [] ) {
60
  $value = $this->post( $name );
61
  return filter_var( $value, $filter, $options );
62
  }
inc/sanitizer.php CHANGED
@@ -1,19 +1,10 @@
1
  <?php
2
  /**
3
  * Sanitize field value before saving.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Sanitize class.
10
  */
11
  class RWMB_Sanitizer {
12
- /**
13
- * Register hook to sanitize field value.
14
- */
15
  public function init() {
16
- add_filter( 'rwmb_sanitize', array( $this, 'sanitize' ), 10, 4 );
17
  }
18
 
19
  /**
@@ -47,56 +38,56 @@ class RWMB_Sanitizer {
47
  return $field['sanitize_callback'];
48
  }
49
 
50
- $callbacks = array(
51
- 'autocomplete' => array( $this, 'sanitize_choice' ),
52
- 'background' => array( $this, 'sanitize_background' ),
53
- 'button_group' => array( $this, 'sanitize_choice' ),
54
- 'checkbox' => array( $this, 'sanitize_checkbox' ),
55
- 'checkbox_list' => array( $this, 'sanitize_choice' ),
56
- 'color' => array( $this, 'sanitize_color' ),
57
- 'date' => array( $this, 'sanitize_datetime' ),
58
- 'datetime' => array( $this, 'sanitize_datetime' ),
59
  'email' => 'sanitize_email',
60
- 'fieldset_text' => array( $this, 'sanitize_text' ),
61
- 'file' => array( $this, 'sanitize_file' ),
62
- 'file_advanced' => array( $this, 'sanitize_object' ),
63
- 'file_input' => array( $this, 'sanitize_url' ),
64
- 'file_upload' => array( $this, 'sanitize_object' ),
65
  'hidden' => 'sanitize_text_field',
66
- 'image' => array( $this, 'sanitize_file' ),
67
- 'image_advanced' => array( $this, 'sanitize_object' ),
68
- 'image_select' => array( $this, 'sanitize_choice' ),
69
- 'image_upload' => array( $this, 'sanitize_object' ),
70
- 'key_value' => array( $this, 'sanitize_text' ),
71
- 'map' => array( $this, 'sanitize_map' ),
72
- 'number' => array( $this, 'sanitize_number' ),
73
- 'oembed' => array( $this, 'sanitize_url' ),
74
- 'osm' => array( $this, 'sanitize_map' ),
75
  'password' => 'sanitize_text_field',
76
- 'post' => array( $this, 'sanitize_object' ),
77
- 'radio' => array( $this, 'sanitize_choice' ),
78
- 'range' => array( $this, 'sanitize_number' ),
79
- 'select' => array( $this, 'sanitize_choice' ),
80
- 'select_advanced' => array( $this, 'sanitize_choice' ),
81
- 'sidebar' => array( $this, 'sanitize_text' ),
82
  'single_image' => 'absint',
83
- 'slider' => array( $this, 'sanitize_slider' ),
84
- 'switch' => array( $this, 'sanitize_checkbox' ),
85
- 'taxonomy' => array( $this, 'sanitize_object' ),
86
- 'taxonomy_advanced' => array( $this, 'sanitize_taxonomy_advanced' ),
87
  'text' => 'sanitize_text_field',
88
- 'text_list' => array( $this, 'sanitize_text' ),
89
  'textarea' => 'wp_kses_post',
90
  'time' => 'sanitize_text_field',
91
- 'url' => array( $this, 'sanitize_url' ),
92
- 'user' => array( $this, 'sanitize_object' ),
93
- 'video' => array( $this, 'sanitize_object' ),
94
  'wysiwyg' => 'wp_kses_post',
95
- );
96
 
97
  $type = $field['type'];
98
 
99
- return isset( $callbacks[ $type ] ) ? $callbacks[ $type ] : null;
100
  }
101
 
102
  /**
@@ -105,9 +96,8 @@ class RWMB_Sanitizer {
105
  *
106
  * @link https://github.com/rilwis/meta-box/issues/6
107
  * @param string $value Checkbox value.
108
- * @return int
109
  */
110
- private function sanitize_checkbox( $value ) {
111
  return (int) ! empty( $value );
112
  }
113
 
@@ -121,13 +111,7 @@ class RWMB_Sanitizer {
121
  return is_numeric( $value ) ? $value : '';
122
  }
123
 
124
- /**
125
- * Sanitize color value.
126
- *
127
- * @param string $value The color value.
128
- * @return string
129
- */
130
- private function sanitize_color( $value ) {
131
  if ( false === strpos( $value, 'rgba' ) ) {
132
  return sanitize_hex_color( $value );
133
  }
@@ -152,7 +136,7 @@ class RWMB_Sanitizer {
152
  private function sanitize_choice( $value, $field ) {
153
  $options = RWMB_Choice_Field::transform_options( $field['options'] );
154
  $options = wp_list_pluck( $options, 'value' );
155
- $value = wp_unslash( $value );
156
  return is_array( $value ) ? array_intersect( $value, $options ) : ( in_array( $value, $options ) ? $value : '' );
157
  }
158
 
@@ -173,24 +157,21 @@ class RWMB_Sanitizer {
173
  * @return array
174
  */
175
  private function sanitize_background( $value ) {
176
- $value = wp_parse_args(
177
- $value,
178
- array(
179
- 'color' => '',
180
- 'image' => '',
181
- 'repeat' => '',
182
- 'attachment' => '',
183
- 'position' => '',
184
- 'size' => '',
185
- )
186
- );
187
  $value['color'] = $this->sanitize_color( $value['color'] );
188
  $value['image'] = esc_url_raw( $value['image'] );
189
 
190
- $value['repeat'] = in_array( $value['repeat'], array( 'no-repeat', 'repeat', 'repeat-x', 'repeat-y', 'inherit' ), true ) ? $value['repeat'] : '';
191
- $value['position'] = in_array( $value['position'], array( 'top left', 'top center', 'top right', 'center left', 'center center', 'center right', 'bottom left', 'bottom center', 'bottom right' ), true ) ? $value['position'] : '';
192
- $value['attachment'] = in_array( $value['attachment'], array( 'fixed', 'scroll', 'inherit' ), true ) ? $value['attachment'] : '';
193
- $value['size'] = in_array( $value['size'], array( 'inherit', 'cover', 'contain' ), true ) ? $value['size'] : '';
194
 
195
  return $value;
196
  }
@@ -242,9 +223,8 @@ class RWMB_Sanitizer {
242
  * Sanitize map field.
243
  *
244
  * @param mixed $value The submitted value.
245
- * @return string
246
  */
247
- private function sanitize_map( $value ) {
248
  $value = sanitize_text_field( $value );
249
  list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' );
250
 
@@ -259,22 +239,15 @@ class RWMB_Sanitizer {
259
  * Sanitize taxonomy advanced field.
260
  *
261
  * @param mixed $value The submitted value.
262
- * @return string
263
  */
264
- private function sanitize_taxonomy_advanced( $value ) {
265
  $value = RWMB_Helpers_Array::from_csv( $value );
266
  $value = array_filter( array_map( 'absint', $value ) );
267
 
268
  return implode( ',', $value );
269
  }
270
 
271
- /**
272
- * Sanitize URL field.
273
- *
274
- * @param string $value The submitted value.
275
- * @return string
276
- */
277
- private function sanitize_url( $value ) {
278
  return esc_url_raw( $value );
279
  }
280
  }
1
  <?php
2
  /**
3
  * Sanitize field value before saving.
 
 
 
 
 
 
4
  */
5
  class RWMB_Sanitizer {
 
 
 
6
  public function init() {
7
+ add_filter( 'rwmb_sanitize', [ $this, 'sanitize' ], 10, 4 );
8
  }
9
 
10
  /**
38
  return $field['sanitize_callback'];
39
  }
40
 
41
+ $callbacks = [
42
+ 'autocomplete' => [ $this, 'sanitize_choice' ],
43
+ 'background' => [ $this, 'sanitize_background' ],
44
+ 'button_group' => [ $this, 'sanitize_choice' ],
45
+ 'checkbox' => [ $this, 'sanitize_checkbox' ],
46
+ 'checkbox_list' => [ $this, 'sanitize_choice' ],
47
+ 'color' => [ $this, 'sanitize_color' ],
48
+ 'date' => [ $this, 'sanitize_datetime' ],
49
+ 'datetime' => [ $this, 'sanitize_datetime' ],
50
  'email' => 'sanitize_email',
51
+ 'fieldset_text' => [ $this, 'sanitize_text' ],
52
+ 'file' => [ $this, 'sanitize_file' ],
53
+ 'file_advanced' => [ $this, 'sanitize_object' ],
54
+ 'file_input' => [ $this, 'sanitize_url' ],
55
+ 'file_upload' => [ $this, 'sanitize_object' ],
56
  'hidden' => 'sanitize_text_field',
57
+ 'image' => [ $this, 'sanitize_file' ],
58
+ 'image_advanced' => [ $this, 'sanitize_object' ],
59
+ 'image_select' => [ $this, 'sanitize_choice' ],
60
+ 'image_upload' => [ $this, 'sanitize_object' ],
61
+ 'key_value' => [ $this, 'sanitize_text' ],
62
+ 'map' => [ $this, 'sanitize_map' ],
63
+ 'number' => [ $this, 'sanitize_number' ],
64
+ 'oembed' => [ $this, 'sanitize_url' ],
65
+ 'osm' => [ $this, 'sanitize_map' ],
66
  'password' => 'sanitize_text_field',
67
+ 'post' => [ $this, 'sanitize_object' ],
68
+ 'radio' => [ $this, 'sanitize_choice' ],
69
+ 'range' => [ $this, 'sanitize_number' ],
70
+ 'select' => [ $this, 'sanitize_choice' ],
71
+ 'select_advanced' => [ $this, 'sanitize_choice' ],
72
+ 'sidebar' => [ $this, 'sanitize_text' ],
73
  'single_image' => 'absint',
74
+ 'slider' => [ $this, 'sanitize_slider' ],
75
+ 'switch' => [ $this, 'sanitize_checkbox' ],
76
+ 'taxonomy' => [ $this, 'sanitize_object' ],
77
+ 'taxonomy_advanced' => [ $this, 'sanitize_taxonomy_advanced' ],
78
  'text' => 'sanitize_text_field',
79
+ 'text_list' => [ $this, 'sanitize_text' ],
80
  'textarea' => 'wp_kses_post',
81
  'time' => 'sanitize_text_field',
82
+ 'url' => [ $this, 'sanitize_url' ],
83
+ 'user' => [ $this, 'sanitize_object' ],
84
+ 'video' => [ $this, 'sanitize_object' ],
85
  'wysiwyg' => 'wp_kses_post',
86
+ ];
87
 
88
  $type = $field['type'];
89
 
90
+ return $callbacks[ $type ] ?? null;
91
  }
92
 
93
  /**
96
  *
97
  * @link https://github.com/rilwis/meta-box/issues/6
98
  * @param string $value Checkbox value.
 
99
  */
100
+ private function sanitize_checkbox( $value ) : int {
101
  return (int) ! empty( $value );
102
  }
103
 
111
  return is_numeric( $value ) ? $value : '';
112
  }
113
 
114
+ private function sanitize_color( string $value ) : string {
 
 
 
 
 
 
115
  if ( false === strpos( $value, 'rgba' ) ) {
116
  return sanitize_hex_color( $value );
117
  }
136
  private function sanitize_choice( $value, $field ) {
137
  $options = RWMB_Choice_Field::transform_options( $field['options'] );
138
  $options = wp_list_pluck( $options, 'value' );
139
+ $value = wp_unslash( $value );
140
  return is_array( $value ) ? array_intersect( $value, $options ) : ( in_array( $value, $options ) ? $value : '' );
141
  }
142
 
157
  * @return array
158
  */
159
  private function sanitize_background( $value ) {
160
+ $value = wp_parse_args( $value, [
161
+ 'color' => '',
162
+ 'image' => '',
163
+ 'repeat' => '',
164
+ 'attachment' => '',
165
+ 'position' => '',
166
+ 'size' => '',
167
+ ] );
 
 
 
168
  $value['color'] = $this->sanitize_color( $value['color'] );
169
  $value['image'] = esc_url_raw( $value['image'] );
170
 
171
+ $value['repeat'] = in_array( $value['repeat'], [ 'no-repeat', 'repeat', 'repeat-x', 'repeat-y', 'inherit' ], true ) ? $value['repeat'] : '';
172
+ $value['position'] = in_array( $value['position'], [ 'top left', 'top center', 'top right', 'center left', 'center center', 'center right', 'bottom left', 'bottom center', 'bottom right' ], true ) ? $value['position'] : '';
173
+ $value['attachment'] = in_array( $value['attachment'], [ 'fixed', 'scroll', 'inherit' ], true ) ? $value['attachment'] : '';
174
+ $value['size'] = in_array( $value['size'], [ 'inherit', 'cover', 'contain' ], true ) ? $value['size'] : '';
175
 
176
  return $value;
177
  }
223
  * Sanitize map field.
224
  *
225
  * @param mixed $value The submitted value.
 
226
  */
227
+ private function sanitize_map( $value ) : string {
228
  $value = sanitize_text_field( $value );
229
  list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' );
230
 
239
  * Sanitize taxonomy advanced field.
240
  *
241
  * @param mixed $value The submitted value.
 
242
  */
243
+ private function sanitize_taxonomy_advanced( $value ) : string {
244
  $value = RWMB_Helpers_Array::from_csv( $value );
245
  $value = array_filter( array_map( 'absint', $value ) );
246
 
247
  return implode( ',', $value );
248
  }
249
 
250
+ private function sanitize_url( string $value ) : string {
 
 
 
 
 
 
251
  return esc_url_raw( $value );
252
  }
253
  }
inc/shortcode.php CHANGED
@@ -53,4 +53,4 @@ class RWMB_Shortcode {
53
 
54
  return $value;
55
  }
56
- }
53
 
54
  return $value;
55
  }
56
+ }
inc/storage-registry.php CHANGED
@@ -1,21 +1,9 @@
1
  <?php
2
  /**
3
  * Storage registry class
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Class RWMB_Storage_Registry
10
  */
11
  class RWMB_Storage_Registry {
12
-
13
- /**
14
- * List storage instances.
15
- *
16
- * @var array
17
- */
18
- protected $storages = array();
19
 
20
  /**
21
  * Get storage instance.
1
  <?php
2
  /**
3
  * Storage registry class
 
 
 
 
 
 
4
  */
5
  class RWMB_Storage_Registry {
6
+ protected $storages = [];
 
 
 
 
 
 
7
 
8
  /**
9
  * Get storage instance.
inc/validation.php CHANGED
@@ -1,28 +1,16 @@
1
  <?php
2
  /**
3
  * Validation module.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * Validation class.
10
  */
11
  class RWMB_Validation {
12
-
13
- /**
14
- * Add hooks when module is loaded.
15
- */
16
  public function __construct() {
17
- add_action( 'rwmb_after', array( $this, 'rules' ) );
18
- add_action( 'rwmb_enqueue_scripts', array( $this, 'enqueue' ) );
19
  }
20
 
21
  /**
22
  * Output validation rules of each meta box.
23
  * The rules are outputted in [data-validation] attribute of an hidden <script> and will be converted into JSON by JS.
24
- *
25
- * @param RW_Meta_Box $object Meta Box object.
26
  */
27
  public function rules( RW_Meta_Box $object ) {
28
  if ( ! empty( $object->meta_box['validation'] ) ) {
@@ -30,18 +18,15 @@ class RWMB_Validation {
30
  }
31
  }
32
 
33
- /**
34
- * Enqueue scripts for validation.
35
- */
36
  public function enqueue() {
37
- wp_enqueue_script( 'rwmb-validation', RWMB_JS_URL . 'validation.min.js', array( 'jquery', 'rwmb' ), RWMB_VER, true );
38
 
39
  RWMB_Helpers_Field::localize_script_once(
40
  'rwmb-validation',
41
  'rwmbValidation',
42
- array(
43
- 'message' => esc_html__( 'Please correct the errors highlighted below and try again.', 'meta-box' ),
44
- )
45
  );
46
  }
47
  }
1
  <?php
2
  /**
3
  * Validation module.
 
 
 
 
 
 
4
  */
5
  class RWMB_Validation {
 
 
 
 
6
  public function __construct() {
7
+ add_action( 'rwmb_after', [ $this, 'rules' ] );
8
+ add_action( 'rwmb_enqueue_scripts', [ $this, 'enqueue' ] );
9
  }
10
 
11
  /**
12
  * Output validation rules of each meta box.
13
  * The rules are outputted in [data-validation] attribute of an hidden <script> and will be converted into JSON by JS.
 
 
14
  */
15
  public function rules( RW_Meta_Box $object ) {
16
  if ( ! empty( $object->meta_box['validation'] ) ) {
18
  }
19
  }
20
 
 
 
 
21
  public function enqueue() {
22
+ wp_enqueue_script( 'rwmb-validation', RWMB_JS_URL . 'validation.min.js', [ 'jquery', 'rwmb' ], RWMB_VER, true );
23
 
24
  RWMB_Helpers_Field::localize_script_once(
25
  'rwmb-validation',
26
  'rwmbValidation',
27
+ [
28
+ 'message' => esc_html( apply_filters( 'rwmb_validation_message_string', __( 'Please correct the errors highlighted below and try again.', 'meta-box' ) ) ),
29
+ ]
30
  );
31
  }
32
  }
inc/walkers/input-list.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
  * The input list walker for checkbox and radio list fields.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * The input list walker class.
10
  */
11
  class RWMB_Walker_Input_List extends RWMB_Walker_Base {
12
  /**
@@ -16,8 +10,8 @@ class RWMB_Walker_Input_List extends RWMB_Walker_Base {
16
  * @param int $depth Depth of the item.
17
  * @param array $args An array of additional arguments.
18
  */
19
- public function start_lvl( &$output, $depth = 0, $args = array() ) {
20
- $output .= '<ul class="rwmb-input-list">';
21
  }
22
 
23
  /**
@@ -27,8 +21,8 @@ class RWMB_Walker_Input_List extends RWMB_Walker_Base {
27
  * @param int $depth Depth of the item.
28
  * @param array $args An array of additional arguments.
29
  */
30
- public function end_lvl( &$output, $depth = 0, $args = array() ) {
31
- $output .= '</ul>';
32
  }
33
 
34
  /**
@@ -40,26 +34,14 @@ class RWMB_Walker_Input_List extends RWMB_Walker_Base {
40
  * @param array $args An array of additional arguments.
41
  * @param int $current_object_id ID of the current item.
42
  */
43
- public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
44
  $attributes = RWMB_Field::call( 'get_attributes', $this->field, $object->value );
45
 
46
  $output .= sprintf(
47
- '<li><label><input %s %s>%s</label>',
48
  RWMB_Field::render_attributes( $attributes ),
49
  checked( in_array( $object->value, $this->meta ), true, false ),
50
  $object->label
51
  );
52
  }
53
-
54
- /**
55
- * Ends the element output, if needed.
56
- *
57
- * @param string $output Passed by reference. Used to append additional content.
58
- * @param object $object The data object.
59
- * @param int $depth Depth of the item.
60
- * @param array $args An array of additional arguments.
61
- */
62
- public function end_el( &$output, $object, $depth = 0, $args = array() ) {
63
- $output .= '</li>';
64
- }
65
  }
1
  <?php
2
  /**
3
  * The input list walker for checkbox and radio list fields.
 
 
 
 
 
 
4
  */
5
  class RWMB_Walker_Input_List extends RWMB_Walker_Base {
6
  /**
10
  * @param int $depth Depth of the item.
11
  * @param array $args An array of additional arguments.
12
  */
13
+ public function start_lvl( &$output, $depth = 0, $args = [] ) {
14
+ $output .= '<fieldset class="rwmb-input-list">';
15
  }
16
 
17
  /**
21
  * @param int $depth Depth of the item.
22
  * @param array $args An array of additional arguments.
23
  */
24
+ public function end_lvl( &$output, $depth = 0, $args = [] ) {
25
+ $output .= '</fieldset>';
26
  }
27
 
28
  /**
34
  * @param array $args An array of additional arguments.
35
  * @param int $current_object_id ID of the current item.
36
  */
37
+ public function start_el( &$output, $object, $depth = 0, $args = [], $current_object_id = 0 ) {
38
  $attributes = RWMB_Field::call( 'get_attributes', $this->field, $object->value );
39
 
40
  $output .= sprintf(
41
+ '<label><input %s %s>%s</label>',
42
  RWMB_Field::render_attributes( $attributes ),
43
  checked( in_array( $object->value, $this->meta ), true, false ),
44
  $object->label
45
  );
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
inc/wpml.php CHANGED
@@ -1,12 +1,6 @@
1
  <?php
2
  /**
3
  * The WPML compatibility module, allowing all fields are translatable by WPML plugin.
4
- *
5
- * @package Meta Box
6
- */
7
-
8
- /**
9
- * WPML compatibility class
10
  */
11
  class RWMB_WPML {
12
  /**
@@ -14,29 +8,23 @@ class RWMB_WPML {
14
  *
15
  * @var array
16
  */
17
- protected $field_types = array( 'post', 'taxonomy_advanced' );
18
 
19
- /**
20
- * Initialize.
21
- */
22
  public function init() {
23
  /**
24
  * Run before meta boxes are registered so it can modify fields.
25
  *
26
  * @see modify_field()
27
  */
28
- add_action( 'init', array( $this, 'register_hooks' ), 9 );
29
  }
30
 
31
- /**
32
- * Register hooks.
33
- */
34
  public function register_hooks() {
35
  if ( ! defined( 'ICL_SITEPRESS_VERSION' ) ) {
36
  return;
37
  }
38
- add_filter( 'wpml_duplicate_generic_string', array( $this, 'translate_ids' ), 10, 3 );
39
- add_filter( 'rwmb_normalize_field', array( $this, 'modify_field' ) );
40
  }
41
 
42
  /**
@@ -67,7 +55,7 @@ class RWMB_WPML {
67
  }
68
 
69
  // Dealing with IDs stored as comma separated strings.
70
- $translated_values = array();
71
  $values = explode( ',', $value );
72
 
73
  foreach ( $values as $v ) {
1
  <?php
2
  /**
3
  * The WPML compatibility module, allowing all fields are translatable by WPML plugin.
 
 
 
 
 
 
4
  */
5
  class RWMB_WPML {
6
  /**
8
  *
9
  * @var array
10
  */
11
+ protected $field_types = [ 'post', 'taxonomy_advanced' ];
12
 
 
 
 
13
  public function init() {
14
  /**
15
  * Run before meta boxes are registered so it can modify fields.
16
  *
17
  * @see modify_field()
18
  */
19
+ add_action( 'init', [ $this, 'register_hooks' ], 9 );
20
  }
21
 
 
 
 
22
  public function register_hooks() {
23
  if ( ! defined( 'ICL_SITEPRESS_VERSION' ) ) {
24
  return;
25
  }
26
+ add_filter( 'wpml_duplicate_generic_string', [ $this, 'translate_ids' ], 10, 3 );
27
+ add_filter( 'rwmb_normalize_field', [ $this, 'modify_field' ] );
28
  }
29
 
30
  /**
55
  }
56
 
57
  // Dealing with IDs stored as comma separated strings.
58
+ $translated_values = [];
59
  $values = explode( ',', $value );
60
 
61
  foreach ( $values as $v ) {
meta-box.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields in WordPress.
6
- * Version: 5.6.8
7
  * Author: MetaBox.io
8
  * Author URI: https://metabox.io
9
  * License: GPL2+
3
  * Plugin Name: Meta Box
4
  * Plugin URI: https://metabox.io
5
  * Description: Create custom meta boxes and custom fields in WordPress.
6
+ * Version: 5.6.9
7
  * Author: MetaBox.io
8
  * Author URI: https://metabox.io
9
  * License: GPL2+
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: https://metabox.io/pricing/
4
  Tags: meta box, custom fields, custom post types, custom taxonomies, cpt, meta boxes, custom field, post type, taxonomy, meta, admin, advanced, custom, edit, field, file, image, magic fields, post types, more fields, post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.3
6
  Requires PHP: 7.0
7
- Tested up to: 6.1.0
8
- Stable tag: 5.6.8
9
  License: GPLv2 or later
10
 
11
  Meta Box plugin is a powerful, professional developer toolkit to create custom meta boxes and custom fields for your custom post types in WordPress.
@@ -177,6 +177,16 @@ To getting started with the plugin, please read the [Quick Start Guide](https://
177
 
178
  == Changelog ==
179
 
 
 
 
 
 
 
 
 
 
 
180
  = 5.6.8 - 2022-11-11 =
181
  - Fix PHP8 warning in image field file info
182
  - Fix wrong comment for translation
4
  Tags: meta box, custom fields, custom post types, custom taxonomies, cpt, meta boxes, custom field, post type, taxonomy, meta, admin, advanced, custom, edit, field, file, image, magic fields, post types, more fields, post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.3
6
  Requires PHP: 7.0
7
+ Tested up to: 6.1.1
8
+ Stable tag: 5.6.9
9
  License: GPLv2 or later
10
 
11
  Meta Box plugin is a powerful, professional developer toolkit to create custom meta boxes and custom fields for your custom post types in WordPress.
177
 
178
  == Changelog ==
179
 
180
+ = 5.6.9 - 2022-12-05 =
181
+ - Improve accessibility for form controls, especially when using on the front end
182
+ - Use all admin themes for switch and button group
183
+ - Add filter 'rwmb_validation_message_string' for validation message
184
+ - Display field label description even if no label
185
+ - Fix not displaying the language according to user preference
186
+ - Fix not setting post parent for the uploaded images on the front end for `image_upload` fields
187
+ - Fix warning when using `file_info` helper function
188
+ - Modernize code for PHP 7
189
+
190
  = 5.6.8 - 2022-11-11 =
191
  - Fix PHP8 warning in image field file info
192
  - Fix wrong comment for translation