Meta Box - Version 4.16.0

Version Description

Download this release

Release Info

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

Code changes from version 4.15.9 to 4.16.0

css/select-advanced.css CHANGED
@@ -1,6 +1,7 @@
1
  .rwmb-field .select2-container {
2
  height: auto;
3
  min-width: 200px;
 
4
  }
5
  #wpbody .rwmb-select-all {
6
  display: block;
1
  .rwmb-field .select2-container {
2
  height: auto;
3
  min-width: 200px;
4
+ max-width: 100%;
5
  }
6
  #wpbody .rwmb-select-all {
7
  display: block;
css/style.css CHANGED
@@ -31,6 +31,10 @@
31
  font-weight: bold;
32
  margin-left: 3px;
33
  }
 
 
 
 
34
 
35
  /* 75% if field has label, 100% if no label */
36
  .rwmb-input {
@@ -122,6 +126,9 @@ select.rwmb-error {
122
  #side-sortables .rwmb-input {
123
  width: 100%;
124
  }
 
 
 
125
 
126
  /* Seamless style
127
  --------------------------------------------------------------*/
31
  font-weight: bold;
32
  margin-left: 3px;
33
  }
34
+ .rwmb-input input,
35
+ .rwmb-input select {
36
+ max-width: 99%;
37
+ }
38
 
39
  /* 75% if field has label, 100% if no label */
40
  .rwmb-input {
126
  #side-sortables .rwmb-input {
127
  width: 100%;
128
  }
129
+ #side-sortables .rwmb-label {
130
+ margin-bottom: 3px;
131
+ }
132
 
133
  /* Seamless style
134
  --------------------------------------------------------------*/
inc/about/about.php CHANGED
@@ -9,22 +9,10 @@
9
  * About page class.
10
  */
11
  class RWMB_About {
12
- /**
13
- * Plugin data.
14
- *
15
- * @var array
16
- */
17
- protected $plugin;
18
-
19
  /**
20
  * Init hooks.
21
  */
22
  public function init() {
23
- if ( ! function_exists( 'get_plugin_data' ) ) {
24
- include ABSPATH . 'wp-admin/includes/plugin.php';
25
- }
26
- $this->plugin = get_plugin_data( RWMB_DIR . 'meta-box.php' );
27
-
28
  // Add links to about page in the plugin action links.
29
  add_filter( 'plugin_action_links_meta-box/meta-box.php', array( $this, 'plugin_links' ) );
30
 
9
  * About page class.
10
  */
11
  class RWMB_About {
 
 
 
 
 
 
 
12
  /**
13
  * Init hooks.
14
  */
15
  public function init() {
 
 
 
 
 
16
  // Add links to about page in the plugin action links.
17
  add_filter( 'plugin_action_links_meta-box/meta-box.php', array( $this, 'plugin_links' ) );
18
 
inc/about/sections/welcome.php CHANGED
@@ -9,12 +9,14 @@
9
  ?>
10
  <h1>
11
  <?php
 
 
12
  // Translators: %s - Plugin name.
13
- echo esc_html( sprintf( __( 'Welcome to %s', 'meta-box' ), $this->plugin['Name'] ) );
14
  ?>
15
  </h1>
16
  <div class="about-text"><?php esc_html_e( 'Meta Box is a free Gutenberg and GDPR-compatible WordPress custom fields plugin and framework that makes quick work of customizing a website with—you guessed it—meta boxes and custom fields in WordPress. Follow the instruction below to get started!', 'meta-box' ); ?></div>
17
- <a target="_blank" class="wp-badge" href="<?php echo esc_url( 'https://metabox.io/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php echo esc_html( $this->plugin['Name'] ); ?></a>
18
  <p class="about-buttons">
19
  <a target="_blank" class="button" href="<?php echo esc_url( 'https://docs.metabox.io?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php esc_html_e( 'Documentation', 'meta-box' ); ?></a>
20
  <a target="_blank" class="button" href="<?php echo esc_url( 'https://metabox.io/plugins/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php esc_html_e( 'Extensions', 'meta-box' ); ?></a>
9
  ?>
10
  <h1>
11
  <?php
12
+ $plugin = get_plugin_data( RWMB_DIR . 'meta-box.php', false, false );
13
+
14
  // Translators: %s - Plugin name.
15
+ echo esc_html( sprintf( __( 'Welcome to %s', 'meta-box' ), $plugin['Name'] ) );
16
  ?>
17
  </h1>
18
  <div class="about-text"><?php esc_html_e( 'Meta Box is a free Gutenberg and GDPR-compatible WordPress custom fields plugin and framework that makes quick work of customizing a website with—you guessed it—meta boxes and custom fields in WordPress. Follow the instruction below to get started!', 'meta-box' ); ?></div>
19
+ <a target="_blank" class="wp-badge" href="<?php echo esc_url( 'https://metabox.io/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php echo esc_html( $plugin['Name'] ); ?></a>
20
  <p class="about-buttons">
21
  <a target="_blank" class="button" href="<?php echo esc_url( 'https://docs.metabox.io?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php esc_html_e( 'Documentation', 'meta-box' ); ?></a>
22
  <a target="_blank" class="button" href="<?php echo esc_url( 'https://metabox.io/plugins/?utm_source=WordPress&utm_medium=link&utm_campaign=plugin' ); ?>"><?php esc_html_e( 'Extensions', 'meta-box' ); ?></a>
inc/autoloader.php CHANGED
@@ -57,7 +57,7 @@ class RWMB_Autoloader {
57
  foreach ( $this->dirs as $dir ) {
58
  if (
59
  ( $dir['prefix'] && 0 !== strpos( $class, $dir['prefix'] ) )
60
- && ( $dir['suffix'] && substr( $class, - strlen( $dir['suffix'] ) ) !== $dir['suffix'] )
61
  ) {
62
  continue;
63
  }
57
  foreach ( $this->dirs as $dir ) {
58
  if (
59
  ( $dir['prefix'] && 0 !== strpos( $class, $dir['prefix'] ) )
60
+ || ( $dir['suffix'] && substr( $class, - strlen( $dir['suffix'] ) ) !== $dir['suffix'] )
61
  ) {
62
  continue;
63
  }
inc/fields/datetime.php CHANGED
@@ -139,7 +139,16 @@ class RWMB_Datetime_Field extends RWMB_Text_Field {
139
  * @return string|int
140
  */
141
  public static function value( $new, $old, $post_id, $field ) {
142
- return $field['timestamp'] ? $new['timestamp'] : $new;
 
 
 
 
 
 
 
 
 
143
  }
144
 
145
  /**
@@ -153,9 +162,19 @@ class RWMB_Datetime_Field extends RWMB_Text_Field {
153
  */
154
  public static function meta( $post_id, $saved, $field ) {
155
  $meta = parent::meta( $post_id, $saved, $field );
 
156
  if ( $field['timestamp'] ) {
157
  $meta = self::prepare_meta( $meta, $field );
 
 
 
 
 
158
  }
 
 
 
 
159
  return $meta;
160
  }
161
 
@@ -189,9 +208,10 @@ class RWMB_Datetime_Field extends RWMB_Text_Field {
189
  $field = wp_parse_args(
190
  $field,
191
  array(
192
- 'timestamp' => false,
193
- 'inline' => false,
194
- 'js_options' => array(),
 
195
  )
196
  );
197
 
139
  * @return string|int
140
  */
141
  public static function value( $new, $old, $post_id, $field ) {
142
+ if ( $field['timestamp'] ) {
143
+ return $new['timestamp'];
144
+ }
145
+
146
+ if ( $field['save_format'] ) {
147
+ $date = DateTime::createFromFormat( self::call( 'translate_format', $field ), $new );
148
+ $new = $date->format( $field['save_format'] );
149
+ }
150
+
151
+ return $new;
152
  }
153
 
154
  /**
162
  */
163
  public static function meta( $post_id, $saved, $field ) {
164
  $meta = parent::meta( $post_id, $saved, $field );
165
+
166
  if ( $field['timestamp'] ) {
167
  $meta = self::prepare_meta( $meta, $field );
168
+ return $meta;
169
+ }
170
+
171
+ if ( ! $field['save_format'] || ! $meta ) {
172
+ return $meta;
173
  }
174
+
175
+ $date = DateTime::createFromFormat( $field['save_format'], $meta );
176
+ $meta = $date->format( self::call( 'translate_format', $field ) );
177
+
178
  return $meta;
179
  }
180
 
208
  $field = wp_parse_args(
209
  $field,
210
  array(
211
+ 'timestamp' => false,
212
+ 'inline' => false,
213
+ 'js_options' => array(),
214
+ 'save_format' => '',
215
  )
216
  );
217
 
inc/fields/file.php CHANGED
@@ -47,11 +47,18 @@ class RWMB_File_Field extends RWMB_Field {
47
  * Ajax callback for deleting files.
48
  */
49
  public static function ajax_delete_file() {
50
- $field_id = (string) filter_input( INPUT_POST, 'field_id' );
51
- $attachment_id = (int) filter_input( INPUT_POST, 'attachment_id', FILTER_SANITIZE_NUMBER_INT );
52
-
53
  check_ajax_referer( "rwmb-delete-file_{$field_id}" );
54
- if ( wp_delete_attachment( $attachment_id ) ) {
 
 
 
 
 
 
 
 
 
55
  wp_send_json_success();
56
  }
57
  wp_send_json_error( __( 'Error: Cannot delete file', 'meta-box' ) );
@@ -97,10 +104,11 @@ class RWMB_File_Field extends RWMB_Field {
97
 
98
  foreach ( (array) $files as $k => $file ) {
99
  // Ignore deleted files (if users accidentally deleted files or uses `force_delete` without saving post).
100
- if ( get_attached_file( $file ) ) {
101
  $output .= self::call( $field, 'file_html', $file, $k );
102
  }
103
  }
 
104
  return sprintf(
105
  '<ul class="rwmb-uploaded" data-field_id="%s" data-delete_nonce="%s" data-reorder_nonce="%s" data-force_delete="%s" data-max_file_uploads="%s" data-mime_type="%s">%s</ul>',
106
  $field['id'],
@@ -125,8 +133,22 @@ class RWMB_File_Field extends RWMB_Field {
125
  $i18n_delete = apply_filters( 'rwmb_file_delete_string', _x( 'Delete', 'file upload', 'meta-box' ) );
126
  $i18n_edit = apply_filters( 'rwmb_file_edit_string', _x( 'Edit', 'file upload', 'meta-box' ) );
127
  $attributes = self::get_attributes( $field, $file );
128
- $path = get_attached_file( $file );
129
- $icon = wp_get_attachment_image( $file, array( 60, 60 ), true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  return sprintf(
132
  '<li class="rwmb-file">
@@ -135,19 +157,18 @@ class RWMB_File_Field extends RWMB_Field {
135
  <a href="%s" target="_blank" class="rwmb-file-title">%s</a>
136
  <p class="rwmb-file-name">%s</p>
137
  <p class="rwmb-file-actions">
138
- <a href="%s" class="rwmb-file-edit" target="_blank"><span class="dashicons dashicons-edit"></span>%s</a>
139
  <a href="#" class="rwmb-file-delete" data-attachment_id="%s"><span class="dashicons dashicons-no-alt"></span>%s</a>
140
  </p>
141
  </div>
142
  <input type="hidden" name="%s[%s]" value="%s">
143
  </li>',
144
- wp_get_attachment_url( $file ),
145
- $icon,
146
- wp_get_attachment_url( $file ),
147
- get_the_title( $file ),
148
- basename( $path ),
149
- get_edit_post_link( $file ),
150
- $i18n_edit,
151
  $file,
152
  $i18n_delete,
153
  $attributes['name'],
@@ -156,6 +177,28 @@ class RWMB_File_Field extends RWMB_Field {
156
  );
157
  }
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  /**
160
  * Get meta values to save.
161
  *
@@ -180,11 +223,12 @@ class RWMB_File_Field extends RWMB_Field {
180
  if ( ! $field['clone'] ) {
181
  $count = self::transform( $input );
182
  for ( $i = 0; $i <= $count; $i ++ ) {
183
- $attachment = media_handle_upload( "{$input}_{$i}", $post_id );
184
- if ( ! is_wp_error( $attachment ) ) {
185
  $new[] = $attachment;
186
  }
187
  }
 
188
  return $new;
189
  }
190
 
@@ -195,8 +239,8 @@ class RWMB_File_Field extends RWMB_Field {
195
  $new[ $clone_index ] = array();
196
  }
197
  for ( $i = 0; $i <= $count; $i ++ ) {
198
- $attachment = media_handle_upload( "{$input}_{$clone_index}_{$i}", $post_id );
199
- if ( ! is_wp_error( $attachment ) ) {
200
  $new[ $clone_index ][] = $attachment;
201
  }
202
  }
@@ -205,6 +249,20 @@ class RWMB_File_Field extends RWMB_Field {
205
  return $new;
206
  }
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  /**
209
  * Transform $_FILES from $_FILES['field']['key']['index'] to $_FILES['field_index']['key'].
210
  *
@@ -273,6 +331,7 @@ class RWMB_File_Field extends RWMB_Field {
273
  'force_delete' => false,
274
  'max_file_uploads' => 0,
275
  'mime_type' => '',
 
276
  )
277
  );
278
  $field['multiple'] = true;
@@ -330,12 +389,17 @@ class RWMB_File_Field extends RWMB_Field {
330
  /**
331
  * Get uploaded file information.
332
  *
333
- * @param int $file Attachment file ID (post ID). Required.
334
- * @param array $args Array of arguments (for size).
 
335
  *
336
  * @return array|bool False if file not found. Array of (id, name, path, url) on success.
337
  */
338
- public static function file_info( $file, $args = array() ) {
 
 
 
 
339
  $path = get_attached_file( $file );
340
  if ( ! $path ) {
341
  return false;
@@ -366,4 +430,52 @@ class RWMB_File_Field extends RWMB_Field {
366
  public static function format_single_value( $field, $value, $args, $post_id ) {
367
  return sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $value['url'] ), esc_html( $value['title'] ) );
368
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  }
47
  * Ajax callback for deleting files.
48
  */
49
  public static function ajax_delete_file() {
50
+ $field_id = filter_input( INPUT_POST, 'field_id', FILTER_SANITIZE_STRING );
 
 
51
  check_ajax_referer( "rwmb-delete-file_{$field_id}" );
52
+
53
+ $attachment = filter_input( INPUT_POST, 'attachment_id' );
54
+ if ( is_numeric( $attachment ) ) {
55
+ $result = wp_delete_attachment( $attachment );
56
+ } else {
57
+ $path = str_replace( home_url( '/' ), ABSPATH . '/', $attachment );
58
+ $result = unlink( $path );
59
+ }
60
+
61
+ if ( $result ) {
62
  wp_send_json_success();
63
  }
64
  wp_send_json_error( __( 'Error: Cannot delete file', 'meta-box' ) );
104
 
105
  foreach ( (array) $files as $k => $file ) {
106
  // Ignore deleted files (if users accidentally deleted files or uses `force_delete` without saving post).
107
+ if ( get_attached_file( $file ) || $field['upload_dir'] ) {
108
  $output .= self::call( $field, 'file_html', $file, $k );
109
  }
110
  }
111
+
112
  return sprintf(
113
  '<ul class="rwmb-uploaded" data-field_id="%s" data-delete_nonce="%s" data-reorder_nonce="%s" data-force_delete="%s" data-max_file_uploads="%s" data-mime_type="%s">%s</ul>',
114
  $field['id'],
133
  $i18n_delete = apply_filters( 'rwmb_file_delete_string', _x( 'Delete', 'file upload', 'meta-box' ) );
134
  $i18n_edit = apply_filters( 'rwmb_file_edit_string', _x( 'Edit', 'file upload', 'meta-box' ) );
135
  $attributes = self::get_attributes( $field, $file );
136
+
137
+ if ( ! $file ) {
138
+ return;
139
+ }
140
+
141
+ if ( $field['upload_dir'] ) {
142
+ $data = self::file_info_custom_dir( $file, $field );
143
+ } else {
144
+ $data = array(
145
+ 'icon' => wp_get_attachment_image( $file, array( 60, 60 ), true ),
146
+ 'name' => basename( get_attached_file( $file ) ),
147
+ 'url' => wp_get_attachment_url( $file ),
148
+ 'title' => get_the_title( $file ),
149
+ 'edit_link' => sprintf( '<a href="%s" class="rwmb-file-edit" target="_blank"><span class="dashicons dashicons-edit"></span>%s</a>', get_edit_post_link( $file ), $i18n_edit ),
150
+ );
151
+ }
152
 
153
  return sprintf(
154
  '<li class="rwmb-file">
157
  <a href="%s" target="_blank" class="rwmb-file-title">%s</a>
158
  <p class="rwmb-file-name">%s</p>
159
  <p class="rwmb-file-actions">
160
+ %s
161
  <a href="#" class="rwmb-file-delete" data-attachment_id="%s"><span class="dashicons dashicons-no-alt"></span>%s</a>
162
  </p>
163
  </div>
164
  <input type="hidden" name="%s[%s]" value="%s">
165
  </li>',
166
+ $data['url'],
167
+ $data['icon'],
168
+ $data['url'],
169
+ $data['title'],
170
+ $data['name'],
171
+ $data['edit_link'],
 
172
  $file,
173
  $i18n_delete,
174
  $attributes['name'],
177
  );
178
  }
179
 
180
+ /**
181
+ * Get file data uploaded to custom directory.
182
+ *
183
+ * @param string $file URL to uploaded file.
184
+ * @param array $field Field settings.
185
+ * @return string
186
+ */
187
+ protected static function file_info_custom_dir( $file, $field ) {
188
+ $path = wp_normalize_path( trailingslashit( $field['upload_dir'] ) . basename( $file ) );
189
+ $ext = pathinfo( $path, PATHINFO_EXTENSION );
190
+ $icon_url = wp_mime_type_icon( wp_ext2type( $ext ) );
191
+ $data = array(
192
+ 'icon' => '<img width="48" height="64" src="' . esc_url( $icon_url ) . '" alt="">',
193
+ 'name' => basename( $path ),
194
+ 'path' => $path,
195
+ 'url' => $file,
196
+ 'title' => preg_replace( '/\.[^.]+$/', '', basename( $path ) ),
197
+ 'edit_link' => '',
198
+ );
199
+ return $data;
200
+ }
201
+
202
  /**
203
  * Get meta values to save.
204
  *
223
  if ( ! $field['clone'] ) {
224
  $count = self::transform( $input );
225
  for ( $i = 0; $i <= $count; $i ++ ) {
226
+ $attachment = self::handle_upload( "{$input}_{$i}", $post_id, $field );
227
+ if ( $attachment && ! is_wp_error( $attachment ) ) {
228
  $new[] = $attachment;
229
  }
230
  }
231
+
232
  return $new;
233
  }
234
 
239
  $new[ $clone_index ] = array();
240
  }
241
  for ( $i = 0; $i <= $count; $i ++ ) {
242
+ $attachment = self::handle_upload( "{$input}_{$clone_index}_{$i}", $post_id, $field );
243
+ if ( $attachment && ! is_wp_error( $attachment ) ) {
244
  $new[ $clone_index ][] = $attachment;
245
  }
246
  }
249
  return $new;
250
  }
251
 
252
+ /**
253
+ * Handle file upload.
254
+ * Consider upload to Media Library or custom folder.
255
+ *
256
+ * @param string $file_id File ID in $_FILES when uploading.
257
+ * @param int $post_id Post ID.
258
+ * @param array $field Field settings.
259
+ *
260
+ * @return \WP_Error|int|string WP_Error if has error, attachment ID if upload in Media Library, URL to file if upload to custom folder.
261
+ */
262
+ protected static function handle_upload( $file_id, $post_id, $field ) {
263
+ return $field['upload_dir'] ? self::handle_upload_custom_dir( $file_id, $post_id, $field ) : media_handle_upload( $file_id, $post_id );
264
+ }
265
+
266
  /**
267
  * Transform $_FILES from $_FILES['field']['key']['index'] to $_FILES['field_index']['key'].
268
  *
331
  'force_delete' => false,
332
  'max_file_uploads' => 0,
333
  'mime_type' => '',
334
+ 'upload_dir' => '',
335
  )
336
  );
337
  $field['multiple'] = true;
389
  /**
390
  * Get uploaded file information.
391
  *
392
+ * @param int $file Attachment file ID (post ID). Required.
393
+ * @param array $args Array of arguments (for size).
394
+ * @param array $field Field settings.
395
  *
396
  * @return array|bool False if file not found. Array of (id, name, path, url) on success.
397
  */
398
+ public static function file_info( $file, $args = array(), $field ) {
399
+ if ( $field['upload_dir'] ) {
400
+ return self::file_info_custom_dir( $file, $field );
401
+ }
402
+
403
  $path = get_attached_file( $file );
404
  if ( ! $path ) {
405
  return false;
430
  public static function format_single_value( $field, $value, $args, $post_id ) {
431
  return sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $value['url'] ), esc_html( $value['title'] ) );
432
  }
433
+
434
+ /**
435
+ * Handle upload for files in custom directory.
436
+ *
437
+ * @param string $file_id File ID in $_FILES when uploading.
438
+ * @param int $post_id Post ID.
439
+ * @param array $field Field settings.
440
+ *
441
+ * @return string URL to uploaded file.
442
+ */
443
+ public static function handle_upload_custom_dir( $file_id, $post_id, $field ) {
444
+ // @codingStandardsIgnoreStart
445
+ if ( ! isset( $_FILES[ $file_id ] ) ) {
446
+ return;
447
+ }
448
+ $file = $_FILES[ $file_id ];
449
+ if ( UPLOAD_ERR_OK !== $file['error'] || ! $file['tmp_name'] ) {
450
+ return;
451
+ }
452
+ // @codingStandardsIgnoreEnd
453
+
454
+ if ( ! file_exists( $field['upload_dir'] ) ) {
455
+ wp_mkdir_p( $field['upload_dir'] );
456
+ }
457
+ if ( ! is_dir( $field['upload_dir'] ) || ! is_writable( $field['upload_dir'] ) ) {
458
+ return;
459
+ }
460
+
461
+ $file_name = wp_unique_filename( $field['upload_dir'], basename( $file['name'] ) );
462
+ $path = trailingslashit( $field['upload_dir'] ) . $file_name;
463
+ move_uploaded_file( $file['tmp_name'], $path );
464
+
465
+ return self::convert_path_to_url( $path );
466
+ }
467
+
468
+ /**
469
+ * Convert a path to an URL.
470
+ *
471
+ * @param string $path Full path to a file or a directory.
472
+ * @return string URL to the file or directory.
473
+ */
474
+ public static function convert_path_to_url( $path ) {
475
+ $path = wp_normalize_path( untrailingslashit( $path ) );
476
+ $root = wp_normalize_path( untrailingslashit( ABSPATH ) );
477
+ $relative_path = str_replace( $root, '', $path );
478
+
479
+ return home_url( $relative_path );
480
+ }
481
  }
inc/fields/image-advanced.php CHANGED
@@ -61,11 +61,13 @@ class RWMB_Image_Advanced_Field extends RWMB_Media_Field {
61
  /**
62
  * Get uploaded file information.
63
  *
64
- * @param int $file Attachment image ID (post ID). Required.
65
- * @param array $args Array of arguments (for size).
 
 
66
  * @return array|bool False if file not found. Array of image info on success.
67
  */
68
- public static function file_info( $file, $args = array() ) {
69
  return RWMB_Image_Field::file_info( $file, $args );
70
  }
71
 
61
  /**
62
  * Get uploaded file information.
63
  *
64
+ * @param int $file Attachment image ID (post ID). Required.
65
+ * @param array $args Array of arguments (for size).
66
+ * @param array $field Field settings.
67
+ *
68
  * @return array|bool False if file not found. Array of image info on success.
69
  */
70
+ public static function file_info( $file, $args = array(), $field ) {
71
  return RWMB_Image_Field::file_info( $file, $args );
72
  }
73
 
inc/fields/image.php CHANGED
@@ -99,12 +99,13 @@ class RWMB_Image_Field extends RWMB_File_Field {
99
  /**
100
  * Get uploaded file information.
101
  *
102
- * @param int $file Attachment image ID (post ID). Required.
103
- * @param array $args Array of arguments (for size).
 
104
  *
105
  * @return array|bool False if file not found. Array of image info on success.
106
  */
107
- public static function file_info( $file, $args = array() ) {
108
  $path = get_attached_file( $file );
109
  if ( ! $path ) {
110
  return false;
99
  /**
100
  * Get uploaded file information.
101
  *
102
+ * @param int $file Attachment image ID (post ID). Required.
103
+ * @param array $args Array of arguments (for size).
104
+ * @param array $field Field settings.
105
  *
106
  * @return array|bool False if file not found. Array of image info on success.
107
  */
108
+ public static function file_info( $file, $args = array(), $field ) {
109
  $path = get_attached_file( $file );
110
  if ( ! $path ) {
111
  return false;
inc/fields/post.php CHANGED
@@ -77,6 +77,14 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field {
77
  'update_post_term_cache' => false,
78
  )
79
  );
 
 
 
 
 
 
 
 
80
  $query = new WP_Query( $args );
81
  $options = array();
82
  foreach ( $query->posts as $post ) {
@@ -89,6 +97,10 @@ class RWMB_Post_Field extends RWMB_Object_Choice_Field {
89
  (array) $post
90
  );
91
  }
 
 
 
 
92
  return $options;
93
  }
94
 
77
  'update_post_term_cache' => false,
78
  )
79
  );
80
+
81
+ // Get from cache to prevent same queries.
82
+ $cache_key = md5( serialize( $args ) );
83
+ $options = wp_cache_get( $cache_key, 'meta-box-post-field' );
84
+ if ( false !== $options ) {
85
+ return $options;
86
+ }
87
+
88
  $query = new WP_Query( $args );
89
  $options = array();
90
  foreach ( $query->posts as $post ) {
97
  (array) $post
98
  );
99
  }
100
+
101
+ // Cache the query.
102
+ wp_cache_set( $cache_key, $options, 'meta-box-post-field' );
103
+
104
  return $options;
105
  }
106
 
inc/fields/user.php CHANGED
@@ -48,6 +48,14 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field {
48
  'fields' => array( 'ID', $display_field ),
49
  )
50
  );
 
 
 
 
 
 
 
 
51
  $users = get_users( $args );
52
  $options = array();
53
  foreach ( $users as $user ) {
@@ -59,6 +67,10 @@ class RWMB_User_Field extends RWMB_Object_Choice_Field {
59
  (array) $user
60
  );
61
  }
 
 
 
 
62
  return $options;
63
  }
64
 
48
  'fields' => array( 'ID', $display_field ),
49
  )
50
  );
51
+
52
+ // Get from cache to prevent same queries.
53
+ $cache_key = md5( serialize( $args ) );
54
+ $options = wp_cache_get( $cache_key, 'meta-box-user-field' );
55
+ if ( false !== $options ) {
56
+ return $options;
57
+ }
58
+
59
  $users = get_users( $args );
60
  $options = array();
61
  foreach ( $users as $user ) {
67
  (array) $user
68
  );
69
  }
70
+
71
+ // Cache the query.
72
+ wp_cache_set( $cache_key, $options, 'meta-box-user-field' );
73
+
74
  return $options;
75
  }
76
 
inc/fields/video.php CHANGED
@@ -45,10 +45,11 @@ class RWMB_Video_Field extends RWMB_Media_Field {
45
  *
46
  * @param int $file_id Attachment image ID (post ID). Required.
47
  * @param array $args Array of arguments (for size).
 
48
  *
49
  * @return array|bool False if file not found. Array of image info on success.
50
  */
51
- public static function file_info( $file_id, $args = array() ) {
52
  if ( ! get_attached_file( $file_id ) ) {
53
  return false;
54
  }
45
  *
46
  * @param int $file_id Attachment image ID (post ID). Required.
47
  * @param array $args Array of arguments (for size).
48
+ * @param array $field Field settings.
49
  *
50
  * @return array|bool False if file not found. Array of image info on success.
51
  */
52
+ public static function file_info( $file_id, $args = array(), $field ) {
53
  if ( ! get_attached_file( $file_id ) ) {
54
  return false;
55
  }
inc/loader.php CHANGED
@@ -18,7 +18,7 @@ class RWMB_Loader {
18
  */
19
  protected function constants() {
20
  // Script version, used to add version for scripts and styles.
21
- define( 'RWMB_VER', '4.15.9' );
22
 
23
  list( $path, $url ) = self::get_path( dirname( dirname( __FILE__ ) ) );
24
 
@@ -86,8 +86,10 @@ class RWMB_Loader {
86
  $core = new RWMB_Core();
87
  $core->init();
88
 
89
- $about = new RWMB_About();
90
- $about->init();
 
 
91
 
92
  // Validation module.
93
  new RWMB_Validation();
18
  */
19
  protected function constants() {
20
  // Script version, used to add version for scripts and styles.
21
+ define( 'RWMB_VER', '4.16.0' );
22
 
23
  list( $path, $url ) = self::get_path( dirname( dirname( __FILE__ ) ) );
24
 
86
  $core = new RWMB_Core();
87
  $core->init();
88
 
89
+ if ( is_admin() ) {
90
+ $about = new RWMB_About();
91
+ $about->init();
92
+ }
93
 
94
  // Validation module.
95
  new RWMB_Validation();
js/media.js CHANGED
@@ -215,14 +215,17 @@ jQuery( function ( $ ) {
215
  },
216
  function ( item ) {
217
  return item.cid;
218
- } );
 
219
 
220
  this.listenTo( this.collection, 'add', this.addItemView );
221
  this.listenTo( this.collection, 'remove', this.removeItemView );
222
  this.listenTo( this.collection, 'reset', this.resetItemViews );
223
 
224
- // Sort media using sortable
225
- this.initSortable();
 
 
226
  },
227
 
228
  listenToItemView: function ( itemView ) {
@@ -321,37 +324,6 @@ jQuery( function ( $ ) {
321
  } );
322
 
323
  this._editFrame.open();
324
- },
325
-
326
- initSortable: function () {
327
- var collection = this.controller.get( 'items' );
328
- this.$el.sortable( {
329
- // Clone the element and the clone will be dragged. Prevent trigger click on the image, which means reselect.
330
- helper : 'clone',
331
-
332
- // Record the initial `index` of the dragged model.
333
- start: function ( event, ui ) {
334
- ui.item.data( 'sortableIndexStart', ui.item.index() );
335
- },
336
-
337
- // Update the model's index in the collection.
338
- // Do so silently, as the view is already accurate.
339
- update: function ( event, ui ) {
340
- var model = collection.at( ui.item.data( 'sortableIndexStart' ) );
341
-
342
- // Silently shift the model to its new index.
343
- collection.remove( model, {
344
- silent: true
345
- } );
346
- collection.add( model, {
347
- silent: true,
348
- at: ui.item.index()
349
- } );
350
-
351
- // Fire the `reset` event to ensure other collections sync.
352
- collection.trigger( 'reset', collection );
353
- }
354
- } );
355
  }
356
  } );
357
 
@@ -458,9 +430,8 @@ jQuery( function ( $ ) {
458
  this.$el.data( 'id', this.model.cid );
459
  },
460
 
461
-
462
  events: {
463
- 'click .rwmb-overlay': function () {
464
  this.trigger( 'click:switch', this.model );
465
  return false;
466
  },
215
  },
216
  function ( item ) {
217
  return item.cid;
218
+ }
219
+ );
220
 
221
  this.listenTo( this.collection, 'add', this.addItemView );
222
  this.listenTo( this.collection, 'remove', this.removeItemView );
223
  this.listenTo( this.collection, 'reset', this.resetItemViews );
224
 
225
+ // Sort items using helper 'clone' to prevent trigger click on the image, which means reselect.
226
+ this.$el.sortable( {
227
+ helper : 'clone'
228
+ } );
229
  },
230
 
231
  listenToItemView: function ( itemView ) {
324
  } );
325
 
326
  this._editFrame.open();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  }
328
  } );
329
 
430
  this.$el.data( 'id', this.model.cid );
431
  },
432
 
 
433
  events: {
434
+ 'click .rwmb-image-overlay': function () {
435
  this.trigger( 'click:switch', this.model );
436
  return false;
437
  },
js/osm.js CHANGED
@@ -1,10 +1,6 @@
1
  ( function( $, L ) {
2
  'use strict';
3
 
4
- var osmTileLayer = L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
5
- attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
6
- } );
7
-
8
  // Use function construction to store map & DOM elements separately for each instance
9
  var OsmField = function ( $container ) {
10
  this.$container = $container;
@@ -43,7 +39,9 @@
43
  center: latLng,
44
  zoom: 14
45
  } );
46
- this.map.addLayer( osmTileLayer );
 
 
47
  this.marker = L.marker( latLng, {
48
  draggable: true
49
  } ).addTo( this.map );
1
  ( function( $, L ) {
2
  'use strict';
3
 
 
 
 
 
4
  // Use function construction to store map & DOM elements separately for each instance
5
  var OsmField = function ( $container ) {
6
  this.$container = $container;
39
  center: latLng,
40
  zoom: 14
41
  } );
42
+ L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
43
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
44
+ } ).addTo( this.map );
45
  this.marker = L.marker( latLng, {
46
  draggable: true
47
  } ).addTo( this.map );
js/select-tree.js CHANGED
@@ -1,19 +1,45 @@
1
  jQuery( function ( $ ) {
2
  'use strict';
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  function update() {
5
  var $this = $( this ),
6
  val = $this.val(),
7
  $selected = $this.siblings( "[data-parent-id='" + val + "']" ),
8
- $notSelected = $this.parent().find( '.rwmb-select-tree' ).not( $selected );
 
 
 
 
 
 
9
 
10
- $selected.removeClass( 'hidden' );
11
- $notSelected
12
- .addClass( 'hidden' )
13
- .find( 'select' )
14
- .prop( 'selectedIndex', 0 );
15
  }
16
 
 
 
17
  $( '.rwmb-input' )
18
  .on( 'change', '.rwmb-select-tree select', update )
19
  .on( 'clone', '.rwmb-select-tree select', update );
1
  jQuery( function ( $ ) {
2
  'use strict';
3
 
4
+ function setInitialRequiredProp() {
5
+ var $this = $( this ),
6
+ required = $this.prop( 'required' );
7
+
8
+ if ( required ) {
9
+ $this.data( 'initial-required', required );
10
+ }
11
+ }
12
+
13
+ function unsetRequiredProp() {
14
+ $( this ).prop( 'required', false );
15
+ }
16
+
17
+ function setRequiredProp() {
18
+ var $this = $( this );
19
+
20
+ if ( $this.data( 'initial-required' ) ) {
21
+ $this.prop( 'required', true );
22
+ }
23
+ }
24
+
25
  function update() {
26
  var $this = $( this ),
27
  val = $this.val(),
28
  $selected = $this.siblings( "[data-parent-id='" + val + "']" ),
29
+ $notSelected = $this.siblings().not( $selected ),
30
+ options = $this.data( 'options' );
31
+
32
+ // Turn select into beautiful select2.
33
+ $this.removeClass( 'select2-hidden-accessible' );
34
+ $this.siblings( '.select2-container' ).remove();
35
+ $this.show().select2( options );
36
 
37
+ $selected.removeClass( 'hidden' ).find( 'select' ).each( setRequiredProp );
38
+ $notSelected.addClass( 'hidden' ).find( 'select' ).each( unsetRequiredProp ).prop( 'selectedIndex', 0 );
 
 
 
39
  }
40
 
41
+ $( '.rwmb-select-tree select' ).select2();
42
+ $( '.rwmb-select-tree select' ).each( setInitialRequiredProp );
43
  $( '.rwmb-input' )
44
  .on( 'change', '.rwmb-select-tree select', update )
45
  .on( 'clone', '.rwmb-select-tree select', update );
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: 4.15.9
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: 4.16.0
7
  * Author: MetaBox.io
8
  * Author URI: https://metabox.io
9
  * License: GPL2+
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: metabox, rilwis, fitwp, f-j-kaiser, funkatronic, PerWiklander, rua
3
  Donate link: https://metabox.io/pricing/
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.3
6
- Tested up to: 5.0
7
- Stable tag: 4.15.9
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional developer toolkit to create custom meta boxes and custom fields for WordPress.
3
  Donate link: https://metabox.io/pricing/
4
  Tags: meta-box, custom fields, custom field, meta, meta-boxes, admin, advanced, custom, edit, field, file, image, magic fields, matrix, more fields, Post, repeater, simple fields, text, textarea, type, cms, fields post
5
  Requires at least: 4.3
6
+ Tested up to: 5.0.3
7
+ Stable tag: 4.16.0
8
  License: GPLv2 or later
9
 
10
  Meta Box plugin is a powerful, professional developer toolkit to create custom meta boxes and custom fields for WordPress.