| @@ -20,8 +20,16 @@ | ||
| 20 | 20 | */ |
| 21 | 21 | class CMB2 extends CMB2_Base { |
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | + * Supported CMB2 object types | |
| 25 | + * | |
| 26 | + * @var array | |
| 27 | + * @since 2.11.0 | |
| 28 | + */ | |
| 29 | + protected $core_object_types = array( 'post', 'user', 'comment', 'term', 'options-page' ); | |
| 30 | + | |
| 31 | + /** | |
| 24 | 32 | * The object properties name. |
| 25 | 33 | * |
| 26 | 34 | * @var string |
| 27 | 35 | * @since 2.2.3 |
| @@ -373,9 +381,9 @@ | ||
| 373 | 381 | $split = array(); |
| 374 | 382 | foreach ( array_filter( $classes ) as $class ) { |
| 375 | 383 | foreach ( explode( ' ', $class ) as $_class ) { |
| 376 | 384 | // Clean up & sanitize. |
| 377 | - $split[] = sanitize_html_class( strip_tags( $_class ) ); | |
| 385 | + $split[] = sanitize_html_class( wp_strip_all_tags( $_class ) ); | |
| 378 | 386 | } |
| 379 | 387 | } |
| 380 | 388 | $classes = $split; |
| 381 | 389 | |
| @@ -531,9 +539,10 @@ | ||
| 531 | 539 | echo '</div></div>'; |
| 532 | 540 | } |
| 533 | 541 | |
| 534 | 542 | if ( ! empty( $group_val ) ) { |
| 535 | - foreach ( $group_val as $group_key => $field_id ) { | |
| 543 | + $group_val_count = count( $group_val ); | |
| 544 | + for ( $i = 0; $i < $group_val_count; $i++ ) { | |
| 536 | 545 | $this->render_group_row( $field_group ); |
| 537 | 546 | $field_group->index++; |
| 538 | 547 | } |
| 539 | 548 | } else { |
| @@ -582,9 +591,9 @@ | ||
| 582 | 591 | |
| 583 | 592 | $atts = array(); |
| 584 | 593 | foreach ( $group_wrap_attributes as $att => $att_value ) { |
| 585 | 594 | if ( ! CMB2_Utils::is_data_attribute( $att ) ) { |
| 586 | - $att_value = htmlspecialchars( $att_value ); | |
| 595 | + $att_value = htmlspecialchars( $att_value, ENT_COMPAT ); | |
| 587 | 596 | } |
| 588 | 597 | |
| 589 | 598 | $atts[ sanitize_html_class( $att ) ] = sanitize_text_field( $att_value ); |
| 590 | 599 | } |
| @@ -614,9 +623,9 @@ | ||
| 614 | 623 | echo '<button type="button" data-selector="', $field_group->id(), '_repeat" data-confirm="', esc_attr( $confirm_deletion ), '" class="dashicons-before dashicons-no-alt cmb-remove-group-row" title="', esc_attr( $field_group->options( 'remove_button' ) ), '"></button>'; |
| 615 | 624 | } |
| 616 | 625 | |
| 617 | 626 | echo ' |
| 618 | - <div class="cmbhandle" title="' , esc_attr__( 'Click to toggle', 'cmb2' ), '"><br></div> | |
| 627 | + <div class="cmbhandle" title="', esc_attr__( 'Click to toggle', 'cmb2' ), '"><br></div> | |
| 619 | 628 | <h3 class="cmb-group-title cmbhandle-title"><span>', $field_group->replace_hash( $field_group->options( 'group_title' ) ), '</span></h3> |
| 620 | 629 | |
| 621 | 630 | <div class="inside cmb-td cmb-nested cmb-field-list">'; |
| 622 | 631 | // Loop and render repeatable group fields. |
| @@ -926,9 +935,9 @@ | ||
| 926 | 935 | if ( ! isset( $this->data_to_save[ $base_id ] ) ) { |
| 927 | 936 | return; |
| 928 | 937 | } |
| 929 | 938 | |
| 930 | - $old = $field_group->get_data(); | |
| 939 | + $old = $field_group->get_data(); | |
| 931 | 940 | // Check if group field has sanitization_cb. |
| 932 | 941 | $group_vals = $field_group->sanitization_cb( $this->data_to_save[ $base_id ] ); |
| 933 | 942 | $saved = array(); |
| 934 | 943 | |
| @@ -1048,10 +1057,20 @@ | ||
| 1048 | 1057 | $object_id = isset( $_REQUEST['post'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post'] ) ) : $object_id; |
| 1049 | 1058 | break; |
| 1050 | 1059 | } |
| 1051 | 1060 | |
| 1061 | + /** | |
| 1062 | + * Filter the object id. | |
| 1063 | + * | |
| 1064 | + * @since 2.11.0 | |
| 1065 | + * | |
| 1066 | + * @param integer|string $object_id Object ID. | |
| 1067 | + * @param CMB2 $cmb This CMB2 object. | |
| 1068 | + */ | |
| 1069 | + $object_id = apply_filters( 'cmb2_set_object_id', $object_id, $this ); | |
| 1070 | + | |
| 1052 | 1071 | // reset to id or 0. |
| 1053 | - $this->object_id = $object_id ? $object_id : 0; | |
| 1072 | + $this->object_id = ! empty( $object_id ) ? $object_id : 0; | |
| 1054 | 1073 | |
| 1055 | 1074 | return $this->object_id; |
| 1056 | 1075 | } |
| 1057 | 1076 | |
| @@ -1065,41 +1084,45 @@ | ||
| 1065 | 1084 | if ( null !== $this->mb_object_type ) { |
| 1066 | 1085 | return $this->mb_object_type; |
| 1067 | 1086 | } |
| 1068 | 1087 | |
| 1088 | + $found_type = ''; | |
| 1089 | + | |
| 1069 | 1090 | if ( $this->is_options_page_mb() ) { |
| 1070 | - $this->mb_object_type = 'options-page'; | |
| 1071 | - return $this->mb_object_type; | |
| 1072 | - } | |
| 1091 | + $found_type = 'options-page'; | |
| 1092 | + } else { | |
| 1093 | + $registered_types = $this->box_types(); | |
| 1073 | 1094 | |
| 1074 | - $registered_types = $this->box_types(); | |
| 1075 | - | |
| 1076 | - $type = ''; | |
| 1077 | - | |
| 1078 | - // if it's an array of one, extract it. | |
| 1079 | - if ( 1 === count( $registered_types ) ) { | |
| 1080 | - $last = end( $registered_types ); | |
| 1081 | - if ( is_string( $last ) ) { | |
| 1082 | - $type = $last; | |
| 1095 | + // if it's an array of one, extract it. | |
| 1096 | + if ( 1 === count( $registered_types ) ) { | |
| 1097 | + $last = end( $registered_types ); | |
| 1098 | + if ( is_string( $last ) ) { | |
| 1099 | + $found_type = $last; | |
| 1100 | + } | |
| 1101 | + } else { | |
| 1102 | + $current_object_type = $this->current_object_type(); | |
| 1103 | + if ( in_array( $current_object_type, $registered_types, true ) ) { | |
| 1104 | + $found_type = $current_object_type; | |
| 1105 | + } | |
| 1083 | 1106 | } |
| 1084 | - } elseif ( ( $curr_type = $this->current_object_type() ) && in_array( $curr_type, $registered_types, true ) ) { | |
| 1085 | - $type = $curr_type; | |
| 1086 | 1107 | } |
| 1087 | 1108 | |
| 1088 | 1109 | // Get our object type. |
| 1089 | - switch ( $type ) { | |
| 1110 | + $mb_object_type = $this->is_supported_core_object_type( $found_type ) | |
| 1111 | + ? $found_type | |
| 1112 | + : 'post'; | |
| 1090 | 1113 | |
| 1091 | - case 'user': | |
| 1092 | - case 'comment': | |
| 1093 | - case 'term': | |
| 1094 | - $this->mb_object_type = $type; | |
| 1095 | - break; | |
| 1114 | + /** | |
| 1115 | + * Filter the metabox object type. | |
| 1116 | + * | |
| 1117 | + * @since 2.11.0 | |
| 1118 | + * | |
| 1119 | + * @param string $mb_object_type The metabox object type. | |
| 1120 | + * @param string $found_type The found object type. | |
| 1121 | + * @param CMB2 $cmb This CMB2 object. | |
| 1122 | + */ | |
| 1123 | + $this->mb_object_type = apply_filters( 'cmb2_set_box_object_type', $mb_object_type, $found_type, $this ); | |
| 1096 | 1124 | |
| 1097 | - default: | |
| 1098 | - $this->mb_object_type = 'post'; | |
| 1099 | - break; | |
| 1100 | - } | |
| 1101 | - | |
| 1102 | 1125 | return $this->mb_object_type; |
| 1103 | 1126 | } |
| 1104 | 1127 | |
| 1105 | 1128 | /** |
| @@ -1549,35 +1572,10 @@ | ||
| 1549 | 1572 | * @param array $field Metabox field config array. |
| 1550 | 1573 | * @return void |
| 1551 | 1574 | */ |
| 1552 | 1575 | protected function field_actions( $field ) { |
| 1553 | - switch ( $field['type'] ) { | |
| 1554 | - case 'file': | |
| 1555 | - case 'file_list': | |
| 1576 | + $field = CMB2_Hookup_Field::init( $field, $this ); | |
| 1556 | 1577 | |
| 1557 | - // Initiate attachment JS hooks. | |
| 1558 | - add_filter( 'wp_prepare_attachment_for_js', array( 'CMB2_Type_File_Base', 'prepare_image_sizes_for_js' ), 10, 3 ); | |
| 1559 | - break; | |
| 1560 | - | |
| 1561 | - case 'oembed': | |
| 1562 | - // Initiate oembed Ajax hooks. | |
| 1563 | - cmb2_ajax(); | |
| 1564 | - break; | |
| 1565 | - | |
| 1566 | - case 'group': | |
| 1567 | - if ( empty( $field['render_row_cb'] ) ) { | |
| 1568 | - $field['render_row_cb'] = array( $this, 'render_group_callback' ); | |
| 1569 | - } | |
| 1570 | - break; | |
| 1571 | - case 'colorpicker': | |
| 1572 | - | |
| 1573 | - // https://github.com/JayWood/CMB2_RGBa_Picker | |
| 1574 | - // Dequeue the rgba_colorpicker custom field script if it is used, | |
| 1575 | - // since we now enqueue our own more current version. | |
| 1576 | - add_action( 'admin_enqueue_scripts', array( 'CMB2_Type_Colorpicker', 'dequeue_rgba_colorpicker_script' ), 99 ); | |
| 1577 | - break; | |
| 1578 | - } | |
| 1579 | - | |
| 1580 | 1578 | if ( isset( $field['column'] ) && false !== $field['column'] ) { |
| 1581 | 1579 | $field = $this->define_field_column( $field ); |
| 1582 | 1580 | } |
| 1583 | 1581 | |
| @@ -1796,8 +1794,18 @@ | ||
| 1796 | 1794 | return $this->prop( 'context' ) && in_array( $this->prop( 'context' ), array( 'form_top', 'before_permalink', 'after_title', 'after_editor' ), true ); |
| 1797 | 1795 | } |
| 1798 | 1796 | |
| 1799 | 1797 | /** |
| 1798 | + * Whether given object type is one of the core supported object types. | |
| 1799 | + * | |
| 1800 | + * @since 2.11.0 | |
| 1801 | + * @return bool | |
| 1802 | + */ | |
| 1803 | + public function is_supported_core_object_type( $object_type ) { | |
| 1804 | + return in_array( $object_type, $this->core_object_types, true ); | |
| 1805 | + } | |
| 1806 | + | |
| 1807 | + /** | |
| 1800 | 1808 | * Magic getter for our object. |
| 1801 | 1809 | * |
| 1802 | 1810 | * @param string $property Object property. |
| 1803 | 1811 | * @throws Exception Throws an exception if the field is invalid. |
| @@ -1807,8 +1815,9 @@ | ||
| 1807 | 1815 | switch ( $property ) { |
| 1808 | 1816 | case 'updated': |
| 1809 | 1817 | case 'has_columns': |
| 1810 | 1818 | case 'tax_metaboxes_to_remove': |
| 1819 | + case 'core_object_types': | |
| 1811 | 1820 | return $this->{$property}; |
| 1812 | 1821 | default: |
| 1813 | 1822 | return parent::__get( $property ); |
| 1814 | 1823 | } |