File: /home/parhudrw/www/wp-content/plugins/around-elementor/modules/posts/widgets/portfolio.php
<?php
namespace AroundElementor\Modules\Posts\Widgets;
use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
use Elementor\Group_Control_Image_Size;
use Elementor\Group_Control_Typography;
use AroundElementor\Base\Base_Widget;
use AroundElementor\Modules\QueryControl\Module as Module_Query;
use AroundElementor\Modules\QueryControl\Controls\Group_Control_Related;
use Elementor\Controls_Manager;
use AroundElementor\Modules\Posts\Skins;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class Portfolio
*/
class Portfolio extends Base_Widget {
/**
* @var \WP_Query
*/
private $_query = null;
protected $_has_template_content = false;
public function get_name() {
return 'ar-portfolio';
}
public function get_title() {
return __( 'Portfolio', 'around-elementor' );
}
public function get_icon() {
return 'eicon-gallery-grid';
}
public function get_keywords() {
return [ 'posts', 'cpt', 'item', 'loop', 'query', 'portfolio', 'custom post type' ];
}
public function get_script_depends() {
return [ 'imagesloaded' ];
}
public function on_import( $element ) {
if ( ! get_post_type_object( $element['settings']['posts_post_type'] ) ) {
$element['settings']['posts_post_type'] = 'post';
}
return $element;
}
protected function register_skins() {
$this->add_skin( new Skins\Skin_style_1( $this ) );
$this->add_skin( new Skins\Skin_style_2( $this ) );
$this->add_skin( new Skins\Skin_style_3( $this ) );
$this->add_skin( new Skins\Skin_style_4( $this ) );
}
public function get_query() {
return $this->_query;
}
protected function register_controls() {
$this->register_query_section_controls();
$this->register_pagination_section_controls();
}
public function register_pagination_section_controls() {
$this->start_controls_section(
'section_pagination',
[
'label' => __( 'Pagination', 'around-elementor' ),
]
);
$this->add_control(
'pagination_type',
[
'label' => __( 'Pagination', 'around-elementor' ),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => [
'' => __( 'None', 'around-elementor' ),
'numbers' => __( 'Numbers', 'around-elementor' ),
'prev_next' => __( 'Previous/Next', 'around-elementor' ),
'numbers_and_prev_next' => __( 'Numbers', 'around-elementor' ) . ' + ' . __( 'Previous/Next', 'around-elementor' ),
],
]
);
$this->add_control(
'pagination_page_limit',
[
'label' => __( 'Page Limit', 'around-elementor' ),
'default' => '5',
'condition' => [
'pagination_type!' => '',
],
]
);
$this->add_control(
'pagination_numbers_shorten',
[
'label' => __( 'Shorten', 'around-elementor' ),
'type' => Controls_Manager::SWITCHER,
'default' => '',
'condition' => [
'pagination_type' => [
'numbers',
'numbers_and_prev_next',
],
],
]
);
$this->add_control(
'pagination_prev_label',
[
'label' => __( 'Previous Label', 'around-elementor' ),
'default' => __( '« Previous', 'around-elementor' ),
'condition' => [
'pagination_type' => [
'prev_next',
'numbers_and_prev_next',
],
],
]
);
$this->add_control(
'pagination_next_label',
[
'label' => __( 'Next Label', 'around-elementor' ),
'default' => __( 'Next »', 'around-elementor' ),
'condition' => [
'pagination_type' => [
'prev_next',
'numbers_and_prev_next',
],
],
]
);
$this->add_control(
'pagination_align',
[
'label' => __( 'Alignment', 'around-elementor' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => __( 'Left', 'around-elementor' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => __( 'Center', 'around-elementor' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => __( 'Right', 'around-elementor' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'selectors' => [
'{{WRAPPER}} .elementor-pagination' => 'text-align: {{VALUE}};',
],
'condition' => [
'pagination_type!' => '',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_pagination_style',
[
'label' => __( 'Pagination', 'around-elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'pagination_type!' => '',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'pagination_typography',
'selector' => '{{WRAPPER}} .elementor-pagination',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_SECONDARY,
],
]
);
$this->add_control(
'pagination_color_heading',
[
'label' => __( 'Colors', 'around-elementor' ),
'type' => Controls_Manager::HEADING,
'separator' => 'before',
]
);
$this->start_controls_tabs( 'pagination_colors' );
$this->start_controls_tab(
'pagination_color_normal',
[
'label' => __( 'Normal', 'around-elementor' ),
]
);
$this->add_control(
'pagination_color',
[
'label' => __( 'Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-pagination .page-numbers:not(.dots)' => 'color: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'pagination_color_hover',
[
'label' => __( 'Hover', 'around-elementor' ),
]
);
$this->add_control(
'pagination_hover_color',
[
'label' => __( 'Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-pagination a.page-numbers:hover' => 'color: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->start_controls_tab(
'pagination_color_active',
[
'label' => __( 'Active', 'around-elementor' ),
]
);
$this->add_control(
'pagination_active_color',
[
'label' => __( 'Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-pagination .page-numbers.current' => 'color: {{VALUE}};',
],
]
);
$this->end_controls_tab();
$this->end_controls_tabs();
$this->add_responsive_control(
'pagination_spacing',
[
'label' => __( 'Space Between', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'separator' => 'before',
'default' => [
'size' => 10,
],
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'selectors' => [
'body:not(.rtl) {{WRAPPER}} .elementor-pagination .page-numbers:not(:first-child)' => 'margin-left: calc( {{SIZE}}{{UNIT}}/2 );',
'body:not(.rtl) {{WRAPPER}} .elementor-pagination .page-numbers:not(:last-child)' => 'margin-right: calc( {{SIZE}}{{UNIT}}/2 );',
'body.rtl {{WRAPPER}} .elementor-pagination .page-numbers:not(:first-child)' => 'margin-right: calc( {{SIZE}}{{UNIT}}/2 );',
'body.rtl {{WRAPPER}} .elementor-pagination .page-numbers:not(:last-child)' => 'margin-left: calc( {{SIZE}}{{UNIT}}/2 );',
],
]
);
$this->add_responsive_control(
'pagination_spacing_top',
[
'label' => __( 'Spacing', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-pagination' => 'margin-top: {{SIZE}}{{UNIT}}',
],
]
);
$this->end_controls_section();
}
//abstract public function query_posts();
public function get_current_page() {
if ( '' === $this->get_settings( 'pagination_type' ) ) {
return 1;
}
return max( 1, get_query_var( 'paged' ), get_query_var( 'page' ) );
}
private function get_wp_link_page( $i ) {
if ( ! is_singular() || is_front_page() ) {
return get_pagenum_link( $i );
}
// Based on wp-includes/post-template.php:957 `_wp_link_page`.
global $wp_rewrite;
$post = get_post();
$query_args = [];
$url = get_permalink();
if ( $i > 1 ) {
if ( '' === get_option( 'permalink_structure' ) || in_array( $post->post_status, [ 'draft', 'pending' ] ) ) {
$url = add_query_arg( 'page', $i, $url );
} elseif ( get_option( 'show_on_front' ) === 'page' && (int) get_option( 'page_on_front' ) === $post->ID ) {
$url = trailingslashit( $url ) . user_trailingslashit( "$wp_rewrite->pagination_base/" . $i, 'single_paged' );
} else {
$url = trailingslashit( $url ) . user_trailingslashit( $i, 'single_paged' );
}
}
if ( is_preview() ) {
if ( ( 'draft' !== $post->post_status ) && isset( $_GET['preview_id'], $_GET['preview_nonce'] ) ) {
$query_args['preview_id'] = wp_unslash( $_GET['preview_id'] );
$query_args['preview_nonce'] = wp_unslash( $_GET['preview_nonce'] );
}
$url = get_preview_post_link( $post, $query_args, $url );
}
return $url;
}
public function get_posts_nav_link( $page_limit = null ) {
if ( ! $page_limit ) {
$page_limit = $this->query->max_num_pages;
}
$return = [];
$paged = $this->get_current_page();
$link_template = '<a class="page-numbers %s" href="%s">%s</a>';
$disabled_template = '<span class="page-numbers %s">%s</span>';
if ( $paged > 1 ) {
$next_page = intval( $paged ) - 1;
if ( $next_page < 1 ) {
$next_page = 1;
}
$return['prev'] = sprintf( $link_template, 'prev', $this->get_wp_link_page( $next_page ), $this->get_settings( 'pagination_prev_label' ) );
} else {
$return['prev'] = sprintf( $disabled_template, 'prev', $this->get_settings( 'pagination_prev_label' ) );
}
$next_page = intval( $paged ) + 1;
if ( $next_page <= $page_limit ) {
$return['next'] = sprintf( $link_template, 'next', $this->get_wp_link_page( $next_page ), $this->get_settings( 'pagination_next_label' ) );
} else {
$return['next'] = sprintf( $disabled_template, 'next', $this->get_settings( 'pagination_next_label' ) );
}
return $return;
}
private function register_query_section_controls() {
$this->start_controls_section(
'section_layout',
[
'label' => __( 'Layout', 'around-elementor' ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_responsive_control(
'columns',
[
'label' => __( 'Columns', 'around-elementor' ),
'type' => Controls_Manager::SELECT,
'default' => '3',
'tablet_default' => '2',
'mobile_default' => '1',
'options' => [
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4',
'5' => '5',
'6' => '6',
],
'prefix_class' => 'elementor-grid%s-',
'frontend_available' => true,
'selectors' => [
'.elementor-msie {{WRAPPER}} .elementor-portfolio-item' => 'width: calc( 100% / {{SIZE}} )',
],
]
);
$this->add_control(
'posts_per_page',
[
'label' => __( 'Posts Per Page', 'around-elementor' ),
'type' => Controls_Manager::NUMBER,
'default' => 6,
]
);
$this->add_group_control(
Group_Control_Image_Size::get_type(),
[
'name' => 'thumbnail_size',
'exclude' => [ 'custom' ],
'default' => 'medium',
'prefix_class' => 'elementor-portfolio--thumbnail-size-',
]
);
$this->add_control(
'show_title',
[
'label' => __( 'Show Title', 'around-elementor' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'yes',
'label_off' => __( 'Off', 'around-elementor' ),
'label_on' => __( 'On', 'around-elementor' ),
]
);
$this->add_control(
'title_tag',
[
'label' => __( 'Title HTML Tag', 'around-elementor' ),
'type' => Controls_Manager::SELECT,
'options' => [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'div' => 'div',
'span' => 'span',
'p' => 'p',
],
'default' => 'h3',
'condition' => [
'show_title' => 'yes',
],
]
);
$this->add_control( 'filters', [
'label' => esc_html__( 'Filter', 'around-elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_on' => esc_html__( 'Enable', 'around-elementor' ),
'label_off' => esc_html__( 'Disable', 'around-elementor' ),
'default' => 'no',
] );
$this->end_controls_section();
$this->start_controls_section(
'section_query',
[
'label' => __( 'Query', 'around-elementor' ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_group_control(
Group_Control_Related::get_type(),
[
'name' => 'posts',
'presets' => [ 'full' ],
'exclude' => [
'posts_per_page', //use the one from Layout section
],
]
);
$this->end_controls_section();
/* $this->start_controls_section(
'filter_bar',
[
'label' => __( 'Filter Bar', 'around-elementor' ),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'show_filter_bar',
[
'label' => __( 'Show', 'around-elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => __( 'Off', 'around-elementor' ),
'label_on' => __( 'On', 'around-elementor' ),
]
);
$this->add_control(
'taxonomy',
[
'label' => __( 'Taxonomy', 'around-elementor' ),
'type' => Controls_Manager::SELECT2,
'label_block' => true,
'default' => [],
'options' => $this->get_taxonomies(),
'condition' => [
'show_filter_bar' => 'yes',
'posts_post_type!' => 'by_id',
],
]
);
$this->end_controls_section();*/
$this->start_controls_section(
'section_design_layout',
[
'label' => __( 'Items', 'around-elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
/*
* The `item_gap` control is replaced by `column_gap` and `row_gap` controls since v 2.1.6
* It is left (hidden) in the widget, to provide compatibility with older installs
*/
$this->add_control(
'item_gap',
[
'label' => __( 'Item Gap', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'selectors' => [
'{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}; --grid-column-gap: {{SIZE}}{{UNIT}};',
],
'frontend_available' => true,
'classes' => 'elementor-hidden',
]
);
$this->add_control(
'column_gap',
[
'label' => __( 'Columns Gap', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}}' => ' --grid-column-gap: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_control(
'row_gap',
[
'label' => __( 'Rows Gap', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'frontend_available' => true,
'selectors' => [
'{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}',
],
]
);
$this->add_control(
'border_radius',
[
'label' => __( 'Border Radius', 'around-elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', '%' ],
'selectors' => [
'{{WRAPPER}} .elementor-portfolio-item__img, {{WRAPPER}} .elementor-portfolio-item__overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_design_overlay',
[
'label' => __( 'Item Overlay', 'around-elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'color_background',
[
'label' => __( 'Background Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_ACCENT,
],
'selectors' => [
'{{WRAPPER}} a .elementor-portfolio-item__overlay' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'color_title',
[
'label' => __( 'Color', 'around-elementor' ),
'separator' => 'before',
'type' => Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} a .elementor-portfolio-item__title' => 'color: {{VALUE}};',
],
'condition' => [
'show_title' => 'yes',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography_title',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .elementor-portfolio-item__title',
'condition' => [
'show_title' => 'yes',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_design_filter',
[
'label' => __( 'Filter Bar', 'around-elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
'condition' => [
'show_filter_bar' => 'yes',
],
]
);
$this->add_control(
'color_filter',
[
'label' => __( 'Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_TEXT,
],
'selectors' => [
'{{WRAPPER}} .elementor-portfolio__filter' => 'color: {{VALUE}}',
],
]
);
$this->add_control(
'color_filter_active',
[
'label' => __( 'Active Color', 'around-elementor' ),
'type' => Controls_Manager::COLOR,
'global' => [
'default' => Global_Colors::COLOR_PRIMARY,
],
'selectors' => [
'{{WRAPPER}} .elementor-portfolio__filter.elementor-active' => 'color: {{VALUE}};',
],
]
);
$this->add_group_control(
Group_Control_Typography::get_type(),
[
'name' => 'typography_filter',
'global' => [
'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
],
'selector' => '{{WRAPPER}} .elementor-portfolio__filter',
]
);
$this->add_control(
'filter_item_spacing',
[
'label' => __( 'Space Between', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 10,
],
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-portfolio__filter:not(:last-child)' => 'margin-right: calc({{SIZE}}{{UNIT}}/2)',
'{{WRAPPER}} .elementor-portfolio__filter:not(:first-child)' => 'margin-left: calc({{SIZE}}{{UNIT}}/2)',
],
]
);
$this->add_control(
'filter_spacing',
[
'label' => __( 'Spacing', 'around-elementor' ),
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 10,
],
'range' => [
'px' => [
'min' => 0,
'max' => 100,
],
],
'selectors' => [
'{{WRAPPER}} .elementor-portfolio__filters' => 'margin-bottom: {{SIZE}}{{UNIT}}',
],
]
);
$this->end_controls_section();
}
protected function get_taxonomies() {
$taxonomies = get_taxonomies( [ 'show_in_nav_menus' => true ], 'objects' );
$options = [ '' => '' ];
foreach ( $taxonomies as $taxonomy ) {
$options[ $taxonomy->name ] = $taxonomy->label;
}
return $options;
}
protected function get_posts_tags() {
$taxonomy = $this->get_settings( 'taxonomy' );
foreach ( $this->_query->posts as $post ) {
if ( ! $taxonomy ) {
$post->tags = [];
continue;
}
$tags = wp_get_post_terms( $post->ID, $taxonomy );
$tags_slugs = [];
foreach ( $tags as $tag ) {
$tags_slugs[ $tag->term_id ] = $tag;
}
$post->tags = $tags_slugs;
}
}
public function query_posts() {
$query_args = [
'posts_per_page' => $this->get_settings( 'posts_per_page' ),
'paged' => $this->get_current_page(),
];
/** @var Module_Query $elementor_query */
$elementor_query = Module_Query::instance();
$this->_query = $elementor_query->get_query( $this, 'posts', $query_args, [] );
}
public function render() {
$this->query_posts();
$wp_query = $this->get_query();
if ( ! $wp_query->found_posts ) {
return;
}
$this->get_posts_tags();
$this->render_loop_header();
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
$this->render_post();
}
$this->render_loop_footer();
wp_reset_postdata();
}
protected function render_thumbnail() {
$settings = $this->get_settings();
$settings['thumbnail_size'] = [
'id' => get_post_thumbnail_id(),
];
$thumbnail_html = Group_Control_Image_Size::get_attachment_image_html( $settings, 'thumbnail_size' );
?>
<div class="elementor-portfolio-item__img elementor-post__thumbnail">
<?php echo $thumbnail_html; ?>
</div>
<?php
}
protected function render_filter_menu() {
$taxonomy = $this->get_settings( 'taxonomy' );
if ( ! $taxonomy ) {
return;
}
$terms = [];
foreach ( $this->_query->posts as $post ) {
$terms += $post->tags;
}
if ( empty( $terms ) ) {
return;
}
usort( $terms, function( $a, $b ) {
return strcmp( $a->name, $b->name );
} );
?>
<ul class="elementor-portfolio__filters">
<li class="elementor-portfolio__filter elementor-active" data-filter="__all"><?php echo __( 'All', 'around-elementor' ); ?></li>
<?php foreach ( $terms as $term ) { ?>
<li class="elementor-portfolio__filter" data-filter="<?php echo esc_attr( $term->term_id ); ?>"><?php echo $term->name; ?></li>
<?php } ?>
</ul>
<?php
}
protected function render_title() {
if ( ! $this->get_settings( 'show_title' ) ) {
return;
}
$tag = $this->get_settings( 'title_tag' );
?>
<<?php echo $tag; ?> class="elementor-portfolio-item__title">
<?php the_title(); ?>
</<?php echo $tag; ?>>
<?php
}
protected function render_categories_names() {
global $post;
if ( ! $post->tags ) {
return;
}
$separator = '<span class="elementor-portfolio-item__tags__separator"></span>';
$tags_array = [];
foreach ( $post->tags as $tag ) {
$tags_array[] = '<span class="elementor-portfolio-item__tags__tag">' . $tag->name . '</span>';
}
?>
<div class="elementor-portfolio-item__tags">
<?php echo implode( $separator, $tags_array ); ?>
</div>
<?php
}
protected function render_post_header() {
global $post;
$tags_classes = array_map( function( $tag ) {
return 'elementor-filter-' . $tag->term_id;
}, $post->tags );
$classes = [
'elementor-portfolio-item',
'elementor-post',
implode( ' ', $tags_classes ),
];
?>
<article <?php post_class( $classes ); ?>>
<a class="elementor-post__thumbnail__link" href="<?php echo get_permalink(); ?>">
<?php
}
protected function render_post_footer() {
?>
</a>
</article>
<?php
}
protected function render_overlay_header() {
?>
<div class="elementor-portfolio-item__overlay">
<?php
}
protected function render_overlay_footer() {
?>
</div>
<?php
}
protected function render_loop_header() {
if ( $this->get_settings( 'show_filter_bar' ) ) {
$this->render_filter_menu();
}
?>
<div class="elementor-portfolio elementor-grid elementor-posts-container">
<?php
}
protected function render_loop_footer() {
?>
</div>
<?php
}
protected function render_post() {
$this->render_post_header();
$this->render_thumbnail();
$this->render_overlay_header();
$this->render_title();
// $this->render_categories_names();
$this->render_overlay_footer();
$this->render_post_footer();
}
public function render_plain_content() {}
}