← All changes
|
includes/widgets/Dynamic_Posts_Grid/Dynamic_Posts_Grid.php
+335
-29
51.1.14
→
51.1.87
View file →
| @@ -22,9 +22,22 @@ | ||
| 22 | 22 | * Features different post types, color coding, and responsive design. |
| 23 | 23 | */ |
| 24 | 24 | class Dynamic_Posts_Grid extends Widget_Base |
| 25 | 25 | { |
| 26 | + /** | |
| 27 | + * Allow Pro to fully override widget output without using parent::render(). | |
| 28 | + * | |
| 29 | + * Pro can return true to indicate it rendered the widget output completely. | |
| 30 | + * | |
| 31 | + * @param array<string, mixed> $settings Widget settings for display. | |
| 32 | + * @return bool Whether Pro rendered output. | |
| 33 | + */ | |
| 34 | + public function maybe_render_pro(array $settings): bool | |
| 35 | + { | |
| 36 | + return false; | |
| 37 | + } | |
| 26 | 38 | |
| 39 | + | |
| 27 | 40 | /** |
| 28 | 41 | * Get widget name. |
| 29 | 42 | * |
| 30 | 43 | * @return string Widget name. |
| @@ -70,9 +83,12 @@ | ||
| 70 | 83 | * @return array Script dependencies. |
| 71 | 84 | */ |
| 72 | 85 | public function get_script_depends(): array |
| 73 | 86 | { |
| 74 | - return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-dynamic-posts-grid-script']; | |
| 87 | + return [ | |
| 88 | + KING_ADDONS_ASSETS_UNIQUE_KEY . '-dompurify-purify.min', | |
| 89 | + KING_ADDONS_ASSETS_UNIQUE_KEY . '-dynamic-posts-grid-script' | |
| 90 | + ]; | |
| 75 | 91 | } |
| 76 | 92 | |
| 77 | 93 | /** |
| 78 | 94 | * Get widget categories. |
| @@ -165,9 +181,12 @@ | ||
| 165 | 181 | </div>', |
| 166 | 182 | ] |
| 167 | 183 | ); |
| 168 | 184 | |
| 169 | - // Post Types | |
| 185 | + // PRO: Widget Mode Control | |
| 186 | + $this->add_control_widget_mode(); | |
| 187 | + | |
| 188 | + // Post Types (shown only in Default mode) | |
| 170 | 189 | $this->add_control( |
| 171 | 190 | 'kng_dynamic_posts_post_types', |
| 172 | 191 | [ |
| 173 | 192 | 'label' => esc_html__('Post Types', 'king-addons'), |
| @@ -175,11 +194,17 @@ | ||
| 175 | 194 | 'multiple' => true, |
| 176 | 195 | 'options' => $this->get_post_types(), |
| 177 | 196 | 'default' => ['post'], |
| 178 | 197 | 'description' => esc_html__('Select post types to display', 'king-addons'), |
| 198 | + 'condition' => [ | |
| 199 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'], | |
| 200 | + ], | |
| 179 | 201 | ] |
| 180 | 202 | ); |
| 181 | 203 | |
| 204 | + // PRO: Custom Post Types Control | |
| 205 | + $this->add_control_custom_post_types(); | |
| 206 | + | |
| 182 | 207 | // Posts per page |
| 183 | 208 | $this->add_control( |
| 184 | 209 | 'kng_dynamic_posts_per_page', |
| 185 | 210 | [ |
| @@ -264,9 +289,9 @@ | ||
| 264 | 289 | ], |
| 265 | 290 | ] |
| 266 | 291 | ); |
| 267 | 292 | |
| 268 | - // Filter taxonomy | |
| 293 | + // Filter taxonomy (shown only in Default mode) | |
| 269 | 294 | $this->add_control( |
| 270 | 295 | 'kng_dynamic_posts_filter_taxonomy', |
| 271 | 296 | [ |
| 272 | 297 | 'label' => esc_html__('Filter Taxonomy', 'king-addons'), |
| @@ -274,8 +299,9 @@ | ||
| 274 | 299 | 'options' => $this->get_taxonomies(), |
| 275 | 300 | 'default' => 'category', |
| 276 | 301 | 'condition' => [ |
| 277 | 302 | 'kng_dynamic_posts_enable_filters' => 'yes', |
| 303 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'], | |
| 278 | 304 | ], |
| 279 | 305 | ] |
| 280 | 306 | ); |
| 281 | 307 | |
| @@ -445,10 +471,54 @@ | ||
| 445 | 471 | ], |
| 446 | 472 | ] |
| 447 | 473 | ); |
| 448 | 474 | |
| 475 | + // PRO: Pagination Type Control | |
| 476 | + $this->add_control_pagination_type(); | |
| 477 | + | |
| 478 | + // PRO: Scroll Threshold Control | |
| 479 | + $this->add_control_scroll_threshold(); | |
| 480 | + | |
| 449 | 481 | $this->end_controls_section(); |
| 450 | 482 | |
| 483 | + // PRO: CPT Actions Section | |
| 484 | + $this->start_controls_section( | |
| 485 | + 'kng_dynamic_posts_cpt_actions_section', | |
| 486 | + [ | |
| 487 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CPT Action Types', 'king-addons') . ' ' . esc_html__('(PRO)', 'king-addons'), | |
| 488 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 489 | + 'condition' => [ | |
| 490 | + 'kng_dynamic_posts_widget_mode' => 'custom_cpt', | |
| 491 | + ], | |
| 492 | + ] | |
| 493 | + ); | |
| 494 | + | |
| 495 | + // PRO: CPT Actions Control | |
| 496 | + $this->add_control_cpt_actions(); | |
| 497 | + | |
| 498 | + $this->end_controls_section(); | |
| 499 | + | |
| 500 | + // PRO: Meta Fields Section | |
| 501 | + $this->start_controls_section( | |
| 502 | + 'kng_dynamic_posts_meta_fields_section', | |
| 503 | + [ | |
| 504 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Meta Fields', 'king-addons') . ' ' . esc_html__('(PRO)', 'king-addons'), | |
| 505 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 506 | + ] | |
| 507 | + ); | |
| 508 | + | |
| 509 | + // PRO: Show Meta Control | |
| 510 | + $this->add_control_show_meta(); | |
| 511 | + | |
| 512 | + // PRO: Meta Fields Control | |
| 513 | + $this->add_control_meta_fields(); | |
| 514 | + | |
| 515 | + // Both controls above are Pro-only, so without this the free build shows | |
| 516 | + // a section header that expands onto an empty panel. | |
| 517 | + Core::renderUpgradeProSection($this, Controls_Manager::RAW_HTML, 'dynamic-posts-grid', 'kng_dynamic_posts_meta_fields_pro_notice_'); | |
| 518 | + | |
| 519 | + $this->end_controls_section(); | |
| 520 | + | |
| 451 | 521 | // Category Colors Section |
| 452 | 522 | $this->start_controls_section( |
| 453 | 523 | 'kng_dynamic_posts_category_colors_section', |
| 454 | 524 | [ |
| @@ -453,8 +523,11 @@ | ||
| 453 | 523 | 'kng_dynamic_posts_category_colors_section', |
| 454 | 524 | [ |
| 455 | 525 | 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Category Colors', 'king-addons'), |
| 456 | 526 | 'tab' => Controls_Manager::TAB_CONTENT, |
| 527 | + 'condition' => [ | |
| 528 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'] | |
| 529 | + ] | |
| 457 | 530 | ] |
| 458 | 531 | ); |
| 459 | 532 | |
| 460 | 533 | // Get categories dynamically |
| @@ -461,13 +534,33 @@ | ||
| 461 | 534 | $this->add_dynamic_category_colors(); |
| 462 | 535 | |
| 463 | 536 | $this->end_controls_section(); |
| 464 | 537 | |
| 538 | + // CPT Colors Section (PRO) | |
| 465 | 539 | $this->start_controls_section( |
| 540 | + 'kng_dynamic_posts_cpt_colors_section', | |
| 541 | + [ | |
| 542 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CPT Colors', 'king-addons'), | |
| 543 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 544 | + 'condition' => [ | |
| 545 | + 'kng_dynamic_posts_widget_mode' => 'custom_cpt' | |
| 546 | + ] | |
| 547 | + ] | |
| 548 | + ); | |
| 549 | + | |
| 550 | + // PRO: CPT Colors | |
| 551 | + $this->add_control_cpt_colors(); | |
| 552 | + | |
| 553 | + $this->end_controls_section(); | |
| 554 | + | |
| 555 | + $this->start_controls_section( | |
| 466 | 556 | 'kng_dynamic_posts_category_button_colors_section', |
| 467 | 557 | [ |
| 468 | 558 | 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Category Button Colors', 'king-addons'), |
| 469 | 559 | 'tab' => Controls_Manager::TAB_CONTENT, |
| 560 | + 'condition' => [ | |
| 561 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'] | |
| 562 | + ] | |
| 470 | 563 | ] |
| 471 | 564 | ); |
| 472 | 565 | |
| 473 | 566 | // Dynamic category button colors |
| @@ -474,10 +567,27 @@ | ||
| 474 | 567 | $this->add_dynamic_category_button_colors(); |
| 475 | 568 | |
| 476 | 569 | $this->end_controls_section(); |
| 477 | 570 | |
| 571 | + // CPT Button Colors Section (PRO) | |
| 572 | + $this->start_controls_section( | |
| 573 | + 'kng_dynamic_posts_cpt_button_colors_section', | |
| 574 | + [ | |
| 575 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CPT Button Colors', 'king-addons'), | |
| 576 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 577 | + 'condition' => [ | |
| 578 | + 'kng_dynamic_posts_widget_mode' => 'custom_cpt' | |
| 579 | + ] | |
| 580 | + ] | |
| 581 | + ); | |
| 478 | 582 | |
| 583 | + // PRO: CPT Button Colors | |
| 584 | + $this->add_control_cpt_button_colors(); | |
| 479 | 585 | |
| 586 | + $this->end_controls_section(); | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 480 | 590 | // Category CTAs Section |
| 481 | 591 | $this->start_controls_section( |
| 482 | 592 | 'kng_dynamic_posts_ctas_section', |
| 483 | 593 | [ |
| @@ -482,8 +592,11 @@ | ||
| 482 | 592 | 'kng_dynamic_posts_ctas_section', |
| 483 | 593 | [ |
| 484 | 594 | 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Category Button Text', 'king-addons'), |
| 485 | 595 | 'tab' => Controls_Manager::TAB_CONTENT, |
| 596 | + 'condition' => [ | |
| 597 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'] | |
| 598 | + ] | |
| 486 | 599 | ] |
| 487 | 600 | ); |
| 488 | 601 | |
| 489 | 602 | // Get categories dynamically |
| @@ -490,8 +603,25 @@ | ||
| 490 | 603 | $this->add_dynamic_category_ctas(); |
| 491 | 604 | |
| 492 | 605 | $this->end_controls_section(); |
| 493 | 606 | |
| 607 | + // CPT Button Text Section (PRO) | |
| 608 | + $this->start_controls_section( | |
| 609 | + 'kng_dynamic_posts_cpt_ctas_section', | |
| 610 | + [ | |
| 611 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CPT Button Text', 'king-addons'), | |
| 612 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 613 | + 'condition' => [ | |
| 614 | + 'kng_dynamic_posts_widget_mode' => 'custom_cpt' | |
| 615 | + ] | |
| 616 | + ] | |
| 617 | + ); | |
| 618 | + | |
| 619 | + // PRO: CPT Button Text | |
| 620 | + $this->add_control_cpt_ctas(); | |
| 621 | + | |
| 622 | + $this->end_controls_section(); | |
| 623 | + | |
| 494 | 624 | // Category Icons Section |
| 495 | 625 | $this->start_controls_section( |
| 496 | 626 | 'kng_dynamic_posts_icons_section', |
| 497 | 627 | [ |
| @@ -496,8 +626,11 @@ | ||
| 496 | 626 | 'kng_dynamic_posts_icons_section', |
| 497 | 627 | [ |
| 498 | 628 | 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Category Icons', 'king-addons'), |
| 499 | 629 | 'tab' => Controls_Manager::TAB_CONTENT, |
| 630 | + 'condition' => [ | |
| 631 | + 'kng_dynamic_posts_widget_mode' => ['', 'default'] | |
| 632 | + ] | |
| 500 | 633 | ] |
| 501 | 634 | ); |
| 502 | 635 | |
| 503 | 636 | // Get categories dynamically |
| @@ -504,8 +637,25 @@ | ||
| 504 | 637 | $this->add_dynamic_category_icons(); |
| 505 | 638 | |
| 506 | 639 | $this->end_controls_section(); |
| 507 | 640 | |
| 641 | + // CPT Icons Section (PRO) | |
| 642 | + $this->start_controls_section( | |
| 643 | + 'kng_dynamic_posts_cpt_icons_section', | |
| 644 | + [ | |
| 645 | + 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CPT Icons', 'king-addons'), | |
| 646 | + 'tab' => Controls_Manager::TAB_CONTENT, | |
| 647 | + 'condition' => [ | |
| 648 | + 'kng_dynamic_posts_widget_mode' => 'custom_cpt' | |
| 649 | + ] | |
| 650 | + ] | |
| 651 | + ); | |
| 652 | + | |
| 653 | + // PRO: CPT Icons | |
| 654 | + $this->add_control_cpt_icons(); | |
| 655 | + | |
| 656 | + $this->end_controls_section(); | |
| 657 | + | |
| 508 | 658 | // Pro Features Section |
| 509 | 659 | if (!king_addons_freemius()->can_use_premium_code__premium_only()) { |
| 510 | 660 | Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'dynamic-posts-grid', [ |
| 511 | 661 | 'Advanced Query Builder', |
| @@ -517,8 +667,11 @@ | ||
| 517 | 667 | 'Custom Date Range Filters', |
| 518 | 668 | 'Author-based Filtering' |
| 519 | 669 | ]); |
| 520 | 670 | } |
| 671 | + | |
| 672 | + // PRO extension point to append content controls without duplicating base controls | |
| 673 | + // Pro content controls are added via add_control_* method calls above | |
| 521 | 674 | } |
| 522 | 675 | |
| 523 | 676 | /** |
| 524 | 677 | * Register style controls. |
| @@ -1422,12 +1575,12 @@ | ||
| 1422 | 1575 | 'label' => esc_html__('Button Padding', 'king-addons'), |
| 1423 | 1576 | 'type' => Controls_Manager::DIMENSIONS, |
| 1424 | 1577 | 'size_units' => ['px', 'em', '%'], |
| 1425 | 1578 | 'default' => [ |
| 1426 | - 'top' => 12, | |
| 1427 | - 'right' => 16, | |
| 1428 | - 'bottom' => 12, | |
| 1429 | - 'left' => 16, | |
| 1579 | + 'top' => 8, | |
| 1580 | + 'right' => 12, | |
| 1581 | + 'bottom' => 8, | |
| 1582 | + 'left' => 12, | |
| 1430 | 1583 | 'unit' => 'px', |
| 1431 | 1584 | ], |
| 1432 | 1585 | 'selectors' => [ |
| 1433 | 1586 | '{{WRAPPER}} .king-addons-dpg-search-btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', |
| @@ -3185,9 +3338,9 @@ | ||
| 3185 | 3338 | * Get available post types. |
| 3186 | 3339 | * |
| 3187 | 3340 | * @return array Post types array. |
| 3188 | 3341 | */ |
| 3189 | - private function get_post_types(): array | |
| 3342 | + protected function get_post_types(): array | |
| 3190 | 3343 | { |
| 3191 | 3344 | $post_types = get_post_types(['public' => true], 'objects'); |
| 3192 | 3345 | $options = []; |
| 3193 | 3346 | |
| @@ -3202,9 +3355,9 @@ | ||
| 3202 | 3355 | * Get available taxonomies. |
| 3203 | 3356 | * |
| 3204 | 3357 | * @return array Taxonomies array. |
| 3205 | 3358 | */ |
| 3206 | - private function get_taxonomies(): array | |
| 3359 | + protected function get_taxonomies(): array | |
| 3207 | 3360 | { |
| 3208 | 3361 | $taxonomies = get_taxonomies(['public' => true], 'objects'); |
| 3209 | 3362 | $options = []; |
| 3210 | 3363 | |
| @@ -3217,9 +3370,9 @@ | ||
| 3217 | 3370 | |
| 3218 | 3371 | /** |
| 3219 | 3372 | * Add dynamic category color controls. |
| 3220 | 3373 | */ |
| 3221 | - private function add_dynamic_category_colors(): void | |
| 3374 | + protected function add_dynamic_category_colors(): void | |
| 3222 | 3375 | { |
| 3223 | 3376 | // Get taxonomy from filter settings (default to category) |
| 3224 | 3377 | $taxonomy = 'category'; |
| 3225 | 3378 | |
| @@ -3311,9 +3464,9 @@ | ||
| 3311 | 3464 | |
| 3312 | 3465 | /** |
| 3313 | 3466 | * Add dynamic category icon controls. |
| 3314 | 3467 | */ |
| 3315 | - private function add_dynamic_category_icons(): void | |
| 3468 | + protected function add_dynamic_category_icons(): void | |
| 3316 | 3469 | { |
| 3317 | 3470 | // Get taxonomy from filter settings (default to category) |
| 3318 | 3471 | $taxonomy = 'category'; |
| 3319 | 3472 | |
| @@ -3503,9 +3656,9 @@ | ||
| 3503 | 3656 | |
| 3504 | 3657 | /** |
| 3505 | 3658 | * Add dynamic category CTA controls. |
| 3506 | 3659 | */ |
| 3507 | - private function add_dynamic_category_ctas(): void | |
| 3660 | + protected function add_dynamic_category_ctas(): void | |
| 3508 | 3661 | { |
| 3509 | 3662 | // Get taxonomy from filter settings (default to category) |
| 3510 | 3663 | $taxonomy = 'category'; |
| 3511 | 3664 | |
| @@ -3587,9 +3740,9 @@ | ||
| 3587 | 3740 | |
| 3588 | 3741 | /** |
| 3589 | 3742 | * Add dynamic category button color controls. |
| 3590 | 3743 | */ |
| 3591 | - private function add_dynamic_category_button_colors(): void | |
| 3744 | + protected function add_dynamic_category_button_colors(): void | |
| 3592 | 3745 | { |
| 3593 | 3746 | // Get taxonomy from filter settings (default to category) |
| 3594 | 3747 | $taxonomy = 'category'; |
| 3595 | 3748 | |
| @@ -3731,20 +3884,8 @@ | ||
| 3731 | 3884 | ], |
| 3732 | 3885 | ] |
| 3733 | 3886 | ); |
| 3734 | 3887 | |
| 3735 | - $this->add_control( | |
| 3736 | - 'kng_dynamic_posts_default_button_border_color', | |
| 3737 | - [ | |
| 3738 | - 'label' => esc_html__('Default Button Border Color', 'king-addons'), | |
| 3739 | - 'type' => Controls_Manager::COLOR, | |
| 3740 | - 'default' => 'rgba(0, 0, 0, 0.1)', | |
| 3741 | - 'selectors' => [ | |
| 3742 | - '{{WRAPPER}} .king-addons-dpg-button' => 'border-color: {{VALUE}};', | |
| 3743 | - ], | |
| 3744 | - ] | |
| 3745 | - ); | |
| 3746 | - | |
| 3747 | 3888 | // Category-specific colors |
| 3748 | 3889 | $default_colors = [ |
| 3749 | 3890 | ['color' => '#FFFFFF', 'bg' => '#EF4444', 'hover_color' => '#FFFFFF', 'hover_bg' => '#DC2626', 'border' => '#EF4444'], // Red |
| 3750 | 3891 | ['color' => '#FFFFFF', 'bg' => '#3B82F6', 'hover_color' => '#FFFFFF', 'hover_bg' => '#2563EB', 'border' => '#3B82F6'], // Blue |
| @@ -4022,8 +4163,12 @@ | ||
| 4022 | 4163 | { |
| 4023 | 4164 | $settings = $this->get_settings_for_display(); |
| 4024 | 4165 | $widget_id = $this->get_id(); |
| 4025 | 4166 | |
| 4167 | + if ($this->maybe_render_pro($settings)) { | |
| 4168 | + return; | |
| 4169 | + } | |
| 4170 | + | |
| 4026 | 4171 | // Query posts |
| 4027 | 4172 | $query_args = [ |
| 4028 | 4173 | 'post_type' => $settings['kng_dynamic_posts_post_types'], |
| 4029 | 4174 | 'posts_per_page' => $settings['kng_dynamic_posts_per_page'], |
| @@ -4046,8 +4191,9 @@ | ||
| 4046 | 4191 | |
| 4047 | 4192 | // Wrapper attributes |
| 4048 | 4193 | $this->add_render_attribute('wrapper', 'class', 'king-addons-dpg-wrapper'); |
| 4049 | 4194 | $this->add_render_attribute('wrapper', 'data-widget-id', $widget_id); |
| 4195 | + $this->add_render_attribute('wrapper', 'data-widget-mode', 'default'); // Set default mode for Free version | |
| 4050 | 4196 | $this->add_render_attribute('wrapper', 'data-posts-per-page', $settings['kng_dynamic_posts_per_page']); |
| 4051 | 4197 | $this->add_render_attribute('wrapper', 'data-post-types', wp_json_encode($settings['kng_dynamic_posts_post_types'])); |
| 4052 | 4198 | $this->add_render_attribute('wrapper', 'data-orderby', $settings['kng_dynamic_posts_orderby']); |
| 4053 | 4199 | $this->add_render_attribute('wrapper', 'data-order', $settings['kng_dynamic_posts_order']); |
| @@ -4056,8 +4202,12 @@ | ||
| 4056 | 4202 | |
| 4057 | 4203 | if ($settings['kng_dynamic_posts_enable_filters'] === 'yes') { |
| 4058 | 4204 | $this->add_render_attribute('wrapper', 'data-filter-taxonomy', $settings['kng_dynamic_posts_filter_taxonomy']); |
| 4059 | 4205 | } |
| 4206 | + | |
| 4207 | + // CPT-related attributes (empty for Free version, but needed for JS compatibility) | |
| 4208 | + $this->add_render_attribute('wrapper', 'data-cpt-actions', ''); | |
| 4209 | + $this->add_render_attribute('wrapper', 'data-cpt-icons', ''); | |
| 4060 | 4210 | ?> |
| 4061 | 4211 | |
| 4062 | 4212 | <div <?php echo $this->get_render_attribute_string('wrapper'); ?>> |
| 4063 | 4213 | |
| @@ -4118,9 +4268,9 @@ | ||
| 4118 | 4268 | </div> |
| 4119 | 4269 | <?php endif; ?> |
| 4120 | 4270 | |
| 4121 | 4271 | <!-- Grid Container --> |
| 4122 | - <div class="king-addons-dpg-grid" data-columns="<?php echo esc_attr($settings['kng_dynamic_posts_columns']); ?>"> | |
| 4272 | + <div class="king-addons-dpg-grid" data-columns="<?php echo esc_attr($settings['kng_dynamic_posts_columns'] ?? '3'); ?>"> | |
| 4123 | 4273 | <?php $this->render_posts($posts_query, $settings); ?> |
| 4124 | 4274 | </div> |
| 4125 | 4275 | |
| 4126 | 4276 | <?php if ($settings['kng_dynamic_posts_enable_load_more'] === 'yes'): ?> |
| @@ -4204,11 +4354,9 @@ | ||
| 4204 | 4354 | </div> |
| 4205 | 4355 | |
| 4206 | 4356 | <!-- CTA Button --> |
| 4207 | 4357 | <div class="king-addons-dpg-cta"> |
| 4208 | - <a href="<?php echo esc_url(get_permalink()); ?>" class="king-addons-dpg-button"> | |
| 4209 | - <?php echo esc_html($cta_text); ?> | |
| 4210 | - </a> | |
| 4358 | + <?php echo $this->get_cta_button_html($post, $settings, $cta_text); ?> | |
| 4211 | 4359 | </div> |
| 4212 | 4360 | |
| 4213 | 4361 | </div> |
| 4214 | 4362 | |
| @@ -4214,5 +4362,163 @@ | ||
| 4214 | 4362 | |
| 4215 | 4363 | <?php |
| 4216 | 4364 | endwhile; |
| 4217 | 4365 | } |
| 4366 | + | |
| 4367 | + /** | |
| 4368 | + * Build WP_Query args. Pro overrides to support Custom CPT mode. | |
| 4369 | + * | |
| 4370 | + * @param array $settings Widget settings. | |
| 4371 | + * @return array | |
| 4372 | + */ | |
| 4373 | + protected function build_query_args(array $settings): array | |
| 4374 | + { | |
| 4375 | + return [ | |
| 4376 | + 'post_type' => $settings['kng_dynamic_posts_post_types'], | |
| 4377 | + 'posts_per_page' => $settings['kng_dynamic_posts_per_page'], | |
| 4378 | + 'orderby' => $settings['kng_dynamic_posts_orderby'], | |
| 4379 | + 'order' => $settings['kng_dynamic_posts_order'], | |
| 4380 | + 'post_status' => 'publish', | |
| 4381 | + ]; | |
| 4382 | + } | |
| 4383 | + | |
| 4384 | + /** | |
| 4385 | + * Build filter terms data for filter bar. Pro overrides for CPT/tabs. | |
| 4386 | + * | |
| 4387 | + * @param array $settings Widget settings. | |
| 4388 | + * @return array | |
| 4389 | + */ | |
| 4390 | + protected function get_filter_terms(array $settings): array | |
| 4391 | + { | |
| 4392 | + if (($settings['kng_dynamic_posts_enable_filters'] ?? '') !== 'yes') { | |
| 4393 | + return []; | |
| 4394 | + } | |
| 4395 | + | |
| 4396 | + $taxonomy = $settings['kng_dynamic_posts_filter_taxonomy'] ?? 'category'; | |
| 4397 | + $terms = get_terms([ | |
| 4398 | + 'taxonomy' => $taxonomy, | |
| 4399 | + 'hide_empty' => true, | |
| 4400 | + ]); | |
| 4401 | + | |
| 4402 | + return is_wp_error($terms) ? [] : $terms; | |
| 4403 | + } | |
| 4404 | + | |
| 4405 | + /** | |
| 4406 | + * Render filter bar wrapper. Pro overrides for advanced UI. | |
| 4407 | + * | |
| 4408 | + * @param array $settings Widget settings. | |
| 4409 | + * @param array $filter_terms Terms list or structured data. | |
| 4410 | + */ | |
| 4411 | + protected function render_filter_bar(array $settings, array $filter_terms): void | |
| 4412 | + { | |
| 4413 | + if (($settings['kng_dynamic_posts_enable_filters'] ?? '') !== 'yes' && ($settings['kng_dynamic_posts_enable_search'] ?? '') !== 'yes') { | |
| 4414 | + return; | |
| 4415 | + } | |
| 4416 | + ?> | |
| 4417 | + <div class="king-addons-dpg-filter-bar"> | |
| 4418 | + <div class="king-addons-dpg-filter-header"> | |
| 4419 | + <h2 class="king-addons-dpg-filter-title"><?php echo esc_html($settings['kng_dynamic_posts_filter_title_text'] ?? ''); ?></h2> | |
| 4420 | + </div> | |
| 4421 | + | |
| 4422 | + <div class="king-addons-dpg-filter-controls"> | |
| 4423 | + <?php if (($settings['kng_dynamic_posts_enable_filters'] ?? '') === 'yes' && !empty($filter_terms)): ?> | |
| 4424 | + <div class="king-addons-dpg-filter-dropdown<?php | |
| 4425 | + $has_custom = !empty($settings['kng_dynamic_posts_filter_dropdown_use_custom']) && $settings['kng_dynamic_posts_filter_dropdown_use_custom'] === 'yes'; | |
| 4426 | + $has_icon = $has_custom && ($settings['kng_dynamic_posts_filter_dropdown_type'] ?? 'icon') === 'icon' && !empty($settings['kng_dynamic_posts_filter_dropdown_custom_icon']['value'] ?? ''); | |
| 4427 | + $has_image = $has_custom && ($settings['kng_dynamic_posts_filter_dropdown_type'] ?? 'icon') === 'image' && !empty($settings['kng_dynamic_posts_filter_dropdown_custom_image']['url'] ?? ''); | |
| 4428 | + echo ($has_custom && ($has_icon || $has_image)) ? ' has-custom-icon' : ''; | |
| 4429 | + ?>"> | |
| 4430 | + <select class="king-addons-dpg-posts-filter" data-taxonomy="<?php echo esc_attr($settings['kng_dynamic_posts_filter_taxonomy'] ?? 'category'); ?>"> | |
| 4431 | + <option value="*"> <?php echo esc_html__('All resources types', 'king-addons'); ?></option> | |
| 4432 | + <?php foreach ($filter_terms as $term): ?> | |
| 4433 | + <option value="<?php echo esc_attr($term->slug); ?>"><?php echo esc_html($term->name); ?></option> | |
| 4434 | + <?php endforeach; ?> | |
| 4435 | + </select> | |
| 4436 | + <?php if ($has_icon): ?> | |
| 4437 | + <span class="dropdown-icon"> | |
| 4438 | + <?php \Elementor\Icons_Manager::render_icon($settings['kng_dynamic_posts_filter_dropdown_custom_icon'], ['class' => 'dropdown-custom-icon']); ?> | |
| 4439 | + </span> | |
| 4440 | + <?php elseif ($has_image): ?> | |
| 4441 | + <span class="dropdown-image"> | |
| 4442 | + <img src="<?php echo esc_url($settings['kng_dynamic_posts_filter_dropdown_custom_image']['url']); ?>" alt="<?php echo esc_attr__('Dropdown icon', 'king-addons'); ?>" /> | |
| 4443 | + </span> | |
| 4444 | + <?php endif; ?> | |
| 4445 | + </div> | |
| 4446 | + <?php endif; ?> | |
| 4447 | + | |
| 4448 | + <?php if (($settings['kng_dynamic_posts_enable_search'] ?? '') === 'yes'): ?> | |
| 4449 | + <div class="king-addons-dpg-search-input"> | |
| 4450 | + <input type="text" class="king-addons-dpg-posts-search" placeholder="<?php echo esc_attr($settings['kng_dynamic_posts_search_placeholder'] ?? ''); ?>"> | |
| 4451 | + <button class="king-addons-dpg-search-btn" type="button"> | |
| 4452 | + <?php if (!empty($settings['kng_dynamic_posts_search_use_custom_icon']) && $settings['kng_dynamic_posts_search_use_custom_icon'] === 'yes' && !empty($settings['kng_dynamic_posts_search_custom_icon']['value'] ?? '')): ?> | |
| 4453 | + <?php \Elementor\Icons_Manager::render_icon($settings['kng_dynamic_posts_search_custom_icon'], ['class' => 'king-addons-dpg-search-custom-icon']); ?> | |
| 4454 | + <?php else: ?> | |
| 4455 | + <svg width="20" height="20" viewBox="0 0 24 24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /></svg> | |
| 4456 | + <?php endif; ?> | |
| 4457 | + </button> | |
| 4458 | + </div> | |
| 4459 | + <?php endif; ?> | |
| 4460 | + </div> | |
| 4461 | + </div> | |
| 4462 | + <?php | |
| 4463 | + } | |
| 4464 | + | |
| 4465 | + /** | |
| 4466 | + * Render pagination wrapper. Pro overrides for advanced types. | |
| 4467 | + * | |
| 4468 | + * @param array $settings | |
| 4469 | + * @param \WP_Query $posts_query | |
| 4470 | + */ | |
| 4471 | + protected function render_pagination(array $settings, \WP_Query $posts_query): void | |
| 4472 | + { | |
| 4473 | + if (($settings['kng_dynamic_posts_enable_load_more'] ?? '') !== 'yes') { | |
| 4474 | + return; | |
| 4475 | + } | |
| 4476 | + ?> | |
| 4477 | + <div class="king-addons-dpg-pagination"> | |
| 4478 | + <div class="king-addons-dpg-pagination-info"> | |
| 4479 | + <?php echo esc_html__('Showing', 'king-addons'); ?> <span class="king-addons-dpg-current-count"><?php echo (int) $posts_query->post_count; ?></span> <?php echo esc_html__('of', 'king-addons'); ?> <span class="king-addons-dpg-total-count"><?php echo (int) $posts_query->found_posts; ?></span> <?php echo esc_html__('items', 'king-addons'); ?> | |
| 4480 | + </div> | |
| 4481 | + <div class="king-addons-dpg-pagination-loading" style="display: none;"> | |
| 4482 | + <?php echo esc_html($settings['kng_dynamic_posts_loading_text'] ?? 'Loading...'); ?> | |
| 4483 | + </div> | |
| 4484 | + <?php if ($posts_query->max_num_pages > 1): ?> | |
| 4485 | + <button class="king-addons-dpg-load-more-btn" data-page="1" data-max-pages="<?php echo esc_attr($posts_query->max_num_pages); ?>"> | |
| 4486 | + <?php echo esc_html($settings['kng_dynamic_posts_load_more_text'] ?? 'LOAD MORE'); ?> | |
| 4487 | + </button> | |
| 4488 | + <?php endif; ?> | |
| 4489 | + <div class="king-addons-dpg-pagination-finish" style="display: none;"> | |
| 4490 | + <?php echo esc_html__('All items loaded', 'king-addons'); ?> | |
| 4491 | + </div> | |
| 4492 | + </div> | |
| 4493 | + <?php | |
| 4494 | + } | |
| 4495 | + | |
| 4496 | + /** | |
| 4497 | + * Render CTA button HTML. Pro overrides to inject action button behaviors. | |
| 4498 | + * | |
| 4499 | + * @param \WP_Post $post | |
| 4500 | + * @param array $settings | |
| 4501 | + * @param string $cta_text | |
| 4502 | + * @return string | |
| 4503 | + */ | |
| 4504 | + protected function get_cta_button_html($post, array $settings, string $cta_text): string | |
| 4505 | + { | |
| 4506 | + return '<a href="' . esc_url(get_permalink($post)) . '" class="king-addons-dpg-button">' . esc_html($cta_text) . '</a>'; | |
| 4507 | + } | |
| 4508 | + | |
| 4509 | + /** | |
| 4510 | + * Extension points for Pro controls (content/style). Intentionally empty in Free. | |
| 4511 | + */ | |
| 4512 | + // PRO Control Methods (empty in Free, overridden in Pro) | |
| 4513 | + public function add_control_widget_mode() {} | |
| 4514 | + public function add_control_custom_post_types() {} | |
| 4515 | + public function add_control_pagination_type() {} | |
| 4516 | + public function add_control_scroll_threshold() {} | |
| 4517 | + public function add_control_show_meta() {} | |
| 4518 | + public function add_control_meta_fields() {} | |
| 4519 | + public function add_control_cpt_actions() {} | |
| 4520 | + public function add_control_cpt_colors() {} | |
| 4521 | + public function add_control_cpt_button_colors() {} | |
| 4522 | + public function add_control_cpt_ctas() {} | |
| 4523 | + public function add_control_cpt_icons() {} | |
| 4218 | 4524 | } |