├── mb-elementor-integrator.php └── src ├── CurrentWidget.php ├── GroupField.php ├── Loader.php ├── Tags ├── Archive │ ├── Image.php │ ├── Text.php │ └── Video.php ├── Post │ ├── Image.php │ ├── Text.php │ └── Video.php └── Settings │ ├── Image.php │ ├── Text.php │ └── Video.php ├── Templates ├── display_field-icon.php ├── display_field-image.php ├── display_field-post.php ├── display_field-taxonomy.php ├── display_field-text.php ├── display_field-url.php └── display_field-user.php ├── ThemeBuilder ├── Conditions │ ├── Group.php │ ├── MBField.php │ └── MBFields.php └── Documents │ └── Group.php ├── Traits ├── Archive.php ├── Base.php ├── Fields │ ├── Image.php │ ├── Text.php │ └── Video.php ├── Location.php ├── Post.php ├── Settings.php └── Skin.php ├── Widgets ├── GroupLocation.php ├── GroupSkin.php └── MBGroup.php └── assets └── images └── mbgroup.svg /mb-elementor-integrator.php: -------------------------------------------------------------------------------- 1 | . 25 | */ 26 | 27 | // Prevent loading this file directly. 28 | if ( ! defined( 'ABSPATH' ) ) { 29 | return; 30 | } 31 | 32 | if ( file_exists( __DIR__ . '/vendor' ) ) { 33 | require __DIR__ . '/vendor/autoload.php'; 34 | } 35 | 36 | if ( class_exists( 'MBEI\Loader' ) ) { 37 | new \MBEI\Loader(); 38 | } 39 | -------------------------------------------------------------------------------- /src/CurrentWidget.php: -------------------------------------------------------------------------------- 1 | get_name(); 14 | } 15 | 16 | public static function name() { 17 | return self::$name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/GroupField.php: -------------------------------------------------------------------------------- 1 | query['pagename'] ); 18 | $current_post = get_page_by_path( $slug, OBJECT, $post_type ); 19 | return $current_post; 20 | } 21 | 22 | public function get_skin_template() { 23 | 24 | $cache_key = 'mbei_skin_template'; 25 | $templates = wp_cache_get( $cache_key ); 26 | if ( false === $templates ) { 27 | $templates = get_posts( [ 28 | 'post_type' => 'elementor_library', 29 | 'numberposts' => -1, 30 | 'post_status' => 'publish', 31 | 'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query 32 | [ 33 | 'taxonomy' => 'elementor_library_type', 34 | 'field' => 'slug', 35 | 'terms' => 'metabox_group_template', 36 | ], 37 | ], 38 | ] ); 39 | wp_cache_set( $cache_key, $templates ); 40 | } 41 | 42 | $options = [ 0 => __( 'Select a skin', 'mb-elementor-integrator' ) ]; 43 | foreach ( $templates as $template ) { 44 | $options[ $template->ID ] = $template->post_title; 45 | } 46 | return $options; 47 | } 48 | 49 | public function get_placeholder_template( $template_id ) { 50 | $templates = $this->get_skin_template(); 51 | $template_name = strtolower( $templates[ $template_id ] ); 52 | return "{{ placeholder template $template_name }}"; 53 | } 54 | 55 | public function get_template_settings( $template_id = null ) { 56 | $template = $this->get_id_support_wpml( $template_id ); 57 | 58 | if ( ! $template ) { 59 | return; 60 | } 61 | 62 | // Get elements settings. 63 | $document = Plugin::instance()->documents->get( $template ); 64 | $settings = $document->get_elements_data(); 65 | 66 | return [ $settings, $template ]; 67 | } 68 | 69 | public function get_template( $template_id = null ) { 70 | // Get elements settings. 71 | list($settings, $template) = $this->get_template_settings( $template_id ); 72 | if ( ! $settings ) { 73 | return; 74 | } 75 | // Get data dynamic tags 76 | $dynamic_tags = []; 77 | $this->find_element_dynamic_tag( $settings, $dynamic_tags ); 78 | $sub_group = isset( $dynamic_tags['sub-group'] ) ? $dynamic_tags['sub-group'] : []; 79 | unset( $dynamic_tags['sub-group'] ); 80 | 81 | $data_replace = $this->dynamic_tag_to_data( $dynamic_tags, Plugin::instance()->dynamic_tags ); 82 | // Get Content Template. 83 | $content_template = Plugin::instance()->frontend->get_builder_content_for_display( $template, true ); 84 | 85 | if ( 0 < count( $sub_group ) ) { 86 | libxml_use_internal_errors( true ); 87 | $domTemplate = new \DOMDocument(); 88 | $domTemplate->loadHTML( $content_template ); 89 | libxml_clear_errors(); 90 | $xpath = new \DOMXpath( $domTemplate ); 91 | foreach ( $sub_group as $sub ) { 92 | $widget_sub = $xpath->query( '//div[@data-id="' . $sub['id'] . '"]//div[contains(@class,"mbei-sub-groups")]' ); 93 | if ( $widget_sub->length > 0 ) { 94 | $widget_node = $widget_sub->item( 0 ); 95 | 96 | $replacement = $domTemplate->createDocumentFragment(); 97 | $replacement->appendXML( '
' . $this->get_placeholder_template( $sub['template'] ) . '
' ); 98 | 99 | $widget_node->parentNode->replaceChild( $replacement, $widget_node ); 100 | $content_template = $domTemplate->saveHTML( $domTemplate->documentElement ); 101 | $content_template = str_replace( [ '', '', '', '', '', '' ], '', $content_template ); 102 | } 103 | } 104 | } 105 | 106 | return [ 107 | 'data' => $data_replace, 108 | 'content' => $content_template, 109 | ]; 110 | } 111 | 112 | private function dynamic_tag_to_data( $dynamic_tags = [], Manager $dynamic_tags_mageger = null ) { 113 | if ( empty( $dynamic_tags ) || empty( $dynamic_tags_mageger ) ) { 114 | return []; 115 | } 116 | 117 | $data_replace = []; 118 | foreach ( $dynamic_tags as $dynamic_tag ) { 119 | // Chek $dynamic_tag is array. 120 | if ( is_array( $dynamic_tag ) ) { 121 | $data_replace = array_merge( $data_replace, $this->dynamic_tag_to_data( $dynamic_tag, $dynamic_tags_mageger ) ); 122 | continue; 123 | } 124 | // Check $dynamic_tag is dynamic tag meta box. 125 | $tag_data = $dynamic_tags_mageger->tag_text_to_tag_data( $dynamic_tag ); 126 | if ( false === strpos( $tag_data['name'], 'meta-box-' ) ) { 127 | continue; 128 | } 129 | // Get tag content. 130 | $tag_data_content = $dynamic_tags_mageger->get_tag_data_content( $tag_data['id'], $tag_data['name'], $tag_data['settings'] ); 131 | list( $post_type, $key ) = explode( ':', $tag_data['settings']['key'], 2 ); 132 | if ( false !== strpos( $key, ':' ) ) { 133 | $key = explode( ':', $key, 2 ); 134 | $key = end( $key ); 135 | } 136 | 137 | if ( false !== strpos( $key, '.' ) ) { 138 | $key = explode( '.', $key, 2 ); 139 | $key = end( $key ); 140 | } 141 | 142 | if ( empty( $key ) ) { 143 | $key = $post_type; 144 | } 145 | 146 | if ( isset( $tag_data_content['url'] ) ) { 147 | $data_replace[ $key ]['content'] = self::change_url_ssl( $tag_data_content['url'] ); 148 | } elseif ( isset( $tag_data['settings']['mb_skin_template'] ) ) { 149 | $data_replace[ $key ]['content'] = $this->get_placeholder_template( $tag_data['settings']['mb_skin_template'] ); 150 | } else { 151 | $data_replace[ $key ]['content'] = $tag_data_content; 152 | } 153 | 154 | // Check tag Advanced 155 | if ( ! empty( $data_replace[ $key ]['content'] ) ) { 156 | if ( isset( $tag_data['settings']['before'] ) && ! empty( $tag_data['settings']['before'] ) ) { 157 | $data_replace[ $key ]['content'] = wp_kses_post( $tag_data['settings']['before'] ) . $data_replace[ $key ]['content']; 158 | } 159 | 160 | if ( isset( $tag_data['settings']['after'] ) && ! empty( $tag_data['settings']['after'] ) ) { 161 | $data_replace[ $key ]['content'] .= wp_kses_post( $tag_data['settings']['after'] ); 162 | } 163 | } elseif ( isset( $tag_data['settings']['fallback'] ) && ! empty( $tag_data['settings']['fallback'] ) ) { 164 | $data_replace[ $key ]['content'] = $tag_data['settings']['fallback']; 165 | } 166 | 167 | $data_replace[ $key ]['template'] = isset( $tag_data['settings']['mb_skin_template'] ) ? $tag_data['settings']['mb_skin_template'] : ''; 168 | } 169 | 170 | return $data_replace; 171 | } 172 | 173 | private function find_element_dynamic_tag( $settings, &$results = [] ) { 174 | if ( ! is_array( $settings ) ) { 175 | return; 176 | } 177 | 178 | foreach ( $settings as $elements ) { 179 | if ( isset( $elements['elType'] ) && $elements['elType'] === 'widget' && isset( $elements['settings']['__dynamic__'] ) ) { 180 | $results = array_merge_recursive( $results, $elements['settings']['__dynamic__'] ); 181 | continue; 182 | } 183 | 184 | if ( isset( $elements['elType'] ) && 'widget' === $elements['elType'] && isset( $elements['settings']['_skin'] ) && 'meta_box_skin_group' === $elements['settings']['_skin'] && ! empty( $elements['settings']['mb_skin_template'] ) ) { 185 | $field_group = 'setting' === $elements['settings']['object-type'] ? $elements['settings']['field-group-setting'] : $elements['settings']['field-group']; 186 | $field_group = explode( '.', $field_group, 2 ); 187 | 188 | $name = 'setting' !== $elements['settings']['object-type'] ? 'meta-box-settings-text' : 'meta-box-text'; 189 | 190 | $results = array_merge_recursive( $results, [ 191 | 'editor' => '[elementor-tag id="' . dechex( wp_rand( 1, 99999999 ) ) . '" name="' . $name . '" settings="' . urlencode( wp_json_encode( [ 192 | 'key' => str_replace( '.', ':', $field_group[1] ), 193 | 'mb_skin_template' => $elements['settings']['mb_skin_template'], 194 | ] ) ) . '"]', 195 | ] ); 196 | $results['sub-group'][] = [ 197 | 'id' => $elements['id'], 198 | 'template' => $elements['settings']['mb_skin_template'], 199 | ]; 200 | } 201 | 202 | $this->find_element_dynamic_tag( $elements, $results ); 203 | } 204 | } 205 | 206 | // Support multilang for WPML 207 | private function get_id_support_wpml( $id ) { 208 | $newid = apply_filters( 'wpml_object_id', $id, 'elementor_library', true ); 209 | return $newid ? $newid : $id; 210 | } 211 | 212 | public function get_option_dynamic_tag( $object_type = 'post' ) { 213 | $groups[] = [ 214 | 'label' => __( '-- Meta Box Field Group --', 'mb-elementor-integrator' ), 215 | 'options' => [], 216 | ]; 217 | 218 | $fields = $this->get_field_group( null, $object_type ); 219 | if ( 0 === count( $fields ) ) { 220 | return $groups; 221 | } 222 | 223 | foreach ( $fields as $field ) { 224 | if ( empty( $field['fields'] ) ) { 225 | continue; 226 | } 227 | 228 | $field_id = ''; 229 | if ( false !== strpos( $field['id'], '.' ) ) { 230 | $field_id = str_replace( '.', ':', $field['id'] ); 231 | } 232 | 233 | $child_options = []; 234 | foreach ( $field['fields'] as $key => $subfield ) { 235 | if ( ! empty( $field_id ) ) { 236 | $child_options[ "{$field_id}.{$subfield['id']}" ] = $subfield['name'] ?: $subfield['id']; 237 | continue; 238 | } 239 | $child_options[ "{$field['id']}:{$subfield['id']}" ] = $subfield['name'] ?: $subfield['id']; 240 | } 241 | $label = ! empty( $field['name'] ) ? $field['name'] : $field['group_title']; 242 | $label_slug = str_replace( '', '-', $label ); 243 | $groups[ "{$field['id']}-{$label_slug}" ] = [ 244 | 'label' => $label, 245 | 'options' => $child_options, 246 | ]; 247 | } 248 | 249 | return $groups; 250 | } 251 | 252 | public function get_value_dynamic_tag( $post_type, $field_id, $template_id = null, $object_type = 'post' ) { 253 | if ( false !== strpos( $field_id, ':' ) ) { 254 | list( $group, $field_id ) = explode( ':', $field_id, 2 ); 255 | } elseif ( false !== strpos( $field_id, '.' ) ) { 256 | list( $group, $field_id ) = explode( '.', $field_id, 2 ); 257 | } 258 | 259 | if ( ! isset( $group ) && empty( get_post_type_object( $post_type ) ) && 'setting' !== $object_type ) { 260 | $group = $post_type; 261 | } 262 | 263 | if ( ! isset( $group ) ) { 264 | return false; 265 | } 266 | 267 | if ( 'setting' === $object_type ) { 268 | $value_field = rwmb_meta( $group, [ 'object_type' => 'setting' ], $post_type ); 269 | } else { 270 | $value_field = empty( get_post_type_object( $post_type ) ) ? rwmb_get_value( $post_type ) : rwmb_get_value( $group ); 271 | $field_id = empty( get_post_type_object( $post_type ) ) ? $group . '.' . $field_id : $field_id; 272 | } 273 | 274 | if ( empty( $value_field ) || ( is_array( $value_field ) && 0 == count( $value_field ) ) ) { 275 | return true; 276 | } 277 | 278 | $sub_fields = false !== strpos( $field_id, '.' ) ? explode( '.', $field_id ) : (array) $field_id; 279 | $value_field = $this->get_value_nested_group( $value_field, $sub_fields, true ); 280 | 281 | if ( false !== is_int( key( $value_field ) ) ) { 282 | $value_field = array_shift( $value_field ); 283 | } 284 | 285 | if ( is_array( $value_field ) ) { 286 | $field = 'setting' === $object_type ? rwmb_get_field_settings( $group, [ 'object_type' => 'setting' ], $post_type ) : rwmb_get_field_settings( $group, [], null ); 287 | $field['fields'] = array_combine( (array) array_column( (array) $field['fields'], 'id' ), (array) $field['fields'] ); 288 | $field['fields'][ $field_id ]['fields'] = array_combine( (array) array_column( (array) $field['fields'][ $field_id ]['fields'], 'id' ), (array) $field['fields'][ $field_id ]['fields'] ); 289 | $this->extract_value_dynamic_tag( $value_field, $field['fields'][ $field_id ]['fields'], $template_id ); 290 | return true; 291 | } 292 | 293 | if ( isset( $value_field[ $field_id ] ) && ! is_array( $value_field[ $field_id ] ) ) { 294 | $value_field = $value_field[ $field_id ]; 295 | } 296 | 297 | echo esc_html( $value_field ); 298 | return true; 299 | } 300 | 301 | public function extract_value_dynamic_tag( $field = [], $field_setting = [], $template_id = null ) { 302 | if ( empty( $template_id ) ) { 303 | if ( false !== is_int( key( $field ) ) ) { 304 | $field = array_shift( $field ); 305 | } 306 | 307 | echo '
'; 308 | foreach ( $field as $key => $value ) { 309 | if ( isset( $field_setting[ $key ] ) && isset( $field_setting[ $key ]['mime_type'] ) && 'image' === $field_setting[ $key ]['mime_type'] && ! empty( $value ) ) { 310 | echo '
' . wp_get_attachment_image( $value, 'full' ) . '
'; 311 | continue; 312 | } 313 | echo '
' . esc_html( $value ) . '
'; 314 | } 315 | echo '
'; 316 | return; 317 | } 318 | 319 | // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 320 | echo $this->get_placeholder_template( $template_id, [ 321 | 'loop_header' => '
', 322 | 'loop_footer' => '
', 323 | ] ); 324 | } 325 | 326 | public function get_image_for_dynamic_tag( $value, $field_type ) { 327 | if ( empty( $value ) ) { 328 | return; 329 | } 330 | 331 | if ( ! is_array( $value ) ) { 332 | $image_src = wp_get_attachment_image_src( $value, 'full' ); 333 | return [ 334 | 'ID' => $value, 335 | 'full_url' => $image_src[0], 336 | ]; 337 | } 338 | 339 | $image = $value; 340 | switch ( $field_type ) { 341 | case 'image': 342 | case 'image_advanced': 343 | case 'image_select': 344 | case 'image_upload': 345 | $image = [ 346 | 'ID' => $value['ID'], 347 | 'full_url' => $value['full_url'], 348 | ]; 349 | break; 350 | } 351 | 352 | return $image; 353 | } 354 | 355 | public function parse_options( $fields = [], $field_group_id = null ) { 356 | if ( empty( $fields ) || ! isset( $fields['fields'] ) || empty( $fields['fields'] ) || empty( $field_group_id ) ) { 357 | return []; 358 | } 359 | 360 | $sub_fields = []; 361 | foreach ( $fields['fields'] as $field ) { 362 | $sub_fields[ $field_group_id . ':' . $field['id'] ] = $field['name']; 363 | } 364 | 365 | return $sub_fields; 366 | } 367 | 368 | public function get_field_group( $key = null, $object_type = 'post' ) { 369 | $field_registry = rwmb_get_registry( 'field' ); 370 | $post_types = $field_registry->get_by_object_type( $object_type ); 371 | 372 | $return_fields = []; 373 | if ( 0 < count( $post_types ) ) { 374 | foreach ( $post_types as $parent_key => $fields ) { 375 | // Fields is empty 376 | if ( 0 === count( $fields ) ) { 377 | continue; 378 | } 379 | // get list field type=group 380 | $nested = 'setting' === $object_type ? $parent_key : ''; 381 | $group_fields = $this->get_field_type_group( $fields, $nested ); 382 | if ( 0 === count( $group_fields ) ) { 383 | continue; 384 | } 385 | 386 | foreach ( $group_fields as $group_field ) { 387 | if ( ! empty( $key ) && $key !== $group_field['id'] ) { 388 | continue; 389 | } 390 | 391 | array_push( $return_fields, $group_field ); 392 | } 393 | } 394 | } 395 | 396 | if ( ! empty( $key ) && 0 < count( $return_fields ) ) { 397 | return $return_fields[0]; 398 | } 399 | 400 | return array_filter( $return_fields ); 401 | } 402 | 403 | public function get_list_field_group( $object_type = 'post' ) { 404 | $fields = $this->get_field_group( null, $object_type ); 405 | $list = []; 406 | foreach ( $fields as $k => $field ) { 407 | if ( in_array( $field['id'], $list ) ) { 408 | continue; 409 | } 410 | 411 | if ( strpos( $field['id'], '.' ) !== false ) { 412 | $field_group = explode( '.', $field['id'] ); 413 | $is_field_group = array_search( $field_group[0], array_column( $fields, 'id' ) ); 414 | if ( ! empty( $is_field_group ) ) { 415 | $label_group = ! empty( $fields[ $is_field_group ]['name'] ) ? $fields[ $is_field_group ]['name'] : $fields[ $is_field_group ]['group_title']; 416 | } else { 417 | $label_group = str_replace( [ '-', '_' ], ' ', ucfirst( $field_group[0] ) ); 418 | } 419 | 420 | $list[ $field['id'] ] = ( ! empty( $field['name'] ) ? $field['name'] : $field['group_title'] ) . ' ( ' . $label_group . ' )'; 421 | continue; 422 | } 423 | 424 | $list[ $field['id'] ] = ! empty( $field['name'] ) ? $field['name'] : $field['group_title']; 425 | } 426 | return $list; 427 | } 428 | 429 | /** 430 | * Check Type field group 431 | * @param array $fields 432 | * @return array $return_fields fields of type group 433 | */ 434 | private function get_field_type_group( $fields, $nested = '' ) { 435 | // not field type is group. 436 | $is_field_group = array_search( 'group', array_column( $fields, 'type' ) ); 437 | if ( false === $is_field_group ) { 438 | return []; 439 | } 440 | 441 | $return_fields = []; 442 | foreach ( $fields as $field ) { 443 | if ( 'group' === $field['type'] ) { 444 | if ( ! empty( $nested ) ) { 445 | $field['id'] = $nested . '.' . $field['id']; 446 | } 447 | $return_fields[] = $field; 448 | if ( isset( $field['fields'] ) && 0 < count( $field['fields'] ) ) { 449 | $return_fields = array_merge( $return_fields, $this->get_field_type_group( $field['fields'], $field['id'] ) ); 450 | } 451 | } 452 | } 453 | 454 | return $return_fields; 455 | } 456 | 457 | public function get_value_nested_group( $values = [], $keys = [], $first_item = false ) { 458 | if ( empty( $keys ) || empty( $values ) ) { 459 | return []; 460 | } 461 | 462 | if ( false === is_int( key( $values ) ) ) { 463 | $values = [ $values ]; 464 | } 465 | 466 | if ( true === $first_item ) { 467 | $values = [ array_shift( $values ) ]; 468 | } 469 | 470 | $return = []; 471 | $match_keys = []; 472 | foreach ( $values as $index => $value ) { 473 | 474 | if ( $index > 0 ) { 475 | $match_keys = []; 476 | } 477 | 478 | foreach ( $keys as $key ) { 479 | if ( ! isset( $value[ $key ] ) ) { 480 | continue; 481 | } 482 | 483 | $match_keys[] = $key; 484 | if ( $key !== end( $keys ) ) { 485 | $return = array_merge( $return, $this->get_value_nested_group( $value[ $key ], array_diff( $keys, $match_keys ) ) ); 486 | continue; 487 | } 488 | 489 | $return = array_merge( $return, (array) $value[ $key ] ); 490 | } 491 | } 492 | 493 | return $return; 494 | } 495 | 496 | public function split_field_nested( $fields = [] ) { 497 | if ( empty( $fields ) || ! is_array( $fields ) ) { 498 | return $fields; 499 | } 500 | 501 | $return = []; 502 | foreach ( $fields as $key => $value ) { 503 | if ( strpos( $value, '.' ) === false ) { 504 | continue; 505 | } 506 | 507 | $keys = explode( '.', $value, 2 ); 508 | $fields[ $key ] = $keys[0]; 509 | $return['sub_cols'][ $keys[0] ][] = $keys[1]; 510 | } 511 | 512 | $return['cols'] = $fields; 513 | return $return; 514 | } 515 | 516 | public static function change_url_ssl( $url ) { 517 | if ( is_ssl() && false === strpos( $url, 'https' ) ) { 518 | return str_replace( 'http', 'https', $url ); 519 | } 520 | return $url; 521 | } 522 | 523 | public function render_nested_group( $data_groups, $data_column ) { 524 | if ( false === is_int( key( $data_groups ) ) ) { 525 | $data_groups = [ $data_groups ]; 526 | } 527 | 528 | $clone = false; 529 | if ( isset( $data_column['id'] ) ) { 530 | $data_groups = [ $data_column['id'] => $data_groups ]; 531 | $clone = true; 532 | } 533 | 534 | foreach ( $data_groups as $data_group ) { 535 | echo '
'; 536 | foreach ( $data_group as $key => $value ) { 537 | if ( ! isset( $data_column[ $key ] ) && $clone === false ) { 538 | continue; 539 | } 540 | 541 | // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 542 | echo '
'; 543 | if ( is_array( $value ) && ! empty( $value ) ) { 544 | $data_column[ $key ]['fields'] = array_combine( array_column( $data_column[ $key ]['fields'], 'id' ), $data_column[ $key ]['fields'] ); 545 | $this->render_nested_group( $value, $data_column[ $key ]['fields'] ); 546 | continue; 547 | } 548 | $this->display_field( $value, $clone === false ? $data_column[ $key ] : $data_column ); 549 | echo '
'; 550 | } 551 | echo '
'; 552 | } 553 | } 554 | 555 | public function display_data_template( $template_id, $data_groups, $data_column, $options = [ 556 | 'loop_header' => '', 557 | 'loop_footer' => '', 558 | ] ) { 559 | $content_template = $this->get_template( $template_id ); 560 | $cols = array_keys( $content_template['data'] ); 561 | 562 | if ( stripos( wp_json_encode( $cols ), '.' ) !== false ) { 563 | $tmp_cols = $this->split_field_nested( $cols ); 564 | } 565 | 566 | foreach ( $data_groups as $k => $data_group ) { 567 | $check_cols = array_intersect( array_keys( $data_group ), $cols ); 568 | if ( 0 === count( $check_cols ) && ! isset( $tmp_cols ) ) { 569 | continue; 570 | } 571 | 572 | $content = $options['loop_header'] . $content_template['content'] . $options['loop_footer']; 573 | foreach ( $cols as $col ) { 574 | if ( ! isset( $data_group[ $col ] ) && false === strpos( $col, '.' ) ) { 575 | continue; 576 | } 577 | 578 | if ( false !== strpos( $col, '.' ) ) { 579 | $tmp_col = explode( '.', $col, 2 ); 580 | array_shift( $tmp_col ); 581 | 582 | $data_sub_column = array_filter( $data_column, function ( $k ) use ( $tmp_col ) { 583 | return $k == $tmp_col[0]; 584 | }, ARRAY_FILTER_USE_KEY); 585 | 586 | ob_start(); 587 | $this->render_nested_group( $data_group, $data_sub_column ); 588 | $value = ob_get_contents(); 589 | ob_end_clean(); 590 | 591 | // Display text from sub field group. 592 | if ( ! isset( $data_sub_column[ $tmp_col[0] ]['mime_type'] ) || 'image' !== $data_sub_column[ $tmp_col[0] ]['mime_type'] ) { 593 | $content_template['data'][ $col ]['content'] = str_replace( "'", '’', $content_template['data'][ $col ]['content'] ); 594 | $content = str_replace( $content_template['data'][ $col ]['content'], $value, $content ); 595 | continue; 596 | } 597 | 598 | // Display image from sub field group. 599 | $search_data = []; 600 | libxml_use_internal_errors( true ); 601 | $dom = new \DOMDocument(); 602 | $dom->loadHTML( $content ); 603 | foreach ( $dom->getElementsByTagName( 'img' ) as $i => $img ) { 604 | if ( false === strpos( $img->getAttribute( 'srcset' ), $content_template['data'][ $col ]['content'] ) ) { 605 | continue; 606 | } 607 | $search_data = [ 608 | 'html' => str_replace( '>', ' />', $dom->saveHTML( $img ) ), 609 | 'width' => 'width="' . $img->getAttribute( 'width' ) . '"', 610 | 'height' => 'height="' . $img->getAttribute( 'height' ) . '"', 611 | 'class' => 'class="' . $img->getAttribute( 'class' ) . '"', 612 | ]; 613 | } 614 | 615 | if ( empty( $search_data ) ) { 616 | continue; 617 | } 618 | 619 | // Replace Attribute Image 620 | $domNew = new \DOMDocument(); 621 | $domNew->loadHTML( $value ); 622 | foreach ( $domNew->getElementsByTagName( 'img' ) as $i => $img ) { 623 | $value = str_replace( [ 624 | 'width="' . $img->getAttribute( 'width' ) . '"', 625 | 'height' => 'height="' . $img->getAttribute( 'height' ) . '"', 626 | 'class="' . $img->getAttribute( 'class' ) . '"', 627 | ], [ 628 | $search_data['width'], 629 | $search_data['height'], 630 | $search_data['class'], 631 | ], $value ); 632 | } 633 | 634 | $content = str_replace( $search_data['html'], $value, $content ); 635 | continue; 636 | } 637 | 638 | // Display field image for group 639 | if ( isset( $data_column[ $col ]['mime_type'] ) && 'image' === $data_column[ $col ]['mime_type'] ) { 640 | $search_data = []; 641 | libxml_use_internal_errors( true ); 642 | $dom = new \DOMDocument(); 643 | $dom->loadHTML( $content ); 644 | foreach ( $dom->getElementsByTagName( 'img' ) as $i => $img ) { 645 | $tmp_image = substr( $content_template['data'][ $col ]['content'], 0, strlen( $content_template['data'][ $col ]['content'] ) - 4 ); 646 | if ( false === strpos( $img->getAttribute( 'srcset' ), $tmp_image ) && false === strpos( $img->getAttribute( 'src' ), $tmp_image ) ) { 647 | continue; 648 | } 649 | $search_data = [ 650 | 'html' => str_replace( '>', ' />', $dom->saveHTML( $img ) ), 651 | 'width' => $img->getAttribute( 'width' ), 652 | 'height' => $img->getAttribute( 'height' ), 653 | 'class' => $img->getAttribute( 'class' ), 654 | ]; 655 | } 656 | 657 | if ( empty( $search_data ) ) { 658 | continue; 659 | } 660 | 661 | $values = is_array( $data_group[ $col ] ) ? $data_group[ $col ] : (array) $data_group[ $col ]; 662 | $content_image = ''; 663 | foreach ( $values as $val ) { 664 | $image = $this->get_image_for_dynamic_tag( $val, $data_column[ $col ]['type'] ); 665 | if ( ! isset( $image['ID'] ) ) { 666 | continue; 667 | } 668 | $content_image .= wp_get_attachment_image( $image['ID'], [ $search_data['width'], $search_data['height'] ], false, [ 'class' => $search_data['class'] ] ); 669 | } 670 | $content = str_replace( $search_data['html'], $content_image, $content ); 671 | continue; 672 | } 673 | 674 | // Get content field group 675 | if ( is_array( $data_group[ $col ] ) && ! empty( $data_group[ $col ] ) ) { 676 | $data_sub_column = isset( $data_column[ $col ]['fields'] ) ? array_combine( array_column( $data_column[ $col ]['fields'], 'id' ), $data_column[ $col ]['fields'] ) : $data_column[ $col ]; 677 | if ( ! empty( $content_template['data'][ $col ]['template'] ) ) { 678 | ob_start(); 679 | $this->display_data_template( $content_template['data'][ $col ]['template'], $data_group[ $col ], $data_sub_column, $options ); 680 | $value = ob_get_contents(); 681 | ob_end_clean(); 682 | 683 | $content = str_replace( $content_template['data'][ $col ]['content'], $value, $content ); 684 | continue; 685 | } 686 | 687 | ob_start(); 688 | $this->render_nested_group( $data_group[ $col ], $data_sub_column ); 689 | $value = ob_get_contents(); 690 | ob_end_clean(); 691 | 692 | $content = str_replace( $content_template['data'][ $col ]['content'], $value, $content ); 693 | continue; 694 | } 695 | 696 | ob_start(); 697 | $this->display_field( $data_group[ $col ], $data_column[ $col ], true ); 698 | $value = ob_get_contents(); 699 | ob_end_clean(); 700 | 701 | $content = str_replace( [ '‘', '“', '”', '–' ], [ '’', '"', '"', '-' ], $content ); 702 | $content_template['data'][ $col ]['content'] = str_replace( [ "'", '"', '–' ], [ '’', '"', '-' ], $content_template['data'][ $col ]['content'] ); 703 | $content = str_replace( $content_template['data'][ $col ]['content'], $value, $content ); 704 | 705 | } 706 | 707 | echo wp_kses( $content, array_merge( wp_kses_allowed_html( 'post' ), [ 'style' => [] ] ) ); 708 | } 709 | } 710 | 711 | public function display_data_widget( $data_groups, $data_column, $options = [ 712 | 'loop_header' => '', 713 | 'loop_footer' => '', 714 | ] ) { 715 | if ( empty( $data_groups ) ) { 716 | return; 717 | } 718 | 719 | foreach ( $data_groups as $data_group ) { 720 | if ( ! is_array( $data_group ) ) { 721 | continue; 722 | } 723 | 724 | echo wp_kses_post( $options['loop_header'] ); 725 | foreach ( $data_group as $key => $value ) { 726 | $data_sub_column = []; 727 | if ( is_array( $value ) && ! empty( $value ) ) { 728 | $data_sub_column = isset( $data_column[ $key ]['fields'] ) ? array_combine( array_column( $data_column[ $key ]['fields'], 'id' ), $data_column[ $key ]['fields'] ) : $data_column[ $key ]; 729 | } 730 | 731 | ob_start(); 732 | count( $data_sub_column ) > 0 ? $this->render_nested_group( $value, $data_sub_column ) : $this->display_field( $value, $data_column[ $key ] ); 733 | $content = ob_get_contents(); 734 | ob_end_clean(); 735 | 736 | if ( empty( $content ) ) { 737 | continue; 738 | } 739 | printf( '
%s
', esc_attr( $key ), wp_kses( $content, array_merge( wp_kses_allowed_html( 'post' ), [ 'style' => [] ] ) ) ); 740 | } 741 | echo wp_kses_post( $options['loop_footer'] ); 742 | } 743 | } 744 | 745 | public function display_field( $data, $field = [], $return = false ) { 746 | 747 | switch ( $field['type'] ) { 748 | case 'image': 749 | case 'image_advanced': 750 | case 'image_select': 751 | case 'image_upload': 752 | case 'single_image': 753 | $file_type = 'image'; 754 | break; 755 | case 'post': 756 | $file_type = 'post'; 757 | break; 758 | case 'taxonomy': 759 | $file_type = 'taxonomy'; 760 | break; 761 | case 'user': 762 | $file_type = 'user'; 763 | break; 764 | case 'icon': 765 | $file_type = 'icon'; 766 | break; 767 | default: 768 | $file_type = 'text'; 769 | break; 770 | } 771 | 772 | $path_file = plugin_dir_path( __DIR__ ) . 'src/Templates/display_field-' . $file_type . '.php'; 773 | 774 | if ( file_exists( $path_file ) ) { 775 | require $path_file; 776 | } 777 | } 778 | 779 | private function display_icon( $data, $field ) { 780 | $icons = array_column( $field['options'], 'label', 'value' ); 781 | 782 | if ( ! $icons[ $data ] ) { 783 | return ''; 784 | } 785 | 786 | // Case using svg 787 | $str_svg = strstr( $icons[ $data ], '', true ); 788 | if ( $str_svg !== false ) { 789 | return $str_svg . ''; 790 | } 791 | 792 | // Case using font with icon_css as string 793 | if ( $field['icon_css'] && is_string( $field['icon_css'] ) ) { 794 | // Frontend 795 | if ( ! is_admin() ) { 796 | $handle = md5( $field['icon_css'] ); 797 | wp_enqueue_style( $handle, $field['icon_css'], [], RWMB_VER ); 798 | } 799 | return ''; 800 | } 801 | 802 | // Case using font with icon_css as function 803 | if ( $field['icon_css'] && is_callable( $field['icon_css'] ) ) { 804 | // Frontend 805 | if ( ! is_admin() ) { 806 | $field['icon_css'](); 807 | } 808 | return ''; 809 | } 810 | } 811 | } 812 | -------------------------------------------------------------------------------- /src/Loader.php: -------------------------------------------------------------------------------- 1 | register_locations(); 23 | $this->register_widgets(); 24 | $this->modules(); 25 | 26 | CurrentWidget::track(); 27 | } 28 | 29 | public function modules() { 30 | new GroupField(); 31 | } 32 | 33 | private function is_valid() { 34 | if ( ! defined( 'RWMB_VER' ) ) { 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | public function register_conditions( $conditions_manager ) { 41 | $conditions_manager->get_condition( 'general' )->register_sub_condition( new ThemeBuilder\Conditions\Group() ); 42 | } 43 | 44 | public function register_locations() { 45 | new Widgets\GroupLocation(); 46 | } 47 | 48 | public function register_widgets() { 49 | add_action('elementor/widgets/register', function ( $widgets_manager ) { 50 | $widgets_manager->register( new Widgets\MBGroup() ); 51 | }); 52 | } 53 | 54 | /** 55 | * Register dynamic tags for Elementor. 56 | * @param object $dynamic_tags Elementor dynamic tags instance. 57 | */ 58 | public function register_tags( Manager $dynamic_tags ) { 59 | if ( ! $this->is_valid() ) { 60 | return; 61 | } 62 | 63 | $dynamic_tags->register( new Tags\Post\Text() ); 64 | $dynamic_tags->register( new Tags\Post\Image() ); 65 | $dynamic_tags->register( new Tags\Post\Video() ); 66 | 67 | if ( function_exists( 'mb_term_meta_load' ) ) { 68 | $dynamic_tags->register( new Tags\Archive\Text() ); 69 | $dynamic_tags->register( new Tags\Archive\Image() ); 70 | $dynamic_tags->register( new Tags\Archive\Video() ); 71 | } 72 | 73 | if ( function_exists( 'mb_settings_page_load' ) ) { 74 | $dynamic_tags->register( new Tags\Settings\Text() ); 75 | $dynamic_tags->register( new Tags\Settings\Image() ); 76 | $dynamic_tags->register( new Tags\Settings\Video() ); 77 | } 78 | } 79 | 80 | public function register_skins() { 81 | if ( ! $this->is_valid() ) { 82 | return; 83 | } 84 | 85 | // Add a custom skin for the POSTS widget 86 | add_action('elementor/widget/metabox-group/skins_init', function ( $widget ) { 87 | $widget->add_skin( new Widgets\GroupSkin( $widget ) ); 88 | }); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Tags/Archive/Image.php: -------------------------------------------------------------------------------- 1 | display_icon( $data, $field ) ); 7 | -------------------------------------------------------------------------------- /src/Templates/display_field-image.php: -------------------------------------------------------------------------------- 1 | post_title ); 8 | -------------------------------------------------------------------------------- /src/Templates/display_field-taxonomy.php: -------------------------------------------------------------------------------- 1 | name ); 8 | -------------------------------------------------------------------------------- /src/Templates/display_field-text.php: -------------------------------------------------------------------------------- 1 | %s', esc_url( $data ), esc_html( $data ) ); 7 | -------------------------------------------------------------------------------- /src/Templates/display_field-user.php: -------------------------------------------------------------------------------- 1 | data->display_name ); 8 | -------------------------------------------------------------------------------- /src/ThemeBuilder/Conditions/Group.php: -------------------------------------------------------------------------------- 1 | label; 42 | 43 | foreach ( $post_types as $post_type => $label ) { 44 | $condition = new Post([ 45 | 'post_type' => $post_type, 46 | ]); 47 | 48 | $this->register_sub_condition( $condition ); 49 | } 50 | 51 | $fields = ( new GroupField() )->get_field_group(); 52 | if ( 0 < count( $fields ) ) { 53 | $condition = new MBFields( $fields ); 54 | $this->register_sub_condition( $condition ); 55 | } 56 | 57 | $this->sub_conditions[] = 'child_of'; 58 | 59 | $this->sub_conditions[] = 'any_child_of'; 60 | 61 | $this->sub_conditions[] = 'by_author'; 62 | 63 | // Last condition. 64 | $this->sub_conditions[] = 'not_found404'; 65 | } 66 | 67 | public function check( $args ) { 68 | return false; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ThemeBuilder/Conditions/MBField.php: -------------------------------------------------------------------------------- 1 | field = $field['field']; 22 | $this->key = $field['key']; 23 | parent::__construct(); 24 | } 25 | 26 | public function get_name() { 27 | return $this->key . '_' . $this->field['id']; 28 | } 29 | 30 | public function get_label() { 31 | return isset( $this->field['group_title'] ) ? $this->field['group_title'] : $this->field['name']; 32 | } 33 | 34 | public function check( $args ) { 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ThemeBuilder/Conditions/MBFields.php: -------------------------------------------------------------------------------- 1 | fields = $fields; 22 | parent::__construct(); 23 | } 24 | 25 | public function get_name() { 26 | return 'metabox-field'; 27 | } 28 | 29 | public function get_label() { 30 | return 'Meta Box Field'; 31 | } 32 | 33 | public function get_all_label() { 34 | return __( 'No Conditions', 'mb-elementor-integrator' ); 35 | } 36 | 37 | public function check( $args ) { 38 | return false; 39 | } 40 | 41 | public function register_sub_conditions() { 42 | foreach ( $this->fields as $key => $field ) { 43 | $condition = new MBField([ 44 | 'key' => $key, 45 | 'field' => $field, 46 | ]); 47 | $this->register_sub_condition( $condition ); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/ThemeBuilder/Documents/Group.php: -------------------------------------------------------------------------------- 1 | label; 44 | $post_types_options = []; 45 | 46 | foreach ( $post_types as $post_type => $label ) { 47 | $post_types_options[ 'single/' . $post_type ] = get_post_type_object( $post_type )->labels->singular_name; 48 | } 49 | 50 | return [ 51 | 'single' => [ 52 | 'label' => __( 'Single', 'mb-elementor-integrator' ), 53 | 'options' => $post_types_options, 54 | ], 55 | 'page/404' => __( '404', 'mb-elementor-integrator' ), 56 | ]; 57 | } 58 | 59 | /** 60 | * Get list post type is public 61 | * @return array $post_types_options 62 | */ 63 | public static function get_public_post_types() { 64 | $post_types_options = []; 65 | $args = [ 66 | 'public' => true, 67 | ]; 68 | $output = 'objects'; // names or objects. 69 | $post_types = get_post_types( $args, $output ); 70 | foreach ( $post_types as $post_type ) { 71 | if ( 'elementor_library' !== $post_type->name ) { 72 | $post_types_options[ $post_type->name ] = $post_type->label; 73 | } 74 | } 75 | return $post_types_options; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Traits/Archive.php: -------------------------------------------------------------------------------- 1 | get_by_object_type( 'term' ); 13 | foreach ( $fields as $taxonomy => $list ) { 14 | $taxonomy_object = get_taxonomy( $taxonomy ); 15 | if ( ! $taxonomy_object ) { 16 | continue; 17 | } 18 | $options = [ 19 | '' => __( '-- Select a field --', 'mb-elementor-integrator' ), 20 | ]; 21 | foreach ( $list as $field ) { 22 | $options[ "{$taxonomy}:{$field['id']}" ] = $field['name'] ?: $field['id']; 23 | } 24 | $groups[] = [ 25 | 'label' => $taxonomy_object->labels->singular_name, 26 | 'options' => $options, 27 | ]; 28 | } 29 | 30 | return $groups; 31 | } 32 | 33 | private function handle_get_value() { 34 | $key = $this->get_settings( 'key' ); 35 | if ( ! $key ) { 36 | return null; 37 | } 38 | list( $taxonomy, $field_id ) = explode( ':', $key ); 39 | return rwmb_meta( $field_id, [ 'object_type' => 'term' ], get_queried_object_id() ); 40 | } 41 | 42 | private function the_value() { 43 | $key = $this->get_settings( 'key' ); 44 | if ( ! $key ) { 45 | return null; 46 | } 47 | list( $taxonomy, $field_id ) = explode( ':', $key ); 48 | rwmb_the_value( $field_id, [ 'object_type' => 'term' ], get_queried_object_id() ); 49 | if ( ! is_singular() ) { 50 | return null; 51 | } 52 | $post_id = get_the_ID(); 53 | $terms = get_the_terms( $post_id, $taxonomy ); 54 | if ( empty( $terms ) ) { 55 | return null; 56 | } 57 | foreach ( $terms as $term ) { 58 | rwmb_the_value( $field_id, [ 'object_type' => 'term' ], $term->term_id ); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Traits/Base.php: -------------------------------------------------------------------------------- 1 | add_control( 'key', [ 25 | 'label' => __( 'Field', 'mb-elementor-integrator' ), 26 | 'type' => Controls_Manager::SELECT, 27 | 'groups' => $this->get_option_groups(), 28 | ] ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Traits/Fields/Image.php: -------------------------------------------------------------------------------- 1 | handle_get_value(); 17 | 18 | if ( empty( $images ) || ! is_array( $images ) ) { 19 | return []; 20 | } 21 | 22 | $widget = CurrentWidget::name() ?? 'null'; 23 | $types = [ 24 | 'null' => 'single', 25 | 'image' => 'single', 26 | 'image-box' => 'single', 27 | 'hotspot' => 'single', 28 | 'price-list' => 'single', 29 | 'media-carousel' => 'single', 30 | 'testimonial-carousel' => 'single', 31 | 'image-carousel' => 'multiple', 32 | 'image-gallery' => 'multiple', 33 | ]; 34 | $method = $types[ $widget ] ?? 'default'; 35 | 36 | return $this->$method( $images ); 37 | } 38 | 39 | private function single( array $images ): array { 40 | if ( isset( $images['ID'] ) ) { 41 | return $this->format( $images ); 42 | } 43 | 44 | $image = reset( $images ); 45 | return $this->format( $image ); 46 | } 47 | 48 | private function multiple( array $images ): array { 49 | if ( isset( $images['ID'] ) ) { 50 | $images = [ $images ]; 51 | } 52 | if ( array_key_first( $images ) === 0 && ( count( $images ) - 1 ) === array_key_last( $images ) ) { 53 | $images = array_merge_recursive( ...$images ); 54 | } 55 | return array_map( [ $this, 'format' ], $images ); 56 | } 57 | 58 | private function default( array $images ): array { 59 | return isset( $images['ID'] ) ? $this->format( $images ) : array_map( [ $this, 'format' ], $images ); 60 | } 61 | 62 | private function format( array $image ): array { 63 | return [ 64 | 'id' => $image['ID'], 65 | 'url' => $image['full_url'] ?? '', 66 | ]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Traits/Fields/Text.php: -------------------------------------------------------------------------------- 1 | the_value(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Traits/Fields/Video.php: -------------------------------------------------------------------------------- 1 | handle_get_value(); 16 | 17 | if ( empty( $url ) ) { 18 | return; 19 | } 20 | 21 | if ( ! is_array( $url ) ) { 22 | return $url; 23 | } 24 | 25 | $value = []; 26 | foreach ( $url as $link ) { 27 | if ( ! empty( $link['src'] ) ) { 28 | $value['url'] = $link['src']; 29 | } 30 | if ( ! empty( $link['url'] ) ) { 31 | $value['url'] = $link['url']; 32 | } 33 | } 34 | 35 | return $value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Traits/Location.php: -------------------------------------------------------------------------------- 1 | get_class_full_name(); 25 | if ( ! empty( $class_full_name ) ) { 26 | Plugin::elementor()->documents->register_document_type( $this->get_id(), $class_full_name ); 27 | Source_Local::add_template_type( $this->get_id() ); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Traits/Post.php: -------------------------------------------------------------------------------- 1 | documents->get_current(); 14 | if ( ! empty( $document ) && 'metabox_group_template' === $document->get_type() ) { 15 | $group_field = new GroupField(); 16 | return $group_field->get_option_dynamic_tag(); 17 | } 18 | 19 | $groups = [ 20 | 0 => [ 21 | 'options' => [ 22 | '' => __( '-- Select a field --', 'mb-elementor-integrator' ), 23 | ], 24 | ], 25 | ]; 26 | 27 | $fields = rwmb_get_registry( 'field' )->get_by_object_type( 'post' ); 28 | $fields = array_diff_key( $fields, array_flip( [ 'mb-post-type', 'mb-taxonomy' ] ) ); 29 | 30 | foreach ( $fields as $post_type => $list ) { 31 | $post_type_object = get_post_type_object( $post_type ); 32 | if ( ! $post_type_object ) { 33 | continue; 34 | } 35 | $options = []; 36 | foreach ( $list as $field ) { 37 | $options[ "{$post_type}:{$field['id']}" ] = $field['name'] ?: $field['id']; 38 | } 39 | $groups[] = [ 40 | 'label' => $post_type_object->labels->singular_name, 41 | 'options' => $options, 42 | ]; 43 | } 44 | 45 | return $groups; 46 | } 47 | 48 | private function handle_get_value() { 49 | $key = $this->get_settings( 'key' ); 50 | if ( ! $key ) { 51 | return null; 52 | } 53 | if ( false === strpos( $key, ':' ) ) { 54 | return rwmb_meta( $key ); 55 | } 56 | 57 | list( $post_type, $field_id ) = explode( ':', $key, 2 ); 58 | if ( ! empty( get_post_type_object( $post_type ) ) ) { 59 | return rwmb_meta( $field_id ); 60 | } 61 | 62 | $group_field = new GroupField(); 63 | ob_start(); 64 | $group_field->get_value_dynamic_tag( $post_type, $field_id, $this->get_settings( 'mb_skin_template' ) ); 65 | $valueField = ob_get_contents(); 66 | ob_end_clean(); 67 | 68 | if ( ! empty( $valueField ) ) { 69 | $image = wp_get_attachment_image_src( $valueField, 'full' ); 70 | if ( ! empty( $image ) ) { 71 | return [ 72 | 'ID' => $valueField, 73 | 'full_url' => $image[0], 74 | ]; 75 | } 76 | return $valueField; 77 | } 78 | } 79 | 80 | private function the_value() { 81 | $key = $this->get_settings( 'key' ); 82 | if ( ! $key ) { 83 | return null; 84 | } 85 | if ( false === strpos( $key, ':' ) ) { 86 | return rwmb_meta( $key ); 87 | } 88 | 89 | list( $post_type, $field_id ) = explode( ':', $key, 2 ); 90 | 91 | $group_field = new GroupField(); 92 | $value = $group_field->get_value_dynamic_tag( $post_type, $field_id, $this->get_settings( 'mb_skin_template' ) ); 93 | if ( $value ) { 94 | return; 95 | } 96 | 97 | $field = rwmb_get_field_settings( $field_id, [], null ); 98 | if ( ! empty( $field ) && ( 'color' === $field['type'] ) ) { 99 | echo esc_html( rwmb_get_value( $field_id ) ); 100 | return; 101 | } 102 | 103 | rwmb_the_value( $field_id ); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Traits/Settings.php: -------------------------------------------------------------------------------- 1 | documents->get_current(); 14 | if ( ! empty( $document ) && 'metabox_group_template' === $document->get_type() ) { 15 | $group_field = new GroupField(); 16 | return $group_field->get_option_dynamic_tag( 'setting' ); 17 | } 18 | 19 | $groups = [ 20 | 0 => [ 21 | 'options' => [ 22 | '' => __( '-- Select a field --', 'mb-elementor-integrator' ), 23 | ], 24 | ], 25 | ]; 26 | 27 | $fields = rwmb_get_registry( 'field' )->get_by_object_type( 'setting' ); 28 | foreach ( $fields as $option_name => $list ) { 29 | foreach ( $list as $field ) { 30 | $options[ "{$option_name}:{$field['id']}" ] = $field['name'] ?: $field['id']; 31 | } 32 | $groups[] = [ 33 | 'label' => $option_name, 34 | 'options' => $options, 35 | ]; 36 | } 37 | 38 | return $groups; 39 | } 40 | 41 | private function handle_get_value() { 42 | $group_field = new GroupField(); 43 | 44 | $key = $this->get_settings( 'key' ); 45 | if ( ! $key ) { 46 | return null; 47 | } 48 | list( $option_name, $field_id ) = explode( ':', $key, 2 ); 49 | if ( false === strpos( $field_id, '.' ) && false === strpos( $field_id, ':' ) ) { 50 | $field = rwmb_get_field_settings( $field_id, [ 'object_type' => 'setting' ], $option_name ); 51 | $value = rwmb_meta( trim( $field_id ), [ 'object_type' => 'setting' ], $option_name ); 52 | 53 | if ( ( isset( $field['mime_type'] ) && $field['mime_type'] === 'image' ) || $field['type'] === 'image' ) { 54 | if ( in_array( $field['type'], [ 'image_advanced', 'image_upload', 'single_image', 'image_select' ], true ) ) { 55 | return $value; 56 | } 57 | 58 | if ( is_array( $value ) && false !== is_int( key( $value ) ) ) { 59 | $value = array_shift( $value ); 60 | } 61 | return $group_field->get_image_for_dynamic_tag( $value, $field['type'] ); 62 | } 63 | 64 | return $value; 65 | } 66 | 67 | // Get data from group or sub-group 68 | list( $field_id, $sub_fields ) = false !== strpos( $field_id, ':' ) ? explode( ':', $field_id, 2 ) : explode( '.', $field_id ); 69 | $sub_fields = false !== strpos( $sub_fields, '.' ) ? explode( '.', $sub_fields, 2 ) : (array) $sub_fields; 70 | 71 | $value_field = rwmb_meta( $field_id, [ 'object_type' => 'setting' ], $option_name ); 72 | if ( 0 < count( $value_field ) ) { 73 | if ( true === is_int( key( $value_field ) ) ) { 74 | $value_field = array_shift( $value_field ); 75 | } 76 | } 77 | 78 | $field = rwmb_get_field_settings( $field_id, [ 'object_type' => 'setting' ], $option_name ); 79 | $field['fields'] = array_combine( array_column( $field['fields'], 'id' ), $field['fields'] ); 80 | 81 | if ( 1 === count( $sub_fields ) ) { 82 | if ( $field['fields'][ end( $sub_fields ) ]['mime_type'] !== 'image' ) { 83 | return $value_field[ end( $sub_fields ) ]; 84 | } 85 | 86 | $image_id = $value_field[ end( $sub_fields ) ]; 87 | 88 | } 89 | 90 | $clone_field = $field; 91 | $type = ''; 92 | foreach ( $sub_fields as $index => $sub_field ) { 93 | if ( ! isset( $clone_field['fields'][ $sub_field ] ) ) { 94 | break; 95 | } 96 | 97 | if ( $index < count( $sub_fields ) - 1 ) { 98 | $clone_field = $clone_field['fields'][ $sub_field ]; 99 | $clone_field['fields'] = array_combine( array_column( $clone_field['fields'], 'id' ), $clone_field['fields'] ); 100 | continue; 101 | } 102 | 103 | $type = $clone_field['fields'][ $sub_field ]['type']; 104 | } 105 | 106 | if ( empty( $type ) ) { 107 | return; 108 | } 109 | 110 | $value_field = $group_field->get_value_nested_group( $value_field, $sub_fields, true ); 111 | if ( false !== is_int( key( $value_field ) ) ) { 112 | $value_field = array_shift( $value_field ); 113 | } 114 | $image_id = $value_field; 115 | 116 | return $group_field->get_image_for_dynamic_tag( $image_id, $type ); 117 | } 118 | 119 | private function the_value() { 120 | $key = $this->get_settings( 'key' ); 121 | if ( ! $key ) { 122 | return null; 123 | } 124 | list( $option_name, $field_id ) = explode( ':', $key, 2 ); 125 | $group_field = new GroupField(); 126 | $value = $group_field->get_value_dynamic_tag( $option_name, $field_id, $this->get_settings( 'mb_skin_template' ), 'setting' ); 127 | if ( $value ) { 128 | return; 129 | } 130 | 131 | $field = rwmb_get_field_settings( $field_id, [ 'object_type' => 'setting' ], $option_name ); 132 | if ( ! empty( $field ) && ( 'color' === $field['type'] ) ) { 133 | echo esc_html( rwmb_get_value( trim( $field_id ), [ 'object_type' => 'setting' ], $option_name ) ); 134 | return; 135 | } 136 | 137 | rwmb_the_value( trim( $field_id ), [ 'object_type' => 'setting' ], $option_name ); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Traits/Skin.php: -------------------------------------------------------------------------------- 1 | used_templates as $post_id ) { 25 | if ( post_password_required( $post_id ) ) { 26 | return ''; 27 | } 28 | 29 | if ( ! Plugin::$instance->db->is_built_with_elementor( $post_id ) ) { 30 | return ''; 31 | } 32 | 33 | $document = Plugin::$instance->documents->get_doc_for_frontend( $post_id ); 34 | 35 | // Change the current post, so widgets can use `documents->get_current`. 36 | Plugin::$instance->documents->switch_to_document( $document ); 37 | 38 | Plugin::$instance->documents->restore_document(); 39 | } 40 | } 41 | 42 | protected function set_used_template( $skin ) { 43 | if ( ! $skin ) { 44 | return; 45 | } 46 | $this->used_templates[ $skin ] = $skin; 47 | } 48 | 49 | public function render() { 50 | echo 'SKIN WIDGET'; 51 | } 52 | 53 | public function render_amp() { 54 | } 55 | 56 | protected function register_divider_controls() { 57 | $this->add_control('mb_hr2', [ 58 | 'type' => Controls_Manager::DIVIDER, 59 | ]); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Widgets/GroupLocation.php: -------------------------------------------------------------------------------- 1 | register_location( 31 | $this->get_id(), 32 | [ 33 | 'label' => __( 'Meta Box Group Skin', 'mb-elementor-integrator' ), 34 | 'multiple' => true, 35 | 'edit_in_content' => true, 36 | ] 37 | ); 38 | } 39 | 40 | public function add_more_types( $settings ) { 41 | $post_id = get_the_ID(); 42 | $document = $this->get_document( $post_id ); 43 | 44 | if ( ! $document || ! array_key_exists( 'theme_builder', $settings ) ) { 45 | return $settings; 46 | } 47 | 48 | $new_types = [ $this->get_id() => Loop::get_properties() ]; 49 | $add_settings = [ 'theme_builder' => [ 'types' => $new_types ] ]; 50 | if ( ! array_key_exists( $this->get_id(), $settings['theme_builder']['types'] ) ) { 51 | $settings = array_merge_recursive( $settings, $add_settings ); 52 | } 53 | return $settings; 54 | } 55 | 56 | public function get_document( $post_id ) { 57 | 58 | $document = null; 59 | 60 | try { 61 | $document = Plugin::$instance->documents->get( $post_id ); 62 | } catch ( Exception $e ) { 63 | return null; 64 | } 65 | 66 | if ( ! empty( $document ) && ! $document instanceof Theme_Document ) { 67 | $document = null; 68 | } 69 | 70 | return $document; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Widgets/GroupSkin.php: -------------------------------------------------------------------------------- 1 | skin_id = dechex( wp_rand( 1, 99999999 ) ); 21 | } 22 | 23 | public function get_title() { 24 | return __( 'Sub-group', 'mb-elementor-integrator' ); 25 | } 26 | 27 | public function get_id() { 28 | return 'meta_box_skin_group'; 29 | } 30 | 31 | private function get_skin_id() { 32 | return $this->skin_id; 33 | } 34 | 35 | private function render_header() { 36 | ?> 37 |
38 | 43 |
44 | '; 49 | } 50 | 51 | protected function render_loop_footer() { 52 | return ''; 53 | } 54 | 55 | private function style_inline( $size, $spacing ) { 56 | echo ''; 62 | } 63 | 64 | public function render() { 65 | $group_fields = new GroupField(); 66 | $post = $group_fields->get_current_post(); 67 | 68 | $data_groups = []; 69 | $data_column = []; 70 | 71 | $settings = $this->parent->get_settings_for_display(); 72 | if ( empty( $settings['object-type'] ) ) { 73 | return; 74 | } 75 | 76 | if ( $settings['object-type'] === 'post' && ( ! isset( $settings['field-group'] ) || empty( $settings['field-group'] ) ) ) { 77 | return; 78 | } 79 | 80 | if ( $settings['object-type'] === 'setting' && ( ! isset( $settings['field-group-setting'] ) || empty( $settings['field-group-setting'] ) ) ) { 81 | return; 82 | } 83 | 84 | // check group nested 85 | $field_group = $settings['object-type'] === 'post' ? $settings['field-group'] : $settings['field-group-setting']; 86 | $field_group = false !== strpos( $field_group, '.' ) ? explode( '.', $field_group ) : (array) $field_group; 87 | 88 | if ( 'setting' === $settings['object-type'] ) { 89 | $object_setting = array_shift( $field_group ); 90 | } 91 | 92 | $data_groups = 'post' === $settings['object-type'] ? rwmb_meta( $field_group[0], [], $post->ID ) : rwmb_meta( $field_group[0], [ 'object_type' => 'setting' ], $object_setting ); 93 | 94 | array_shift( $field_group ); 95 | if ( ! empty( $field_group ) ) { 96 | $data_groups = $group_fields->get_value_nested_group( $data_groups, $field_group ); 97 | } 98 | 99 | if ( empty( $data_groups ) ) { 100 | return; 101 | } 102 | 103 | if ( false === is_int( key( $data_groups ) ) ) { 104 | $data_groups = [ $data_groups ]; 105 | } 106 | 107 | // $data_groups = 0 < count( $data_groups ) ? [ array_shift( $data_groups ) ] : $data_groups; 108 | 109 | $fields = $group_fields->get_field_group( 'post' === $settings['object-type'] ? $settings['field-group'] : $settings['field-group-setting'], $settings['object-type'] ); 110 | $data_column = array_combine( array_column( $fields['fields'], 'id' ), $fields['fields'] ); 111 | 112 | $mb_column = ! empty( $this->parent->get_settings_for_display( 'mb_column' ) ) ? $this->parent->get_settings_for_display( 'mb_column' ) : 3; 113 | $mb_spacing = ! empty( $this->parent->get_settings_for_display( 'mb_spacing' ) ) ? $this->parent->get_settings_for_display( 'mb_spacing' ) : 20; 114 | 115 | $this->style_inline( (int) $mb_column, (float) $mb_spacing ); 116 | $this->render_header(); 117 | if ( $this->parent->get_settings_for_display( 'mb_skin_template' ) ) { 118 | $group_fields->display_data_template( $this->parent->get_settings_for_display( 'mb_skin_template' ), $data_groups, $data_column, [ 119 | 'loop_header' => $this->render_loop_header(), 120 | 'loop_footer' => $this->render_loop_footer(), 121 | ] ); 122 | } else { 123 | $group_fields->display_data_widget( $data_groups, $data_column, [ 124 | 'loop_header' => $this->render_loop_header(), 125 | 'loop_footer' => $this->render_loop_footer(), 126 | ]); 127 | } 128 | $this->render_footer(); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Widgets/MBGroup.php: -------------------------------------------------------------------------------- 1 | start_controls_section( 'section_metabox', [ 83 | 'label' => esc_html__( 'Meta Box Group', 'mb-elementor-integrator' ), 84 | ] ); 85 | 86 | $this->update_control( '_skin', [ 87 | 'label' => esc_html__( 'Type', 'mb-elementor-integrator' ), 88 | ] ); 89 | 90 | $this->add_control( 'object-type', [ 91 | 'label' => esc_html__( 'Object Type', 'mb-elementor-integrator' ), 92 | 'type' => Controls_Manager::SELECT, 93 | 'options' => [ 94 | 'post' => esc_html__( 'Post', 'mb-elementor-integrator' ), 95 | 'setting' => esc_html__( 'Settings page', 'mb-elementor-integrator' ), 96 | ], 97 | 'default' => 'post', 98 | ] ); 99 | 100 | $group_fields = new GroupField(); 101 | $options = $group_fields->get_list_field_group( 'post' ); 102 | $this->add_control( 'field-group', [ 103 | 'label' => esc_html__( 'Group', 'mb-elementor-integrator' ), 104 | 'type' => Controls_Manager::SELECT2, 105 | 'label_block' => true, 106 | 'options' => $options, 107 | 'default' => key( $options ), 108 | 'condition' => [ 109 | 'object-type' => 'post', 110 | ], 111 | ] ); 112 | 113 | $options = $group_fields->get_list_field_group( 'setting' ); 114 | $this->add_control( 'field-group-setting', [ 115 | 'label' => esc_html__( 'Group', 'mb-elementor-integrator' ), 116 | 'type' => Controls_Manager::SELECT2, 117 | 'label_block' => true, 118 | 'options' => $options, 119 | 'default' => key( $options ), 120 | 'condition' => [ 121 | 'object-type' => 'setting', 122 | ], 123 | ] ); 124 | 125 | $this->add_control( 'mb_skin_template', [ 126 | 'label' => __( 'Skin', 'mb-elementor-integrator' ), 127 | 'description' => '
' . 129 | __( 'Create/edit a Group Skin', 'mb-elementor-integrator' ) . '
', 130 | 'type' => Controls_Manager::SELECT2, 131 | 'label_block' => true, 132 | 'default' => [], 133 | 'options' => $group_fields->get_skin_template(), 134 | ] ); 135 | 136 | $this->end_controls_section(); 137 | 138 | $this->start_controls_section( 'section_display', [ 139 | 'label' => esc_html__( 'Display', 'mb-elementor-integrator' ), 140 | ] ); 141 | 142 | $this->add_responsive_control( 'mb_column', [ 143 | 'label' => __( 'Columns', 'mb-elementor-integrator' ), 144 | 'type' => Controls_Manager::NUMBER, 145 | 'devices' => [ 'desktop', 'tablet', 'mobile' ], 146 | 'desktop_default' => 3, 147 | 'tablet_default' => 2, 148 | 'mobile_default' => 1, 149 | 'selectors' => [ 150 | '{{WRAPPER}} .mbei-groups' => 'display: grid; grid-template-columns: repeat({{SIZE}}, 1fr);', 151 | ], 152 | ] ); 153 | 154 | $this->add_responsive_control( 'mb_spacing', [ 155 | 'label' => __( 'Spacing Item (px)', 'mb-elementor-integrator' ), 156 | 'type' => Controls_Manager::NUMBER, 157 | 'devices' => [ 'desktop', 'tablet', 'mobile' ], 158 | 'desktop_default' => 20, 159 | 'tablet_default' => 20, 160 | 'mobile_default' => 10, 161 | 'selectors' => [ 162 | '{{WRAPPER}} .mbei-groups' => 'gap: {{SIZE}}px;', 163 | ], 164 | ] ); 165 | 166 | $this->end_controls_section(); 167 | } 168 | 169 | public function render_nested_group( $data_groups, $data_column, $group_fields ) { 170 | if ( false === is_int( key( $data_groups ) ) ) { 171 | $data_groups = [ $data_groups ]; 172 | } 173 | 174 | foreach ( $data_groups as $data_group ) { 175 | echo '
'; 176 | foreach ( $data_group as $key => $value ) { 177 | if ( ! isset( $data_column[ $key ] ) ) { 178 | continue; 179 | } 180 | 181 | echo '
'; 182 | if ( is_array( $value ) && ! empty( $value ) ) { 183 | $data_column[ $key ]['fields'] = array_combine( array_column( $data_column[ $key ]['fields'], 'id' ), $data_column[ $key ]['fields'] ); 184 | $this->render_nested_group( $value, $data_column[ $key ]['fields'], $group_fields ); 185 | continue; 186 | } 187 | $group_fields->display_field( $value, $data_column[ $key ] ); 188 | echo '
'; 189 | } 190 | echo '
'; 191 | } 192 | } 193 | 194 | private function render_header() { 195 | ?>
'; 204 | } 205 | 206 | protected function render_loop_footer() { 207 | return ''; 208 | } 209 | 210 | /** 211 | * Render Term List widget output on the frontend. 212 | * 213 | * Written in PHP and used to generate the final HTML. 214 | * 215 | * @since 0.1 216 | * @access protected 217 | */ 218 | protected function render() { 219 | $group_fields = new GroupField(); 220 | $post = $group_fields->get_current_post(); 221 | 222 | $data_groups = []; 223 | $data_column = []; 224 | 225 | $settings = $this->get_settings_for_display(); 226 | if ( empty( $settings['object-type'] ) ) { 227 | return; 228 | } 229 | 230 | if ( $settings['object-type'] === 'post' && ( ! isset( $settings['field-group'] ) || empty( $settings['field-group'] ) ) ) { 231 | return; 232 | } 233 | 234 | if ( $settings['object-type'] === 'setting' && ( ! isset( $settings['field-group-setting'] ) || empty( $settings['field-group-setting'] ) ) ) { 235 | return; 236 | } 237 | 238 | // check group nested 239 | $field_group = $settings['object-type'] === 'post' ? $settings['field-group'] : $settings['field-group-setting']; 240 | $field_group = false !== strpos( $field_group, '.' ) ? explode( '.', $field_group ) : (array) $field_group; 241 | 242 | if ( 'setting' === $settings['object-type'] ) { 243 | $object_setting = array_shift( $field_group ); 244 | } 245 | 246 | $data_groups = 'post' === $settings['object-type'] ? rwmb_meta( $field_group[0], [], $post->ID ) : rwmb_meta( $field_group[0], [ 'object_type' => 'setting' ], $object_setting ); 247 | 248 | array_shift( $field_group ); 249 | if ( ! empty( $field_group ) ) { 250 | $data_groups = $group_fields->get_value_nested_group( $data_groups, $field_group ); 251 | } 252 | 253 | if ( empty( $data_groups ) ) { 254 | return; 255 | } 256 | 257 | if ( false === is_int( key( $data_groups ) ) ) { 258 | $data_groups = [ $data_groups ]; 259 | } 260 | 261 | $fields = $group_fields->get_field_group( 'post' === $settings['object-type'] ? $settings['field-group'] : $settings['field-group-setting'], $settings['object-type'] ); 262 | $data_column = array_combine( array_column( $fields['fields'], 'id' ), $fields['fields'] ); 263 | 264 | $this->render_header(); 265 | if ( $this->get_settings_for_display( 'mb_skin_template' ) ) { 266 | $group_fields->display_data_template( $this->get_settings_for_display( 'mb_skin_template' ), $data_groups, $data_column, [ 267 | 'loop_header' => $this->render_loop_header(), 268 | 'loop_footer' => $this->render_loop_footer(), 269 | ] ); 270 | } else { 271 | $group_fields->display_data_widget( $data_groups, $data_column, [ 272 | 'loop_header' => $this->render_loop_header(), 273 | 'loop_footer' => $this->render_loop_footer(), 274 | ]); 275 | } 276 | $this->render_footer(); 277 | } 278 | 279 | protected function content_template() { 280 | parent::content_template(); 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /src/assets/images/mbgroup.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Edit Custom Grid 145 | 146 | 147 | 148 | 149 | 150 | 151 | --------------------------------------------------------------------------------