// Đăng ký Elementor Widget hiển thị danh sách bài viết theo post type & category có phân trang add_action('elementor/widgets/widgets_registered', function () { if (!class_exists('Elementor\\Widget_Base')) return; class Custom_Loop_Widget extends \Elementor\Widget_Base { public function get_name() { return 'custom_loop_widget'; } public function get_title() { return __('Custom Loop Widget', 'custom-loop'); } public function get_icon() { return 'eicon-post-list'; } public function get_categories() { return ['general']; } protected function get_terms_list($taxonomy = 'category') { $terms = get_terms([ 'taxonomy' => $taxonomy, 'hide_empty' => false, ]); $options = []; foreach ($terms as $term) { $options[$term->term_id] = $term->name; } return $options; } protected function register_controls() { $this->start_controls_section('content_section', [ 'label' => __('Query Settings', 'custom-loop'), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ]); $this->add_control('post_type', [ 'label' => __('Post Type', 'custom-loop'), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'post', 'options' => [ 'post' => 'Post', 'page' => 'Page', 'course' => 'Course', 'product' => 'Product', ], ]); $this->add_control('taxonomy', [ 'label' => __('Taxonomy (e.g. category, course_category)', 'custom-loop'), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => 'category', ]); $this->add_control('categories', [ 'label' => __('Categories (select)', 'custom-loop'), 'type' => \Elementor\Controls_Manager::SELECT2, 'multiple' => true, 'label_block' => true, 'options' => $this->get_terms_list(), ]); $this->add_control('relation', [ 'label' => __('Filter Relation', 'custom-loop'), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'OR', 'options' => [ 'OR' => 'OR', 'AND' => 'AND', ], ]); $this->add_control('posts_per_page', [ 'label' => __('Posts Per Page', 'custom-loop'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 6, ]); $this->add_control('show_pagination', [ 'label' => __('Show Pagination', 'custom-loop'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'no', 'label_on' => __('Yes', 'custom-loop'), 'label_off' => __('No', 'custom-loop'), 'return_value' => 'yes', ]); $this->end_controls_section(); } protected function render() { $settings = $this->get_settings_for_display(); $taxonomy = $settings['taxonomy'] ?: 'category'; $paged = get_query_var('paged') ?: get_query_var('page') ?: 1; $tax_query = []; if (!empty($settings['categories'])) { $tax_query[] = [ 'taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $settings['categories'], ]; } $query_args = [ 'post_type' => $settings['post_type'], 'posts_per_page' => $settings['posts_per_page'], 'paged' => $settings['show_pagination'] === 'yes' ? $paged : 1, ]; if (!empty($tax_query)) { $query_args['tax_query'] = [ 'relation' => $settings['relation'], $tax_query[0], ]; } $query = new WP_Query($query_args); if ($query->have_posts()) { echo '
'; while ($query->have_posts()) { $query->the_post(); echo '
'; if (has_post_thumbnail()) { echo '' . get_the_post_thumbnail(null, 'medium') . ''; } echo '

' . get_the_title() . '

'; echo '
'; } echo '
'; if ($settings['show_pagination'] === 'yes') { echo '
'; echo paginate_links([ 'total' => $query->max_num_pages, 'current' => $paged, ]); echo '
'; } wp_reset_postdata(); } else { echo '

No posts found.

'; } } } \Elementor\Plugin::instance()->widgets_manager->register_widget_type(new Custom_Loop_Widget()); });