Files
2025-02-24 22:33:42 +01:00

271 lines
7.0 KiB
PHP

<?php
use Elementor\Controls_Manager;
use Elementor\Group_Control_Text_Shadow;
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Group_Control_Text_Stroke;
use Elementor\Group_Control_Typography;
use ElementorPro\Modules\LoopFilter\Traits\Hierarchical_Taxonomy_Trait;
use ElementorPro\Modules\LoopFilter\Traits\Taxonomy_Filter_Trait;
use ElementorPro\Modules\Posts\Traits\Pagination_Trait;
use Elementor\Utils;
use ElementorPro\Modules\ThemeBuilder\Module as ThemeBuilderModule;
class Elementor_Category_Nav_Tree extends \Elementor\Widget_Base {
use Hierarchical_Taxonomy_Trait;
use Taxonomy_Filter_Trait;
use Pagination_Trait;
public function get_name() {
return 'category_nav_tree';
}
public function get_title() {
return esc_html__( 'Category Nav Tree', 'elementor-addon' );
}
public function get_icon() {
return 'eicon-code';
}
public function get_categories() {
return [ 'basic' ];
}
public function get_keywords() {
return [ 'category', 'nav', 'tree', 'category nav tree' ];
}
protected function register_controls() {
$this->start_controls_section(
'section_title',
[
'label' => esc_html__( 'List', 'elementor' ),
]
);
$this->add_control(
'taxonomy',
[
'label' => esc_html__( 'Taxonomy', 'elementor-pro' ),
'type' => Controls_Manager::SELECT,
'options' => $this->get_taxonomies_list(),
'label_block' => true,
'frontend_available' => true,
]
);
$this->add_control(
"list_dots",
[
'label' => esc_html__( 'List dots - hide', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_on' => esc_html__( 'On', 'elementor' ),
'label_off' => esc_html__( 'Off', 'elementor' ),
'selectors' => [
"{{WRAPPER}} ul" => 'list-style-type: none;',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_title_style',
[
'label' => esc_html__( 'List', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'title_color',
[
'label' => esc_html__( 'Text Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'selectors' => [
'{{WRAPPER}} .category-nav-tree li a' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .category-nav-tree li a',
]
);
$this->add_group_control(
Group_Control_Text_Stroke::get_type(),
[
'name' => 'text_stroke',
'selector' => '{{WRAPPER}} .category-nav-tree li a',
]
);
$this->add_responsive_control(
'list_margin',
[
'label' => esc_html__( 'Margin - list', 'elementor-pro' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .category-nav-tree' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->add_responsive_control(
'list_padding',
[
'label' => esc_html__( 'Padding - list', 'elementor-pro' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
'selectors' => [
'{{WRAPPER}} .category-nav-tree' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
protected function get_taxonomies_list() {
$taxonomies = get_taxonomies( [], 'objects' );
$options = [ '' => esc_html__( 'Select a taxonomy', 'elementor-pro' ) ];
foreach ( $taxonomies as $taxonomy ) {
$options[ $taxonomy->name ] = $taxonomy->label;
}
return $options;
}
public function render() {
if (has_nav_menu('custom-category-menu')) {
$menu_items = wp_get_nav_menu_items(get_nav_menu_locations()['custom-category-menu']);
if ($menu_items) {
$menu_tree = $this->build_menu_tree($menu_items);
echo '<ul class="category-nav-tree">';
$this->render_menu_tree($menu_tree);
echo '</ul>';
} else {
echo '<p>' . esc_html__('No menu items found in the Custom Category Menu.', 'elementor-addon') . '</p>';
}
} else {
echo '<p>' . esc_html__('Please assign a menu to the Custom Category Menu location.', 'elementor-addon') . '</p>';
}
}
protected function build_menu_tree($menu_items) {
$tree = [];
foreach ($menu_items as $item) {
$tree[$item->menu_item_parent][] = $item;
}
return $tree;
}
protected function render_menu_tree($menu_tree, $parent_id = 0, $level = 0) {
if (!isset($menu_tree[$parent_id])) {
return false;
}
$current_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$has_active_child = false;
$parent_is_active = false;
foreach ($menu_tree[$parent_id] as $menu_item) {
$classes = 'lvl-' . esc_attr($level);
$a_classes = '';
$is_current = trailingslashit($menu_item->url) === trailingslashit($current_url);
if ($is_current) {
$classes .= ' active';
$parent_is_active = true;
}
$has_children = isset($menu_tree[$menu_item->ID]);
if ($has_children) {
$a_classes .= 'parent';
}
$child_active = $this->render_menu_tree_helper($menu_tree, $menu_item->ID, $level + 1);
if ($child_active) {
$classes .= ' active';
$has_active_child = true;
}
echo '<li class="' . esc_attr($classes) . '">';
echo '<span class="' . esc_attr($a_classes) . '">';
echo '<a href="' . esc_url($menu_item->url) . '" >';
echo esc_html($menu_item->title);
echo '</a>';
if ($has_children) {
echo '<span class="parent-arrow"><i aria-hidden="true" class="xlio ion-ios-arrow-down"></i></span>';
}
echo '</span>';
if (isset($menu_tree[$menu_item->ID])) {
echo '<ul class="ul-lvl-' . esc_attr($level + 1) . '">';
$this->render_menu_tree($menu_tree, $menu_item->ID, $level + 1);
echo '</ul>';
}
echo '</li>';
}
return $has_active_child || $parent_is_active;
}
protected function render_menu_tree_helper($menu_tree, $parent_id = 0, $level = 0) {
if (!isset($menu_tree[$parent_id])) {
return false;
}
$current_url = (is_ssl() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$has_active_child = false;
$parent_is_active = false;
foreach ($menu_tree[$parent_id] as $menu_item) {
$classes = 'lvl-' . esc_attr($level);
$is_current = trailingslashit($menu_item->url) === trailingslashit($current_url);
if ($is_current) {
$classes .= ' active';
$parent_is_active = true;
}
$child_active2 = $this->render_menu_tree_helper($menu_tree, $menu_item->ID, $level + 1);
if ($child_active2) {
$classes .= ' active';
$has_active_child = true;
}
if (isset($menu_tree[$menu_item->ID])) {
$this->render_menu_tree_helper($menu_tree, $menu_item->ID, $level + 1);
}
}
return $has_active_child || $parent_is_active;
}
}