Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/posts.tar
Назад
data/controller.php 0000644 00000002700 14720516621 0010354 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Data; use Elementor\Utils; use ElementorPro\Data\Base\Controller as Controller_Base; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Controller extends Controller_Base { public function get_name() { return 'posts-widget'; } public function register_endpoints() { // There is only get items end point } public function get_items( $request ) { $document = Plugin::elementor()->documents->get( $request->get_param( 'post_id' ) ); if ( ! $document ) { return new \WP_Error( 'document_not_exist', __( 'Document doesn\'t exist', 'elementor-pro' ), [ 'status' => 404 ] ); } $element_data = $document->get_elements_data(); $posts_widget = Utils::find_element_recursive( $element_data, $request->get_param( 'element_id' ) ); if ( empty( $posts_widget ) ) { return new \WP_Error( 'Element_not_exist', __( 'Posts widget doesn\'t exist', 'elementor-pro' ), [ 'status' => 404 ] ); } set_query_var( 'paged', $request->get_param( 'page' ) ); /** @var \ElementorPro\Modules\Posts\Widgets\Posts $element_instance */ $element_instance = Plugin::elementor()->elements_manager->create_element_instance( $posts_widget ); ob_start(); $element_instance->render_content(); $html = ob_get_clean(); return [ 'content' => $html, ]; } public function get_permission_callback( $request ) { return true; } } traits/query-note-trait.php 0000644 00000002406 14720516621 0012022 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Traits; use ElementorPro\Modules\Posts\Widgets\Posts_Base; use ElementorPro\Plugin; use ElementorPro\Core\Utils; use Elementor\Controls_Manager; use Elementor\Core\Base\Document; trait Query_Note_Trait { public function is_editing_archive_template() { if ( Plugin::elementor()->documents->get_current() ) { $id = Utils::get_current_post_id(); } else { $id = get_the_ID(); } return 'archive' === get_post_meta( $id, Document::TYPE_META_KEY, true ); } public function inject_archive_query_note( $placement_id, $condition_id, $widget ) { $archive_setting_url = admin_url( 'options-reading.php' ); $widget->start_injection( [ 'of' => $placement_id, 'at' => 'before', ] ); $widget->add_control( 'archive_query_note', [ 'type' => Controls_Manager::RAW_HTML, 'raw' => sprintf( esc_html__( 'The amount of items displayed in your Archive is set in your WordPress settings. %s', 'elementor-pro' ), '<a target="_blank" href="' . esc_url( $archive_setting_url ) . '">' . esc_html__( 'Take me there', 'elementor-pro' ) . '</a>' ), 'content_classes' => 'elementor-descriptor', 'condition' => [ $condition_id => 'current_query', ], ] ); $widget->end_injection(); } } traits/button-widget-trait.php 0000644 00000037423 14720516621 0012515 0 ustar 00 <?php // @TODO: Use the button trait from core when it will be added. namespace ElementorPro\Modules\Posts\Traits; use Elementor\Controls_Manager; use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Background; use Elementor\Group_Control_Border; use Elementor\Group_Control_Box_Shadow; use Elementor\Group_Control_Text_Shadow; use Elementor\Group_Control_Typography; use Elementor\Icons_Manager; use Elementor\Utils; use Elementor\Widget_Base; trait Button_Widget_Trait { /** * Get button sizes. * * Retrieve an array of button sizes for the button widget. * * @since 3.4.0 * @access public * @static * * @return array An array containing button sizes. */ public static function get_button_sizes() { return [ 'xs' => esc_html__( 'Extra Small', 'elementor-pro' ), 'sm' => esc_html__( 'Small', 'elementor-pro' ), 'md' => esc_html__( 'Medium', 'elementor-pro' ), 'lg' => esc_html__( 'Large', 'elementor-pro' ), 'xl' => esc_html__( 'Extra Large', 'elementor-pro' ), ]; } protected function register_button_content_controls( $args = [] ) { $default_args = [ 'section_condition' => [], 'button_text' => esc_html__( 'Click here', 'elementor-pro' ), 'control_label_name' => esc_html__( 'Text', 'elementor-pro' ), 'exclude_inline_options' => [], ]; $args = wp_parse_args( $args, $default_args ); $this->add_control( 'button_type', [ 'label' => esc_html__( 'Type', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'default' => '', 'options' => [ '' => esc_html__( 'Default', 'elementor-pro' ), 'info' => esc_html__( 'Info', 'elementor-pro' ), 'success' => esc_html__( 'Success', 'elementor-pro' ), 'warning' => esc_html__( 'Warning', 'elementor-pro' ), 'danger' => esc_html__( 'Danger', 'elementor-pro' ), ], 'prefix_class' => 'elementor-button-', 'condition' => $args['section_condition'], ] ); $this->add_control( 'text', [ 'label' => $args['control_label_name'], 'type' => Controls_Manager::TEXT, 'dynamic' => [ 'active' => true, ], 'default' => $args['button_text'], 'placeholder' => $args['button_text'], 'condition' => $args['section_condition'], ] ); $this->add_control( 'link', [ 'label' => esc_html__( 'Link', 'elementor-pro' ), 'type' => Controls_Manager::URL, 'dynamic' => [ 'active' => true, ], 'default' => [ 'url' => '#', ], 'condition' => $args['section_condition'], ] ); $this->add_control( 'size', [ 'label' => esc_html__( 'Size', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'default' => 'sm', 'options' => self::get_button_sizes(), 'style_transfer' => true, 'condition' => array_merge( $args['section_condition'], [ 'size[value]!' => 'sm' ] ), // a workaround to hide the control, unless it's in use (not default). ] ); $this->add_control( 'selected_icon', [ 'label' => esc_html__( 'Icon', 'elementor-pro' ), 'type' => Controls_Manager::ICONS, 'fa4compatibility' => 'icon', 'skin' => 'inline', 'label_block' => false, 'condition' => $args['section_condition'], 'exclude_inline_options' => $args['exclude_inline_options'], ] ); $start = is_rtl() ? 'right' : 'left'; $end = is_rtl() ? 'left' : 'right'; $this->add_control( 'icon_align', [ 'label' => esc_html__( 'Icon Position', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'default' => is_rtl() ? 'row-reverse' : 'row', 'options' => [ 'row' => [ 'title' => esc_html__( 'Start', 'elementor-pro' ), 'icon' => "eicon-h-align-{$start}", ], 'row-reverse' => [ 'title' => esc_html__( 'End', 'elementor-pro' ), 'icon' => "eicon-h-align-{$end}", ], ], 'selectors_dictionary' => [ 'left' => is_rtl() ? 'row-reverse' : 'row', 'right' => is_rtl() ? 'row' : 'row-reverse', ], 'selectors' => [ '{{WRAPPER}} .elementor-button-content-wrapper' => 'flex-direction: {{VALUE}};', ], 'condition' => array_merge( $args['section_condition'], [ 'text!' => '', 'selected_icon[value]!' => '', ] ), ] ); $this->add_control( 'icon_indent', [ 'label' => esc_html__( 'Icon Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-button .elementor-button-content-wrapper' => 'gap: {{SIZE}}{{UNIT}};', ], 'condition' => array_merge( $args['section_condition'], [ 'text!' => '', 'selected_icon[value]!' => '', ] ), ] ); $this->add_control( 'button_css_id', [ 'label' => esc_html__( 'Button ID', 'elementor-pro' ), 'type' => Controls_Manager::TEXT, 'dynamic' => [ 'active' => true, ], 'ai' => [ 'active' => false, ], 'default' => '', 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor-pro' ), 'description' => sprintf( esc_html__( 'Please make sure the ID is unique and not used elsewhere on the page. This field allows %1$sA-z 0-9%2$s & underscore chars without spaces.', 'elementor-pro' ), '<code>', '</code>' ), 'separator' => 'before', 'condition' => $args['section_condition'], ] ); } protected function register_button_style_controls( $args = [] ) { $default_args = [ 'section_condition' => [], 'prefix_class' => 'elementor%s-align-', 'alignment_default' => '', 'content_alignment_default' => '', ]; $args = wp_parse_args( $args, $default_args ); $this->add_responsive_control( 'align', [ 'label' => esc_html__( 'Position', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-h-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-h-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-h-align-right', ], 'justify' => [ 'title' => esc_html__( 'Stretch', 'elementor-pro' ), 'icon' => 'eicon-h-align-stretch', ], ], 'prefix_class' => $args['prefix_class'], 'default' => $args['alignment_default'], 'condition' => $args['section_condition'], ] ); $start = is_rtl() ? 'right' : 'left'; $end = is_rtl() ? 'left' : 'right'; $this->add_responsive_control( 'content_align', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'start' => [ 'title' => esc_html__( 'Start', 'elementor-pro' ), 'icon' => "eicon-text-align-{$start}", ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'end' => [ 'title' => esc_html__( 'End', 'elementor-pro' ), 'icon' => "eicon-text-align-{$end}", ], 'space-between' => [ 'title' => esc_html__( 'Space between', 'elementor-pro' ), 'icon' => 'eicon-text-align-justify', ], ], 'default' => $args['content_alignment_default'], 'selectors' => [ '{{WRAPPER}} .elementor-button .elementor-button-content-wrapper' => 'justify-content: {{VALUE}};', ], 'condition' => array_merge( $args['section_condition'], [ 'align' => 'justify' ] ), ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_ACCENT, ], 'selector' => '{{WRAPPER}} .elementor-button', 'condition' => $args['section_condition'], ] ); $this->add_group_control( Group_Control_Text_Shadow::get_type(), [ 'name' => 'text_shadow', 'selector' => '{{WRAPPER}} .elementor-button', 'condition' => $args['section_condition'], ] ); $this->start_controls_tabs( 'tabs_button_style', [ 'condition' => $args['section_condition'], ] ); $this->start_controls_tab( 'tab_button_normal', [ 'label' => esc_html__( 'Normal', 'elementor-pro' ), 'condition' => $args['section_condition'], ] ); $this->add_control( 'button_text_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}} .elementor-button' => 'fill: {{VALUE}}; color: {{VALUE}};', ], 'condition' => $args['section_condition'], ] ); $this->add_group_control( Group_Control_Background::get_type(), [ 'name' => 'background', 'types' => [ 'classic', 'gradient' ], 'exclude' => [ 'image' ], 'selector' => '{{WRAPPER}} .elementor-button', 'fields_options' => [ 'background' => [ 'default' => 'classic', ], 'color' => [ 'global' => [ 'default' => Global_Colors::COLOR_ACCENT, ], ], ], 'condition' => $args['section_condition'], ] ); $this->end_controls_tab(); $this->start_controls_tab( 'tab_button_hover', [ 'label' => esc_html__( 'Hover', 'elementor-pro' ), 'condition' => $args['section_condition'], ] ); $this->add_control( 'hover_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus' => 'color: {{VALUE}};', '{{WRAPPER}} .elementor-button:hover svg, {{WRAPPER}} .elementor-button:focus svg' => 'fill: {{VALUE}};', ], 'condition' => $args['section_condition'], ] ); $this->add_group_control( Group_Control_Background::get_type(), [ 'name' => 'button_background_hover', 'types' => [ 'classic', 'gradient' ], 'exclude' => [ 'image' ], 'selector' => '{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus', 'fields_options' => [ 'background' => [ 'default' => 'classic', ], ], 'condition' => $args['section_condition'], ] ); $this->add_control( 'button_hover_border_color', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'condition' => [ 'border_border!' => '', ], 'selectors' => [ '{{WRAPPER}} .elementor-button:hover, {{WRAPPER}} .elementor-button:focus' => 'border-color: {{VALUE}};', ], 'condition' => $args['section_condition'], ] ); $this->add_control( 'button_hover_transition_duration', [ 'label' => esc_html__( 'Transition Duration', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 's', 'ms', 'custom' ], 'default' => [ 'unit' => 's', ], 'selectors' => [ '{{WRAPPER}} .elementor-button' => 'transition-duration: {{SIZE}}{{UNIT}};', ], ] ); $this->add_control( 'hover_animation', [ 'label' => esc_html__( 'Hover Animation', 'elementor-pro' ), 'type' => Controls_Manager::HOVER_ANIMATION, 'condition' => $args['section_condition'], ] ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_group_control( Group_Control_Border::get_type(), [ 'name' => 'border', 'selector' => '{{WRAPPER}} .elementor-button', 'separator' => 'before', 'condition' => $args['section_condition'], ] ); $this->add_control( 'border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], 'condition' => $args['section_condition'], ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'button_box_shadow', 'selector' => '{{WRAPPER}} .elementor-button', 'condition' => $args['section_condition'], ] ); $this->add_responsive_control( 'text_padding', [ 'label' => esc_html__( 'Padding', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], 'separator' => 'before', 'condition' => $args['section_condition'], ] ); } /** * Render button widget output on the frontend. * * Written in PHP and used to generate the final HTML. * * @param \Elementor\Widget_Base|null $instance * * @since 3.4.0 * @access protected */ protected function render_button( Widget_Base $instance = null ) { if ( empty( $instance ) ) { $instance = $this; } $settings = $instance->get_settings(); if ( empty( $settings['text'] ) && empty( $settings['selected_icon']['value'] ) ) { return; } $instance->add_render_attribute( 'wrapper', 'class', 'elementor-button-wrapper' ); if ( ! empty( $settings['link']['url'] ) ) { $instance->add_link_attributes( 'button', $settings['link'] ); $instance->add_render_attribute( 'button', 'class', 'elementor-button-link' ); } $instance->add_render_attribute( 'button', 'class', 'elementor-button' ); $instance->add_render_attribute( 'button', 'role', 'button' ); if ( ! empty( $settings['button_css_id'] ) ) { $instance->add_render_attribute( 'button', 'id', $settings['button_css_id'] ); } if ( ! empty( $settings['size'] ) ) { $instance->add_render_attribute( 'button', 'class', 'elementor-size-' . $settings['size'] ); } if ( $settings['hover_animation'] ) { $instance->add_render_attribute( 'button', 'class', 'elementor-animation-' . $settings['hover_animation'] ); } ?> <div <?php $instance->print_render_attribute_string( 'wrapper' ); ?>> <a <?php $instance->print_render_attribute_string( 'button' ); ?>> <?php $this->render_text( $instance ); ?> </a> </div> <?php } /** * Render button text. * * Render button widget text. * * @param \Elementor\Widget_Base $instance * * @since 3.4.0 * @access protected */ protected function render_text( Widget_Base $instance ) { $settings = $instance->get_settings(); $migrated = isset( $settings['__fa4_migrated']['selected_icon'] ); $is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed(); $instance->add_render_attribute( [ 'content-wrapper' => [ 'class' => 'elementor-button-content-wrapper', ], 'icon' => [ 'class' => 'elementor-button-icon', ], 'text' => [ 'class' => 'elementor-button-text', ], ] ); // TODO: replace the protected with public //$instance->add_inline_editing_attributes( 'text', 'none' ); ?> <span <?php $instance->print_render_attribute_string( 'content-wrapper' ); ?>> <?php if ( ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon']['value'] ) ) : ?> <span <?php $instance->print_render_attribute_string( 'icon' ); ?>> <?php if ( $is_new || $migrated ) : Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] ); else : ?> <i class="<?php echo esc_attr( $settings['icon'] ); ?>" aria-hidden="true"></i> <?php endif; ?> </span> <?php endif; ?> <?php if ( ! empty( $settings['text'] ) ) : ?> <span <?php $instance->print_render_attribute_string( 'text' ); ?>><?php $instance->print_unescaped_setting( 'text' ); ?></span> <?php endif; ?> </span> <?php } public function on_import( $element ) { return Icons_Manager::on_import_migration( $element, 'icon', 'selected_icon' ); } } traits/pagination-trait.php 0000644 00000010446 14720516621 0012046 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Traits; use ElementorPro\Modules\GlobalWidget\Widgets\Global_Widget; use ElementorPro\Modules\Posts\Widgets\Posts_Base; use ElementorPro\Plugin; trait Pagination_Trait { /** * Checks a set of elements if there is a posts/archive widget that may be paginated to a specific page number. * * @param array $elements * @param $current_page * * @return bool */ public function is_valid_pagination( array $elements, $current_page ) { $is_valid = false; $posts_widgets = $this->get_widgets_that_support_pagination(); Plugin::elementor()->db->iterate_data( $elements, $this->check_pagination_handler( $posts_widgets, $current_page, $is_valid ) ); return $is_valid; } /** * Get all widgets that may add pagination. * * @return array */ public function get_widgets_that_support_pagination() { $widgets = Plugin::elementor()->widgets_manager->get_widget_types(); $posts_widgets = []; foreach ( $widgets as $widget ) { if ( $widget instanceof Posts_Base || $widget instanceof Global_Widget ) { $posts_widgets[] = $widget->get_name(); } } return $posts_widgets; } /** * @return void */ public function check_pagination_handler( array $posts_widgets, $current_page, &$is_valid ) { return function ( $element ) use ( &$is_valid, $posts_widgets, $current_page ) { if ( ! $this->is_valid_post_widget( $element, $posts_widgets ) ) { return; } $is_valid = $this->should_allow_pagination( $element, $current_page ); }; } /** * @return bool */ private function is_valid_post_widget( $element, $posts_widgets ) { return isset( $element['widgetType'] ) && in_array( $element['widgetType'], $posts_widgets, true ); } /** * @return bool */ private function widget_has_pagination( $element ) { return ! empty( $element['settings']['pagination_type'] ); } /** * @return bool */ private function should_allow_pagination( $element, $current_page ) { if ( ! $this->widget_has_pagination( $element ) ) { return false; } $using_ajax_pagination = in_array($element['settings']['pagination_type'], [ Posts_Base::LOAD_MORE_ON_CLICK, Posts_Base::LOAD_MORE_INFINITE_SCROLL, ], true); if ( empty( $element['settings']['pagination_page_limit'] ) || $using_ajax_pagination ) { return true; } return (int) $current_page <= (int) $element['settings']['pagination_page_limit']; } public function get_base_url() { if ( is_page() || is_single() ) { // Check if it's a normal page. return get_permalink(); } elseif ( is_year() ) { return get_year_link( get_query_var( 'year' ) ); } elseif ( is_month() ) { return get_month_link( get_query_var( 'year' ), get_query_var( 'monthnum' ) ); } elseif ( is_day() ) { return get_day_link( get_query_var( 'year' ), get_query_var( 'monthnum' ), get_query_var( 'day' ) ); } elseif ( is_category() || is_tag() || is_tax() ) { $queried_object = get_queried_object(); return get_term_link( $queried_object->term_id, $queried_object->taxonomy ); } elseif ( is_author() ) { return get_author_posts_url( get_the_author_meta( 'ID' ) ); } elseif ( is_search() ) { return get_search_link(); } elseif ( is_archive() ) { // Check if it's an archive page. return get_post_type_archive_link( get_post_type() ); } elseif ( is_singular() && 'post' !== get_post_type() && 'page' !== get_post_type() ) { // Check if it's a single post/page of a custom post type. $post_type = get_post_type_object( get_post_type() ); if ( $post_type->has_archive ) { return get_post_type_archive_link( get_post_type() ); } else { return get_permalink(); } } elseif ( $this->is_posts_page() ) { return get_permalink( get_option( 'page_for_posts' ) ); } // Fallback to home URL. return home_url( '/' ); } /** * Determines whether the query is for an existing blog posts index page * * @param bool $custom_page_option * @return bool */ private function is_posts_page( $custom_page_option = true ) { if ( $custom_page_option ) { return ! is_front_page() && is_home(); } $posts_page_id = (int) get_option( 'page_for_posts' ); $base_url = get_query_var( 'pagination_base_url' ); if ( ! empty( $base_url ) ) { $post_id = url_to_postid( $base_url ); return $posts_page_id === $post_id; } return false; } } module.php 0000644 00000004256 14720516621 0006555 0 ustar 00 <?php namespace ElementorPro\Modules\Posts; use Elementor\Utils; use ElementorPro\Base\Module_Base; use ElementorPro\Modules\Posts\Data\Controller; use ElementorPro\Modules\Posts\Widgets\Posts_Base; use ElementorPro\Plugin; use ElementorPro\Modules\Posts\Traits\Pagination_Trait; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Module extends Module_Base { use Pagination_Trait; public function get_name() { return 'posts'; } public function get_widgets() { return [ 'Posts', 'Portfolio', ]; } /** * Get the base URL for assets. * * @return string */ public function get_assets_base_url(): string { return ELEMENTOR_PRO_URL; } /** * Register styles. * * At build time, Elementor compiles `/modules/posts/assets/scss/frontend.scss` * to `/assets/css/widget-posts.min.css`. * * @return void */ public function register_styles() { wp_register_style( 'widget-posts', $this->get_css_assets_url( 'widget-posts', null, true, true ), [ 'elementor-frontend' ], ELEMENTOR_PRO_VERSION ); } /** * Fix WP 5.5 pagination issue. * * Return true to mark that it's handled and avoid WP to set it as 404. * * @see https://github.com/elementor/elementor/issues/12126 * @see https://core.trac.wordpress.org/ticket/50976 * * Based on the logic at \WP::handle_404. * * @param $handled - Default false. * @param $wp_query * * @return bool */ public function allow_posts_widget_pagination( $handled, $wp_query ) { // Check it's not already handled and it's a single paged query. if ( $handled || empty( $wp_query->query_vars['page'] ) || ! is_singular() || empty( $wp_query->post ) ) { return $handled; } $document = Plugin::elementor()->documents->get( $wp_query->post->ID ); return $this->is_valid_pagination( $document->get_elements_data(), $wp_query->query_vars['page'] ); } public function __construct() { parent::__construct(); Plugin::elementor()->data_manager->register_controller( Controller::class ); add_filter( 'pre_handle_404', [ $this, 'allow_posts_widget_pagination' ], 10, 2 ); add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_styles' ] ); } } widgets/portfolio.php 0000644 00000040401 14720516621 0010743 0 ustar 00 <?php namespace ElementorPro\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 Elementor\Utils; use ElementorPro\Base\Base_Widget; use ElementorPro\Modules\QueryControl\Module as Module_Query; use ElementorPro\Modules\QueryControl\Controls\Group_Control_Related; use Elementor\Controls_Manager; 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 'portfolio'; } public function get_title() { return esc_html__( 'Portfolio', 'elementor-pro' ); } 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' ]; } /** * Get style dependencies. * * Retrieve the list of style dependencies the widget requires. * * @since 3.24.0 * @access public * * @return array Widget style dependencies. */ public function get_style_depends(): array { return [ 'widget-posts' ]; } public function on_import( $element ) { if ( isset( $element['settings']['posts_post_type'] ) && ! get_post_type_object( $element['settings']['posts_post_type'] ) ) { $element['settings']['posts_post_type'] = 'post'; } return $element; } public function get_query() { return $this->_query; } protected function register_controls() { $this->register_query_section_controls(); } private function register_query_section_controls() { $this->start_controls_section( 'section_layout', [ 'label' => esc_html__( 'Layout', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_CONTENT, ] ); $this->add_responsive_control( 'columns', [ 'label' => esc_html__( 'Columns', 'elementor-pro' ), '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' => esc_html__( 'Posts Per Page', 'elementor-pro' ), '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( 'masonry', [ 'label' => esc_html__( 'Masonry', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_off' => esc_html__( 'Off', 'elementor-pro' ), 'label_on' => esc_html__( 'On', 'elementor-pro' ), 'condition' => [ 'columns!' => '1', ], 'render_type' => 'ui', 'frontend_available' => true, ] ); $this->add_control( 'item_ratio', [ 'label' => esc_html__( 'Item Ratio', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'size' => 0.66, ], 'range' => [ 'px' => [ 'min' => 0.1, 'max' => 2, 'step' => 0.01, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__thumbnail__link' => 'padding-bottom: calc( {{SIZE}} * 100% )', '{{WRAPPER}}:after' => 'content: "{{SIZE}}"; position: absolute; color: transparent;', ], 'condition' => [ 'masonry' => '', ], 'frontend_available' => true, ] ); $this->add_control( 'show_title', [ 'label' => esc_html__( 'Show Title', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'label_off' => esc_html__( 'Off', 'elementor-pro' ), 'label_on' => esc_html__( 'On', 'elementor-pro' ), ] ); $this->add_control( 'title_tag', [ 'label' => esc_html__( 'Title HTML Tag', 'elementor-pro' ), '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->end_controls_section(); $this->start_controls_section( 'section_query', [ 'label' => esc_html__( 'Query', 'elementor-pro' ), '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' => esc_html__( 'Filter Bar', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_CONTENT, ] ); $this->add_control( 'show_filter_bar', [ 'label' => esc_html__( 'Show', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_off' => esc_html__( 'Off', 'elementor-pro' ), 'label_on' => esc_html__( 'On', 'elementor-pro' ), ] ); $this->add_control( 'taxonomy', [ 'label' => esc_html__( 'Taxonomy', 'elementor-pro' ), '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' => esc_html__( 'Items', 'elementor-pro' ), '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' => esc_html__( 'Item Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}; --grid-column-gap: {{SIZE}}{{UNIT}};', ], 'frontend_available' => true, 'classes' => 'elementor-hidden', ] ); $this->add_control( 'column_gap', [ 'label' => esc_html__( 'Columns Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}}' => ' --grid-column-gap: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'row_gap', [ 'label' => esc_html__( 'Rows Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'frontend_available' => true, 'selectors' => [ '{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], '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' => esc_html__( 'Item Overlay', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'color_background', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), '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' => esc_html__( 'Color', 'elementor-pro' ), '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' => esc_html__( 'Filter Bar', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ 'show_filter_bar' => 'yes', ], ] ); $this->add_control( 'color_filter', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_TEXT, ], 'selectors' => [ '{{WRAPPER}} .elementor-portfolio__filter' => 'color: {{VALUE}}', ], ] ); $this->add_control( 'color_filter_active', [ 'label' => esc_html__( 'Active Color', 'elementor-pro' ), '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' => esc_html__( 'Space Between', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 10, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], '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' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 10, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], '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' ), ]; /** @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(), ]; ?> <div class="elementor-portfolio-item__img elementor-post__thumbnail"> <?php Group_Control_Image_Size::print_attachment_image_html( $settings, 'thumbnail_size' ); ?> </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" tabindex="0" data-filter="__all"><?php echo esc_html__( 'All', 'elementor-pro' ); ?></li> <?php foreach ( $terms as $term ) { ?> <li class="elementor-portfolio__filter" tabindex="0" data-filter="<?php echo esc_attr( $term->term_id ); ?>"><?php echo esc_html( $term->name ); ?></li> <?php } ?> </ul> <?php } protected function render_title() { if ( ! $this->get_settings( 'show_title' ) ) { return; } $tag = $this->get_settings( 'title_tag' ); ?> <<?php Utils::print_validated_html_tag( $tag ); ?> class="elementor-portfolio-item__title"> <?php the_title(); ?> </<?php Utils::print_validated_html_tag( $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">' . esc_html( $tag->name ) . '</span>'; } ?> <div class="elementor-portfolio-item__tags"> <?php // PHPCS - `$separator`, `$separator` is safe. ?> <?php echo implode( $separator, $tags_array ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </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 ), ]; // PHPCS - `get_permalink` is safe. ?> <article <?php post_class( $classes ); ?>> <a class="elementor-post__thumbnail__link" href="<?php echo get_permalink(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>"> <?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() {} public function get_group_name() { return 'posts'; } } widgets/posts-base.php 0000644 00000060403 14720516621 0011012 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Widgets; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Typography; use ElementorPro\Base\Base_Widget; use Elementor\Controls_Manager; use ElementorPro\Core\Utils; use ElementorPro\Modules\Posts\Traits\Button_Widget_Trait; use ElementorPro\Modules\Posts\Traits\Pagination_Trait; use ElementorPro\Modules\LoopBuilder\Module as LoopBuilderModule; use ElementorPro\Modules\Woocommerce\Module as WoocommerceModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Class Posts */ abstract class Posts_Base extends Base_Widget { use Button_Widget_Trait; use Pagination_Trait; const LOAD_MORE_ON_CLICK = 'load_more_on_click'; const LOAD_MORE_INFINITE_SCROLL = 'load_more_infinite_scroll'; /** * @var \WP_Query */ protected $query = null; protected $_has_template_content = false; public function get_icon() { return 'eicon-post-list'; } public function get_script_depends() { return [ 'imagesloaded' ]; } public function get_query() { return $this->query; } public function render() {} public function register_load_more_button_style_controls() { $this->add_control( 'heading_load_more_style_button', [ 'label' => esc_html__( 'Button', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'condition' => [ 'pagination_type' => 'load_more_on_click', ], ] ); $this->register_button_style_controls( [ 'section_condition' => [ 'pagination_type' => 'load_more_on_click', ], 'prefix_class' => 'load-more-align-', 'alignment_default' => 'center', ] ); } public function register_load_more_message_style_controls() { $this->add_control( 'heading_load_more_on_click_no_posts_message', [ 'label' => esc_html__( 'No More Posts Message', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'pagination_type' => 'load_more_on_click', ], 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'heading_load_more_on_click_infinity_scroll_no_posts_message', [ 'label' => esc_html__( 'No More Posts Message', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'condition' => [ 'pagination_type' => 'load_more_infinite_scroll', ], 'dynamic' => [ 'active' => true, ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'load_more_no_posts_message', 'selector' => '{{WRAPPER}} .e-load-more-message', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY, ], ] ); $this->add_control( 'load_more_no_posts_message_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}}' => '--load-more-message-color: {{VALUE}};', ], ] ); $this->add_control( 'load_more_spinner_color', [ 'label' => esc_html__( 'Spinner Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'default' => '', 'selectors' => [ '{{WRAPPER}}' => '--load-more-spinner-color: {{VALUE}};', ], 'separator' => 'before', 'condition' => [ 'load_more_spinner[value]!' => '', ], ] ); $this->add_responsive_control( 'load_more_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}}' => '--load-more—spacing: {{SIZE}}{{UNIT}};', ], 'separator' => 'before', ] ); } public function register_pagination_section_controls() { $this->start_controls_section( 'section_pagination', [ 'label' => esc_html__( 'Pagination', 'elementor-pro' ), 'condition' => [ '_skin!' => [ LoopBuilderModule::LOOP_POST_TAXONOMY_SKIN_ID, WoocommerceModule::LOOP_PRODUCT_TAXONOMY_SKIN_ID, ], ], ] ); $this->add_control( 'pagination_type', [ 'label' => esc_html__( 'Pagination', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'default' => '', 'options' => $this->get_pagination_type_options(), 'frontend_available' => true, ] ); $this->add_control( 'pagination_page_limit', [ 'label' => esc_html__( 'Page Limit', 'elementor-pro' ), 'default' => '5', 'condition' => [ 'pagination_type!' => [ 'load_more_on_click', 'load_more_infinite_scroll', '', ], ], ] ); $this->add_control( 'pagination_numbers_shorten', [ 'label' => esc_html__( 'Shorten', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'condition' => [ 'pagination_type' => [ 'numbers', 'numbers_and_prev_next', ], ], ] ); $this->add_control( 'pagination_prev_label', [ 'label' => esc_html__( 'Previous Label', 'elementor-pro' ), 'dynamic' => [ 'active' => true, ], 'default' => esc_html__( '« Previous', 'elementor-pro' ), 'condition' => [ 'pagination_type' => [ 'prev_next', 'numbers_and_prev_next', ], ], ] ); $this->add_control( 'pagination_next_label', [ 'label' => esc_html__( 'Next Label', 'elementor-pro' ), 'default' => esc_html__( 'Next »', 'elementor-pro' ), 'condition' => [ 'pagination_type' => [ 'prev_next', 'numbers_and_prev_next', ], ], 'dynamic' => [ 'active' => true, ], ] ); $this->add_control( 'pagination_align', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-text-align-right', ], ], 'default' => 'center', 'selectors' => [ '{{WRAPPER}} .elementor-pagination' => 'text-align: {{VALUE}};', ], 'condition' => [ 'pagination_type!' => [ 'load_more_on_click', 'load_more_infinite_scroll', '', ], ], ] ); $this->add_control( 'pagination_individual_divider', [ 'type' => Controls_Manager::DIVIDER, 'condition' => [ 'pagination_type' => [ 'numbers', 'numbers_and_prev_next', 'prev_next', ], ], ] ); $this->add_control( 'pagination_individual_handle', [ 'label' => esc_html__( 'Individual Pagination', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'On', 'elementor-pro' ), 'label_off' => esc_html__( 'Off', 'elementor-pro' ), 'default' => '', 'condition' => [ 'pagination_type' => [ 'numbers', 'numbers_and_prev_next', 'prev_next', ], ], ] ); $this->add_control( 'pagination_individual_handle_message', [ 'type' => Controls_Manager::RAW_HTML, 'raw' => esc_html__( 'For multiple Posts Widgets on the same page, toggle this on to control the pagination for each individually. Note: It affects the page\'s URL structure.', 'elementor-pro' ), 'content_classes' => 'elementor-control-field-description', 'condition' => [ 'pagination_type' => [ 'numbers', 'numbers_and_prev_next', 'prev_next', ], ], ] ); $this->add_control( 'load_more_spinner', [ 'label' => esc_html__( 'Spinner', 'elementor-pro' ), 'type' => Controls_Manager::ICONS, 'fa4compatibility' => 'icon', 'default' => [ 'value' => 'fas fa-spinner', 'library' => 'fa-solid', ], 'exclude_inline_options' => [ 'svg' ], 'recommended' => [ 'fa-solid' => [ 'spinner', 'cog', 'sync', 'sync-alt', 'asterisk', 'circle-notch', ], ], 'skin' => 'inline', 'label_block' => false, 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], ], 'frontend_available' => true, ] ); $this->add_control( 'heading_load_more_button', [ 'label' => esc_html__( 'Button', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'pagination_type' => 'load_more_on_click', ], ] ); $this->register_button_content_controls( [ 'button_text' => esc_html__( 'Load More', 'elementor-pro' ), 'control_label_name' => esc_html__( 'Button Text', 'elementor-pro' ), 'section_condition' => [ 'pagination_type' => 'load_more_on_click', ], 'exclude_inline_options' => [ 'svg' ], ] ); $this->remove_control( 'button_type' ); $this->remove_control( 'link' ); $this->remove_control( 'size' ); $this->add_control( 'heading_load_more_no_posts_message', [ 'label' => esc_html__( 'No More Posts Message', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], ], 'dynamic' => [ 'active' => true, ], ] ); $this->add_responsive_control( 'load_more_no_posts_message_align', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-text-align-right', ], 'justify' => [ 'title' => esc_html__( 'Justified', 'elementor-pro' ), 'icon' => 'eicon-text-align-justify', ], ], 'selectors' => [ '{{WRAPPER}}' => '--load-more-message-alignment: {{VALUE}};', ], 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], ], ] ); $this->add_control( 'load_more_no_posts_message_switcher', [ 'label' => esc_html__( 'Custom Messages', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], ], ] ); $this->add_control( 'load_more_no_posts_custom_message', [ 'label' => esc_html__( 'No more posts message', 'elementor-pro' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'No more posts to show', 'elementor-pro' ), 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], 'load_more_no_posts_message_switcher' => 'yes', ], 'label_block' => true, 'dynamic' => [ 'active' => true, ], ] ); $this->end_controls_section(); // Pagination style controls for prev/next and numbers pagination. $this->start_controls_section( 'section_pagination_style', [ 'label' => esc_html__( 'Pagination', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ 'pagination_type!' => [ 'load_more_on_click', 'load_more_infinite_scroll', '', ], ], ] ); $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' => esc_html__( 'Colors', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', ] ); $this->start_controls_tabs( 'pagination_colors' ); $this->start_controls_tab( 'pagination_color_normal', [ 'label' => esc_html__( 'Normal', 'elementor-pro' ), ] ); $this->add_control( 'pagination_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), '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' => esc_html__( 'Hover', 'elementor-pro' ), ] ); $this->add_control( 'pagination_hover_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), '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' => esc_html__( 'Active', 'elementor-pro' ), ] ); $this->add_control( 'pagination_active_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), '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' => esc_html__( 'Space Between', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'separator' => 'before', 'default' => [ 'size' => 10, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], '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' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-pagination' => 'margin-top: {{SIZE}}{{UNIT}}', ], ] ); $this->end_controls_section(); // Pagination style controls for on-load pagination with type on-click/infinity-scroll. $this->start_controls_section( 'section_style', [ 'label' => esc_html__( 'Pagination', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ 'pagination_type' => [ 'load_more_on_click', 'load_more_infinite_scroll', ], ], ] ); $this->register_load_more_button_style_controls(); $this->register_load_more_message_style_controls(); $this->end_controls_section(); } abstract public function query_posts(); public function get_current_page() { if ( '' === $this->get_settings_for_display( 'pagination_type' ) ) { return 1; } return max( 1, get_query_var( 'paged' ), get_query_var( 'page' ), Utils::_unstable_get_super_global_value( $_GET, 'e-page-' . $this->get_id() ) ); } public function is_rest_request() { $request_uri = Utils::_unstable_get_super_global_value( $_SERVER, 'REQUEST_URI' ); return false !== wp_get_referer() && isset( $_SERVER['REQUEST_URI'] ) && ( false !== strpos( $request_uri, 'wp-json' ) || false !== strpos( $request_uri, 'rest_route' ) ); } public function get_wp_link_page( $i ) { if ( ( ! is_singular() || is_front_page() ) && ! $this->is_rest_request() && ! $this->is_allow_to_use_custom_page_option() ) { 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 ( $this->is_rest_request() ) { $link_unescaped = wp_get_referer(); $post_id = url_to_postid( $link_unescaped ); if ( $post_id > 0 ) { $post = get_post( $post_id ); } $url = $this->get_base_url_for_rest_request( $post_id, $url ); } if ( $i > 1 ) { if ( '' === get_option( 'permalink_structure' ) || in_array( $post->post_status, [ 'draft', 'pending' ] ) ) { $url = add_query_arg( $this->get_wp_pagination_query_var(), $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 ( $i > 1 && $this->is_allow_to_use_custom_page_option() ) { $url = $this->get_wp_link_page_url_for_custom_page_option( $url, $i, $post_id ?? 0 ); } if ( 1 === $i && $this->is_allow_to_use_custom_page_option() ) { $url = $this->get_base_url(); } if ( is_preview() ) { $url = $this->get_wp_link_page_url_for_preview( $post, $query_args, $url ); } if ( $this->is_rest_request() ) { $url = $this->get_wp_link_page_url_for_rest_request( $url, $link_unescaped ); } if ( ! $this->is_rest_request() && $this->current_url_contains_taxonomy_filter() && ! is_preview() ) { $url = $this->get_wp_link_page_url_for_normal_page_load( $url ); } return esc_url( $url ); } public function is_allow_to_use_custom_page_option() { return 'ajax' === $this->get_settings_for_display( 'pagination_load_type' ) || 'yes' === $this->get_settings_for_display( 'pagination_individual_handle' ); } protected function get_base_url_for_rest_request( $post_id, $url ) { if ( $post_id > 0 ) { return get_permalink( $post_id ); } global $wp_rewrite; if ( $wp_rewrite->using_permalinks() && ( $this->current_url_contains_taxonomy_filter() || $this->referer_contains_taxonomy_filter() ) ) { $url = $this->is_allow_to_use_custom_page_option() ? get_query_var( 'pagination_base_url' ) : get_query_var( 'pagination_base_url' ) . user_trailingslashit( "$wp_rewrite->pagination_base/", 'single_paged' ); } else { $url = remove_query_arg( 'p', $url ); } return $url; } protected function get_wp_link_page_url_for_preview( $post, $query_args, $url ) { if ( 'draft' === $post->post_status || ! isset( $_GET['preview_id'], $_GET['preview_nonce'] ) ) { return $url; } $query_args['preview_id'] = Utils::_unstable_get_super_global_value( $_GET, 'preview_id' ); $query_args['preview_nonce'] = Utils::_unstable_get_super_global_value( $_GET, 'preview_nonce' ); if ( $this->is_rest_request() || ! $this->current_url_contains_taxonomy_filter() ) { return get_preview_post_link( $post, $query_args, $url ); } wp_parse_str( htmlspecialchars_decode( Utils::_unstable_get_super_global_value( $_SERVER, 'QUERY_STRING' ) ), $query_params ); foreach ( $query_params as $param_key => $param_value ) { if ( false !== strpos( $param_key, 'e-filter-' ) ) { $query_args[ $param_key ] = $param_value; } } return get_preview_post_link( $post, $query_args, $url ); } protected function get_wp_link_page_url_for_rest_request( $url, $link_unescaped ) { $url_components = wp_parse_url( $link_unescaped ); $query_args = []; if ( isset( $url_components['query'] ) ) { wp_parse_str( $url_components['query'], $query_args ); } $url = ! empty( $query_args ) ? $url . '&' . http_build_query( $query_args ) : $url; return $this->format_query_string_concatenation( $url ); } protected function get_wp_link_page_url_for_normal_page_load( $url ) { wp_parse_str( htmlspecialchars_decode( Utils::_unstable_get_super_global_value( $_SERVER, 'QUERY_STRING' ) ), $query_params ); $e_filters = ''; foreach ( $query_params as $param_key => $param_value ) { if ( false !== strpos( $param_key, 'e-filter' ) ) { $e_filters .= '&' . $param_key . '=' . $param_value; } } return $this->format_query_string_concatenation( $url . $e_filters ); } public function current_url_contains_taxonomy_filter() { return false !== strpos( Utils::_unstable_get_super_global_value( $_SERVER, 'QUERY_STRING' ), 'e-filter-' ); } public function referer_contains_taxonomy_filter() { return false !== strpos( Utils::_unstable_get_super_global_value( $_SERVER, 'HTTP_REFERER' ), 'e-filter-' ); } protected function format_query_string_concatenation( $input ) { if ( false === strpos( $input, '?' ) ) { // If "?" doesn't exist in the input URL, replace the first "&" with "?" $input = preg_replace( '/&/', '?', $input, 1 ); } return $input; } 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_for_display( 'pagination_prev_label' ) ); } else { $return['prev'] = sprintf( $disabled_template, 'prev', $this->get_settings_for_display( '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_for_display( 'pagination_next_label' ) ); } else { $return['next'] = sprintf( $disabled_template, 'next', $this->get_settings_for_display( 'pagination_next_label' ) ); } return $return; } protected function register_controls() { $this->start_controls_section( 'section_layout', [ 'label' => esc_html__( 'Layout', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_CONTENT, ] ); $this->end_controls_section(); } protected function get_pagination_type_options() { return [ '' => esc_html__( 'None', 'elementor-pro' ), 'numbers' => esc_html__( 'Numbers', 'elementor-pro' ), 'prev_next' => esc_html__( 'Previous/Next', 'elementor-pro' ), 'numbers_and_prev_next' => esc_html__( 'Numbers', 'elementor-pro' ) . ' + ' . esc_html__( 'Previous/Next', 'elementor-pro' ), self::LOAD_MORE_ON_CLICK => esc_html__( 'Load on Click', 'elementor-pro' ), self::LOAD_MORE_INFINITE_SCROLL => esc_html__( 'Infinite Scroll', 'elementor-pro' ), ]; } public function render_plain_content() {} /** * @param string $url * @param int $i * @param int $post_id * @return string */ private function get_wp_link_page_url_for_custom_page_option( $url, $i, $post_id ) { $base_raw_url = $this->is_rest_request() ? $this->get_base_url_for_rest_request( $post_id, $url ) : $this->get_base_url(); $pagination_key = 'e-page-' . $this->get_id(); if ( 'yes' === $this->get_settings_for_display( 'pagination_individual_handle' ) ) { $base_raw_url .= $this->get_pagination_query_vars_for_others_individually_paginated_widgets( $pagination_key ); } return $this->format_query_string_concatenation( $base_raw_url . '&' . $pagination_key . '=' . $i ); } private function get_pagination_query_vars_for_others_individually_paginated_widgets( string $pagination_key ): string { wp_parse_str( htmlspecialchars_decode( Utils::_unstable_get_super_global_value( $_SERVER, 'QUERY_STRING' ) ), $query_params ); $e_page = ''; foreach ( $query_params as $param_key => $param_value ) { if ( false !== strpos( $param_key, 'e-page' ) && $pagination_key !== $param_key ) { $e_page .= '&' . $param_key . '=' . $param_value; } } return $e_page; } /** * @return string */ private function get_wp_pagination_query_var() { if ( '' === get_option( 'permalink_structure' ) && $this->is_posts_page( $this->is_allow_to_use_custom_page_option() ) ) { return 'paged'; } return 'page'; } } widgets/posts.php 0000644 00000006412 14720516621 0010102 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Widgets; use Elementor\Controls_Manager; use ElementorPro\Modules\QueryControl\Module as Module_Query; use ElementorPro\Modules\QueryControl\Controls\Group_Control_Related; use ElementorPro\Modules\Posts\Skins; use ElementorPro\Modules\Posts\Traits\Query_Note_Trait; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Class Posts */ class Posts extends Posts_Base { use Query_Note_Trait; public function get_name() { return 'posts'; } public function get_title() { return esc_html__( 'Posts', 'elementor-pro' ); } public function get_keywords() { return [ 'posts', 'cpt', 'item', 'loop', 'query', 'cards', 'custom post type' ]; } /** * Get style dependencies. * * Retrieve the list of style dependencies the widget requires. * * @since 3.24.0 * @access public * * @return array Widget style dependencies. */ public function get_style_depends(): array { return [ 'widget-posts' ]; } public function on_import( $element ) { if ( isset( $element['settings']['posts_post_type'] ) && ! 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_Classic( $this ) ); $this->add_skin( new Skins\Skin_Cards( $this ) ); $this->add_skin( new Skins\Skin_Full_Content( $this ) ); } protected function register_controls() { parent::register_controls(); $this->register_query_section_controls(); $this->register_pagination_section_controls(); } /** * Get Query Name * * Returns the query control name used in the widget's main query. * * @since 3.8.0 * * @return string */ public function get_query_name() { return $this->get_name(); } public function query_posts() { $query_args = [ 'posts_per_page' => $this->get_posts_per_page_value(), 'paged' => $this->get_current_page(), 'has_custom_pagination' => $this->is_allow_to_use_custom_page_option(), ]; /** @var Module_Query $elementor_query */ $elementor_query = Module_Query::instance(); $this->query = $elementor_query->get_query( $this, $this->get_query_name(), $query_args, [] ); } /** * Get Posts Per Page Value * * Returns the value of the Posts Per Page control of the widget. This method was created because in some cases, * the control is registered in the widget, and in some cases, it is registered in a widget skin. * * @since 3.8.0 * @access protected * * @return mixed */ protected function get_posts_per_page_value() { return $this->get_current_skin()->get_instance_value( 'posts_per_page' ); } protected function register_query_section_controls() { $this->start_controls_section( 'section_query', [ 'label' => esc_html__( 'Query', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_CONTENT, ] ); $this->add_group_control( Group_Control_Related::get_type(), [ 'name' => $this->get_name(), 'presets' => [ 'full' ], 'exclude' => [ 'posts_per_page', //use the one from Layout section ], ] ); if ( $this->is_editing_archive_template() ) { $this->inject_archive_query_note( 'posts_query_id', 'posts_post_type', $this ); } $this->end_controls_section(); } } skins/skin-cards.php 0000644 00000037634 14720516621 0010463 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Skins; use Elementor\Controls_Manager; 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 Elementor\Utils; use Elementor\Widget_Base; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Skin_Cards extends Skin_Base { protected function _register_controls_actions() { parent::_register_controls_actions(); add_action( 'elementor/element/posts/cards_section_design_image/before_section_end', [ $this, 'register_additional_design_image_controls' ] ); } public function get_id() { return 'cards'; } public function get_title() { return esc_html__( 'Cards', 'elementor-pro' ); } public function start_controls_tab( $id, $args ) { $args['condition']['_skin'] = $this->get_id(); $this->parent->start_controls_tab( $this->get_control_id( $id ), $args ); } public function end_controls_tab() { $this->parent->end_controls_tab(); } public function start_controls_tabs( $id ) { $args['condition']['_skin'] = $this->get_id(); $this->parent->start_controls_tabs( $this->get_control_id( $id ) ); } public function end_controls_tabs() { $this->parent->end_controls_tabs(); } public function register_controls( Widget_Base $widget ) { $this->parent = $widget; $this->register_columns_controls(); $this->register_post_count_control(); $this->register_thumbnail_controls(); $this->register_title_controls(); $this->register_excerpt_controls(); $this->register_meta_data_controls(); $this->register_read_more_controls(); $this->register_link_controls(); $this->register_badge_controls(); $this->register_avatar_controls(); } public function register_design_controls() { $this->register_design_layout_controls(); $this->register_design_card_controls(); $this->register_design_image_controls(); $this->register_design_content_controls(); } protected function register_thumbnail_controls() { parent::register_thumbnail_controls(); $this->remove_responsive_control( 'image_width' ); $this->update_control( 'thumbnail', [ 'label' => esc_html__( 'Show Image', 'elementor-pro' ), 'options' => [ 'top' => esc_html__( 'Yes', 'elementor-pro' ), 'none' => esc_html__( 'No', 'elementor-pro' ), ], 'render_type' => 'template', ] ); } protected function register_meta_data_controls() { parent::register_meta_data_controls(); $this->update_control( 'meta_separator', [ 'default' => '•', ] ); } public function register_additional_design_image_controls() { $this->update_control( 'image_spacing', [ 'selectors' => [ '{{WRAPPER}} .elementor-post__text' => 'margin-top: {{SIZE}}{{UNIT}}', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); $this->remove_control( 'img_border_radius' ); $this->add_control( 'heading_badge_style', [ 'label' => esc_html__( 'Badge', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_position', [ 'label' => 'Badge Position', 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-h-align-left', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-h-align-right', ], ], 'default' => 'right', 'selectors' => [ '{{WRAPPER}} .elementor-post__badge' => '{{VALUE}}: 0', ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_bg_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__badge' => 'background-color: {{VALUE}};', ], 'global' => [ 'default' => Global_Colors::COLOR_ACCENT, ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_color', [ 'label' => esc_html__( 'Text Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__badge' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__badge' => 'border-radius: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_size', [ 'label' => esc_html__( 'Size', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'min' => 5, 'max' => 50, ], 'em' => [ 'min' => 0.5, 'max' => 5, ], 'rem' => [ 'min' => 0.5, 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__badge' => 'font-size: {{SIZE}}{{UNIT}}', ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'badge_margin', [ 'label' => esc_html__( 'Margin', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'default' => [ 'size' => 20, ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__badge' => 'margin: {{SIZE}}{{UNIT}}', ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'badge_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_ACCENT, ], 'selector' => '{{WRAPPER}} .elementor-post__card .elementor-post__badge', 'exclude' => [ 'font_size', 'line-height' ], 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); $this->add_control( 'heading_avatar_style', [ 'label' => esc_html__( 'Avatar', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', $this->get_control_id( 'show_avatar' ) => 'show-avatar', ], ] ); $this->add_control( 'avatar_size', [ 'label' => esc_html__( 'Size', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__avatar' => 'top: calc(-{{SIZE}}{{UNIT}} / 2);', '{{WRAPPER}} .elementor-post__avatar img' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};', '{{WRAPPER}} .elementor-post__thumbnail__link' => 'margin-bottom: calc({{SIZE}}{{UNIT}} / 2)', ], 'condition' => [ $this->get_control_id( 'show_avatar' ) => 'show-avatar', ], ] ); } public function register_badge_controls() { $this->add_control( 'show_badge', [ 'label' => esc_html__( 'Badge', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Show', 'elementor-pro' ), 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'default' => 'yes', 'separator' => 'before', ] ); $this->add_control( 'badge_taxonomy', [ 'label' => esc_html__( 'Badge Taxonomy', 'elementor-pro' ), 'type' => Controls_Manager::SELECT2, 'label_block' => true, 'default' => 'category', 'options' => $this->get_taxonomies(), 'condition' => [ $this->get_control_id( 'show_badge' ) => 'yes', ], ] ); } public function register_avatar_controls() { $this->add_control( 'show_avatar', [ 'label' => esc_html__( 'Avatar', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Show', 'elementor-pro' ), 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'return_value' => 'show-avatar', 'default' => 'show-avatar', 'separator' => 'before', 'prefix_class' => 'elementor-posts--', 'render_type' => 'template', 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); } public function register_design_card_controls() { $this->start_controls_section( 'section_design_card', [ 'label' => esc_html__( 'Card', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'card_bg_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__card' => 'background-color: {{VALUE}}', ], ] ); $this->add_control( 'card_border_color', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__card' => 'border-color: {{VALUE}}', ], ] ); $this->add_control( 'card_border_width', [ 'label' => esc_html__( 'Border Width', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ 'px' => [ 'max' => 20, ], 'em' => [ 'max' => 2, ], 'rem' => [ 'max' => 2, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card' => 'border-width: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'card_border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 200, ], 'em' => [ 'max' => 20, ], 'rem' => [ 'max' => 20, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card' => 'border-radius: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'card_padding', [ 'label' => esc_html__( 'Horizontal Padding', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__text' => 'padding: 0 {{SIZE}}{{UNIT}}', '{{WRAPPER}} .elementor-post__meta-data' => 'padding: 10px {{SIZE}}{{UNIT}}', '{{WRAPPER}} .elementor-post__avatar' => 'padding-right: {{SIZE}}{{UNIT}}; padding-left: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'card_vertical_padding', [ 'label' => esc_html__( 'Vertical Padding', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__card' => 'padding-top: {{SIZE}}{{UNIT}}; padding-bottom: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'box_shadow_box_shadow_type', // The name of this control is like that, for future extensibility to group_control box shadow. [ 'label' => esc_html__( 'Box Shadow', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'prefix_class' => 'elementor-card-shadow-', 'default' => 'yes', ] ); $this->add_control( 'hover_effect', [ 'label' => esc_html__( 'Hover Effect', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'label_block' => false, 'options' => [ 'none' => esc_html__( 'None', 'elementor-pro' ), 'gradient' => esc_html__( 'Gradient', 'elementor-pro' ), //'zoom-in' => esc_html__( 'Zoom In', 'elementor-pro' ), //'zoom-out' => esc_html__( 'Zoom Out', 'elementor-pro' ), ], 'default' => 'gradient', 'separator' => 'before', 'prefix_class' => 'elementor-posts__hover-', ] ); $this->add_control( 'meta_border_color', [ 'label' => esc_html__( 'Meta Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => [ '{{WRAPPER}} .elementor-post__card .elementor-post__meta-data' => 'border-top-color: {{VALUE}}', ], 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->end_controls_section(); } protected function register_design_content_controls() { parent::register_design_content_controls(); $this->remove_control( 'meta_spacing' ); $this->update_control( 'read_more_spacing', [ 'selectors' => [ '{{WRAPPER}} .elementor-post__read-more' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], ], [ 'recursive' => true, ] ); } 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 render_post_header() { ?> <article <?php post_class( [ 'elementor-post elementor-grid-item' ] ); ?>> <div class="elementor-post__card"> <?php } protected function render_post_footer() { ?> </div> </article> <?php } protected function render_avatar() { ?> <div class="elementor-post__avatar"> <?php echo get_avatar( get_the_author_meta( 'ID' ), 128, '', get_the_author_meta( 'display_name' ) ); ?> </div> <?php } protected function render_badge() { $taxonomy = $this->get_instance_value( 'badge_taxonomy' ); if ( empty( $taxonomy ) || ! taxonomy_exists( $taxonomy ) ) { return; } $terms = get_the_terms( get_the_ID(), $taxonomy ); if ( empty( $terms[0] ) ) { return; } ?> <div class="elementor-post__badge"><?php echo esc_html( $terms[0]->name ); ?></div> <?php } protected function render_thumbnail() { if ( 'none' === $this->get_instance_value( 'thumbnail' ) ) { return; } $settings = $this->parent->get_settings(); $setting_key = $this->get_control_id( 'thumbnail_size' ); $settings[ $setting_key ] = [ 'id' => get_post_thumbnail_id(), ]; $thumbnail_html = Group_Control_Image_Size::get_attachment_image_html( $settings, $setting_key ); if ( empty( $thumbnail_html ) ) { return; } $optional_attributes_html = $this->get_optional_link_attributes_html(); ?> <a class="elementor-post__thumbnail__link" href="<?php echo esc_url( get_permalink() ); ?>" tabindex="-1" <?php Utils::print_unescaped_internal_string( $optional_attributes_html ); ?>><div class="elementor-post__thumbnail"><?php Utils::print_unescaped_internal_string( $thumbnail_html ); ?></div></a> <?php if ( $this->get_instance_value( 'show_badge' ) ) { $this->render_badge(); } if ( $this->get_instance_value( 'show_avatar' ) ) { $this->render_avatar(); } } protected function render_post() { $this->render_post_header(); $this->render_thumbnail(); $this->render_text_header(); $this->render_title(); $this->render_excerpt(); $this->render_read_more(); $this->render_text_footer(); $this->render_meta_data(); $this->render_post_footer(); } } skins/skin-full-content.php 0000644 00000000374 14720516621 0011770 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Skins; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Skin_Full_Content extends Skin_Classic { use Skin_Content_Base; public function get_id() { return 'full_content'; } } skins/skin-base.php 0000644 00000110173 14720516621 0010267 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Skins; use Elementor\Controls_Manager; use Elementor\Core\Kits\Documents\Tabs\Global_Colors; use Elementor\Core\Kits\Documents\Tabs\Global_Typography; use Elementor\Group_Control_Css_Filter; use Elementor\Group_Control_Image_Size; use Elementor\Group_Control_Typography; use Elementor\Group_Control_Text_Stroke; use Elementor\Icons_Manager; use Elementor\Skin_Base as Elementor_Skin_Base; use Elementor\Utils; use Elementor\Widget_Base; use ElementorPro\Modules\LoopBuilder\Providers\Taxonomy_Loop_Provider; use ElementorPro\Modules\Posts\Traits\Button_Widget_Trait; use ElementorPro\Plugin; use ElementorPro\Modules\Posts\Widgets\Posts_Base; use ElementorPro\Core\Utils as ProUtils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Skin_Base extends Elementor_Skin_Base { use Button_Widget_Trait; /** * @var string Save current permalink to avoid conflict with plugins the filters the permalink during the post render. */ protected $current_permalink; protected function _register_controls_actions() { add_action( 'elementor/element/posts/section_layout/before_section_end', [ $this, 'register_controls' ] ); add_action( 'elementor/element/posts/section_query/after_section_end', [ $this, 'register_style_sections' ] ); } public function register_style_sections( Widget_Base $widget ) { $this->parent = $widget; $this->register_design_controls(); } public function register_controls( Widget_Base $widget ) { $this->parent = $widget; $this->register_columns_controls(); $this->register_post_count_control(); $this->register_thumbnail_controls(); $this->register_title_controls(); $this->register_excerpt_controls(); $this->register_meta_data_controls(); $this->register_read_more_controls(); $this->register_link_controls(); } public function register_design_controls() { $this->register_design_layout_controls(); $this->register_design_image_controls(); $this->register_design_content_controls(); } protected function register_thumbnail_controls() { $this->add_control( 'thumbnail', [ 'label' => esc_html__( 'Image Position', 'elementor-pro' ), 'type' => Controls_Manager::SELECT, 'default' => 'top', 'options' => [ 'top' => esc_html__( 'Top', 'elementor-pro' ), 'left' => esc_html__( 'Left', 'elementor-pro' ), 'right' => esc_html__( 'Right', 'elementor-pro' ), 'none' => esc_html__( 'None', 'elementor-pro' ), ], 'prefix_class' => 'elementor-posts--thumbnail-', ] ); $this->add_control( 'masonry', [ 'label' => esc_html__( 'Masonry', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_off' => esc_html__( 'Off', 'elementor-pro' ), 'label_on' => esc_html__( 'On', 'elementor-pro' ), 'condition' => [ $this->get_control_id( 'columns!' ) => '1', $this->get_control_id( 'thumbnail' ) => 'top', ], 'render_type' => 'ui', 'frontend_available' => true, ] ); $this->add_group_control( Group_Control_Image_Size::get_type(), [ 'name' => 'thumbnail_size', 'default' => 'medium', 'exclude' => [ 'custom' ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], 'prefix_class' => 'elementor-posts--thumbnail-size-', ] ); $this->add_responsive_control( 'item_ratio', [ 'label' => esc_html__( 'Image Ratio', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'size' => 0.66, ], 'tablet_default' => [ 'size' => '', ], 'mobile_default' => [ 'size' => 0.5, ], 'range' => [ 'px' => [ 'min' => 0.1, 'max' => 2, 'step' => 0.01, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-posts-container .elementor-post__thumbnail' => 'padding-bottom: calc( {{SIZE}} * 100% );', '{{WRAPPER}}:after' => 'content: "{{SIZE}}";', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', $this->get_control_id( 'masonry' ) => '', ], ] ); $this->add_responsive_control( 'image_width', [ 'label' => esc_html__( 'Image Width', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ '%' => [ 'min' => 10, 'max' => 100, ], 'px' => [ 'min' => 10, 'max' => 600, ], 'em' => [ 'min' => 1, 'max' => 60, ], 'rem' => [ 'min' => 1, 'max' => 60, ], ], 'default' => [ 'size' => 100, 'unit' => '%', ], 'tablet_default' => [ 'size' => '', 'unit' => '%', ], 'mobile_default' => [ 'size' => 100, 'unit' => '%', ], 'selectors' => [ '{{WRAPPER}} .elementor-post__thumbnail__link' => 'width: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); } protected function register_columns_controls() { $this->add_responsive_control( 'columns', [ 'label' => esc_html__( 'Columns', 'elementor-pro' ), '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, ] ); } protected function register_post_count_control() { $this->add_control( 'posts_per_page', [ 'label' => esc_html__( 'Posts Per Page', 'elementor-pro' ), 'type' => Controls_Manager::NUMBER, 'default' => 6, ] ); } protected function register_title_controls() { $this->add_control( 'show_title', [ 'label' => esc_html__( 'Title', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Show', 'elementor-pro' ), 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'default' => 'yes', 'separator' => 'before', ] ); $this->add_control( 'title_tag', [ 'label' => esc_html__( 'Title HTML Tag', 'elementor-pro' ), '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' => [ $this->get_control_id( 'show_title' ) => 'yes', ], ] ); } protected function register_excerpt_controls() { $this->add_control( 'show_excerpt', [ 'label' => esc_html__( 'Excerpt', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Show', 'elementor-pro' ), 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'default' => 'yes', ] ); $this->add_control( 'excerpt_length', [ 'label' => esc_html__( 'Excerpt Length', 'elementor-pro' ), 'type' => Controls_Manager::NUMBER, /** This filter is documented in wp-includes/formatting.php */ 'default' => apply_filters( 'excerpt_length', 25 ), 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); $this->add_control( 'apply_to_custom_excerpt', [ 'label' => esc_html__( 'Apply to custom Excerpt', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Yes', 'elementor-pro' ), 'label_off' => esc_html__( 'No', 'elementor-pro' ), 'default' => 'no', 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); } protected function register_read_more_controls() { $this->add_control( 'show_read_more', [ 'label' => esc_html__( 'Read More', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Show', 'elementor-pro' ), 'label_off' => esc_html__( 'Hide', 'elementor-pro' ), 'default' => 'yes', 'separator' => 'before', ] ); $this->add_control( 'read_more_text', [ 'label' => esc_html__( 'Read More Text', 'elementor-pro' ), 'type' => Controls_Manager::TEXT, 'dynamic' => [ 'active' => true, ], 'ai' => [ 'active' => false, ], 'default' => esc_html__( 'Read More »', 'elementor-pro' ), 'condition' => [ $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); $this->add_control( 'read_more_alignment', [ 'label' => esc_html__( 'Automatically align buttons', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Yes', 'elementor-pro' ), 'label_off' => esc_html__( 'No', 'elementor-pro' ), 'default' => '', 'render_type' => 'template', 'selectors' => [ // --item-display is used for the styling of both elementor-post__card and elementor-post__text '{{WRAPPER}}' => '--item-display: flex; --read-more-alignment: 1;', ], 'condition' => [ $this->get_control_id( 'masonry!' ) => 'yes', $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); } protected function register_link_controls() { $this->add_control( 'open_new_tab', [ 'label' => esc_html__( 'Open in new window', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'label_on' => esc_html__( 'Yes', 'elementor-pro' ), 'label_off' => esc_html__( 'No', 'elementor-pro' ), 'default' => 'no', 'render_type' => 'none', ] ); } protected function get_optional_link_attributes_html() { $settings = $this->parent->get_settings(); $new_tab_setting_key = $this->get_control_id( 'open_new_tab' ); $optional_attributes_html = 'yes' === $settings[ $new_tab_setting_key ] ? 'target="_blank"' : ''; return $optional_attributes_html; } protected function register_meta_data_controls() { $this->add_control( 'meta_data', [ 'label' => esc_html__( 'Meta Data', 'elementor-pro' ), 'label_block' => true, 'type' => Controls_Manager::SELECT2, 'default' => [ 'date', 'comments' ], 'multiple' => true, 'options' => [ 'author' => esc_html__( 'Author', 'elementor-pro' ), 'date' => esc_html__( 'Date', 'elementor-pro' ), 'time' => esc_html__( 'Time', 'elementor-pro' ), 'comments' => esc_html__( 'Comments', 'elementor-pro' ), 'modified' => esc_html__( 'Date Modified', 'elementor-pro' ), ], 'separator' => 'before', ] ); $this->add_control( 'meta_separator', [ 'label' => esc_html__( 'Separator Between', 'elementor-pro' ), 'type' => Controls_Manager::TEXT, 'default' => '///', 'ai' => [ 'active' => false, ], 'selectors' => [ '{{WRAPPER}} .elementor-post__meta-data span + span:before' => 'content: "{{VALUE}}"', ], 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], 'dynamic' => [ 'active' => true, ], ] ); } /** * Style Tab */ protected function register_design_layout_controls() { $this->start_controls_section( 'section_design_layout', [ 'label' => esc_html__( 'Layout', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'column_gap', [ 'label' => esc_html__( 'Columns Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 30, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}}' => '--grid-column-gap: {{SIZE}}{{UNIT}}', ], ] ); $this->add_responsive_control( 'row_gap', [ 'label' => esc_html__( 'Rows Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 35, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'frontend_available' => true, 'selectors' => [ '{{WRAPPER}}' => '--grid-row-gap: {{SIZE}}{{UNIT}}', ], ] ); $this->add_control( 'alignment', [ 'label' => esc_html__( 'Alignment', 'elementor-pro' ), 'type' => Controls_Manager::CHOOSE, 'options' => [ 'left' => [ 'title' => esc_html__( 'Left', 'elementor-pro' ), 'icon' => 'eicon-text-align-left', ], 'center' => [ 'title' => esc_html__( 'Center', 'elementor-pro' ), 'icon' => 'eicon-text-align-center', ], 'right' => [ 'title' => esc_html__( 'Right', 'elementor-pro' ), 'icon' => 'eicon-text-align-right', ], ], 'prefix_class' => 'elementor-posts--align-', ] ); $this->end_controls_section(); } protected function register_design_image_controls() { $this->start_controls_section( 'section_design_image', [ 'label' => esc_html__( 'Image', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); $this->add_responsive_control( 'img_border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-post__thumbnail' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); $this->add_responsive_control( 'image_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}}.elementor-posts--thumbnail-left .elementor-post__thumbnail__link' => 'margin-right: {{SIZE}}{{UNIT}}', '{{WRAPPER}}.elementor-posts--thumbnail-right .elementor-post__thumbnail__link' => 'margin-left: {{SIZE}}{{UNIT}}', '{{WRAPPER}}.elementor-posts--thumbnail-top .elementor-post__thumbnail__link' => 'margin-bottom: {{SIZE}}{{UNIT}}', ], 'default' => [ 'size' => 20, ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => 'none', ], ] ); $this->start_controls_tabs( 'thumbnail_effects_tabs' ); $this->start_controls_tab( 'normal', [ 'label' => esc_html__( 'Normal', 'elementor-pro' ), ] ); $this->add_group_control( Group_Control_Css_Filter::get_type(), [ 'name' => 'thumbnail_filters', 'selector' => '{{WRAPPER}} .elementor-post__thumbnail img', ] ); $this->end_controls_tab(); $this->start_controls_tab( 'hover', [ 'label' => esc_html__( 'Hover', 'elementor-pro' ), ] ); $this->add_group_control( Group_Control_Css_Filter::get_type(), [ 'name' => 'thumbnail_hover_filters', 'selector' => '{{WRAPPER}} .elementor-post:hover .elementor-post__thumbnail img', ] ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->end_controls_section(); } protected function register_design_content_controls() { $this->start_controls_section( 'section_design_content', [ 'label' => esc_html__( 'Content', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'heading_title_style', [ 'label' => esc_html__( 'Title', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'condition' => [ $this->get_control_id( 'show_title' ) => 'yes', ], ] ); $this->add_control( 'title_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_SECONDARY, ], 'selectors' => [ '{{WRAPPER}} .elementor-post__title, {{WRAPPER}} .elementor-post__title a' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'show_title' ) => 'yes', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'title_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_PRIMARY, ], 'selector' => '{{WRAPPER}} .elementor-post__title, {{WRAPPER}} .elementor-post__title a', 'condition' => [ $this->get_control_id( 'show_title' ) => 'yes', ], ] ); $this->add_group_control( Group_Control_Text_Stroke::get_type(), [ 'name' => 'text_stroke', 'selector' => '{{WRAPPER}} .elementor-post__title', ] ); $this->add_responsive_control( 'title_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__title' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'show_title' ) => 'yes', ], ] ); $this->add_control( 'heading_meta_style', [ 'label' => esc_html__( 'Meta', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->add_control( 'meta_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__meta-data' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->add_control( 'meta_separator_color', [ 'label' => esc_html__( 'Separator Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__meta-data span:before' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'meta_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY, ], 'selector' => '{{WRAPPER}} .elementor-post__meta-data', 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->add_responsive_control( 'meta_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__meta-data' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'meta_data!' ) => [], ], ] ); $this->add_control( 'heading_excerpt_style', [ 'label' => esc_html__( 'Excerpt', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); $this->add_control( 'excerpt_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post__excerpt p' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'excerpt_typography', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_TEXT, ], 'selector' => '{{WRAPPER}} .elementor-post__excerpt p', 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); $this->add_responsive_control( 'excerpt_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__excerpt' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'show_excerpt' ) => 'yes', ], ] ); $this->add_control( 'heading_readmore_style', [ 'label' => esc_html__( 'Read More', 'elementor-pro' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); $this->add_control( 'read_more_color', [ 'label' => esc_html__( 'Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'global' => [ 'default' => Global_Colors::COLOR_ACCENT, ], 'selectors' => [ '{{WRAPPER}} .elementor-post__read-more' => 'color: {{VALUE}};', ], 'condition' => [ $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'read_more_typography', // The 'a' selector is added for specificity, for when this control's selector is used in globals CSS. 'selector' => '{{WRAPPER}} a.elementor-post__read-more', 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_ACCENT, ], 'condition' => [ $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); $this->add_responsive_control( 'read_more_spacing', [ 'label' => esc_html__( 'Spacing', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__text' => 'margin-bottom: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'show_read_more' ) => 'yes', ], ] ); $this->end_controls_section(); } public function render() { $this->parent->query_posts(); /** @var \WP_Query $query */ $query = $this->parent->get_query(); if ( ! $query->found_posts ) { $this->handle_no_posts_found(); return; } $this->render_loop_header(); // It's the global `wp_query` it self. and the loop was started from the theme. if ( $query->in_the_loop ) { $this->current_permalink = get_permalink(); $this->render_post(); } else { while ( $query->have_posts() ) { $query->the_post(); $this->current_permalink = get_permalink(); $this->render_post(); } } wp_reset_postdata(); $this->render_loop_footer(); } public function filter_excerpt_length() { return $this->get_instance_value( 'excerpt_length' ); } public function filter_excerpt_more( $more ) { return ''; } public function get_container_class() { return 'elementor-posts--skin-' . $this->get_id(); } protected function render_thumbnail() { $thumbnail = $this->get_instance_value( 'thumbnail' ); if ( 'none' === $thumbnail && ! Plugin::elementor()->editor->is_edit_mode() ) { return; } $settings = $this->parent->get_settings(); $setting_key = $this->get_control_id( 'thumbnail_size' ); $settings[ $setting_key ] = [ 'id' => get_post_thumbnail_id(), ]; $thumbnail_html = Group_Control_Image_Size::get_attachment_image_html( $settings, $setting_key ); if ( empty( $thumbnail_html ) ) { return; } $optional_attributes_html = $this->get_optional_link_attributes_html(); ?> <a class="elementor-post__thumbnail__link" href="<?php echo esc_attr( $this->current_permalink ); ?>" tabindex="-1" <?php echo esc_attr( $optional_attributes_html ); ?>> <div class="elementor-post__thumbnail"><?php echo wp_kses_post( $thumbnail_html ); ?></div> </a> <?php } protected function render_title() { if ( ! $this->get_instance_value( 'show_title' ) ) { return; } $optional_attributes_html = $this->get_optional_link_attributes_html(); $tag = $this->get_instance_value( 'title_tag' ); ?> <<?php Utils::print_validated_html_tag( $tag ); ?> class="elementor-post__title"> <a href="<?php echo esc_attr( $this->current_permalink ); ?>" <?php echo esc_attr( $optional_attributes_html ); ?>> <?php the_title(); ?> </a> </<?php Utils::print_validated_html_tag( $tag ); ?>> <?php } protected function render_excerpt() { add_filter( 'excerpt_more', [ $this, 'filter_excerpt_more' ], 20 ); add_filter( 'excerpt_length', [ $this, 'filter_excerpt_length' ], 20 ); if ( ! $this->get_instance_value( 'show_excerpt' ) ) { return; } add_filter( 'excerpt_more', [ $this, 'filter_excerpt_more' ], 20 ); add_filter( 'excerpt_length', [ $this, 'filter_excerpt_length' ], 20 ); ?> <div class="elementor-post__excerpt"> <?php global $post; $apply_to_custom_excerpt = $this->get_instance_value( 'apply_to_custom_excerpt' ); // Force the manually-generated Excerpt length as well if the user chose to enable 'apply_to_custom_excerpt'. if ( 'yes' === $apply_to_custom_excerpt && ! empty( $post->post_excerpt ) ) { $max_length = (int) $this->get_instance_value( 'excerpt_length' ); $excerpt = apply_filters( 'the_excerpt', get_the_excerpt() ); $excerpt = ProUtils::trim_words( $excerpt, $max_length ); echo wp_kses_post( $excerpt ); } else { the_excerpt(); } ?> </div> <?php remove_filter( 'excerpt_length', [ $this, 'filter_excerpt_length' ], 20 ); remove_filter( 'excerpt_more', [ $this, 'filter_excerpt_more' ], 20 ); } protected function render_read_more() { $settings = $this->parent->get_settings_for_display(); $read_more_key = $this->get_control_id( 'read_more_text' ); $read_more = $settings[ $read_more_key ]; if ( ! $this->get_instance_value( 'show_read_more' ) ) { return; } $aria_label_text = sprintf( /* translators: %s: Post title. */ esc_attr__( 'Read more about %s', 'elementor-pro' ), get_the_title() ); $optional_attributes_html = $this->get_optional_link_attributes_html(); if ( $this->display_read_more_bottom() ) : ?> <div class="elementor-post__read-more-wrapper"> <?php endif; ?> <a class="elementor-post__read-more" href="<?php echo esc_url( $this->current_permalink ); ?>" aria-label="<?php echo esc_attr( $aria_label_text ); ?>" tabindex="-1" <?php Utils::print_unescaped_internal_string( $optional_attributes_html ); ?>> <?php echo wp_kses_post( $read_more ); ?> </a> <?php if ( $this->display_read_more_bottom() ) : ?> </div> <?php endif; } protected function render_post_header() { ?> <article <?php post_class( [ 'elementor-post elementor-grid-item' ] ); ?>> <?php } protected function render_post_footer() { ?> </article> <?php } protected function render_text_header() { ?> <div class="elementor-post__text"> <?php } protected function render_text_footer() { ?> </div> <?php } protected function get_loop_header_widget_classes() { return [ 'elementor-posts-container', 'elementor-posts', $this->get_container_class(), ]; } protected function handle_no_posts_found() {} protected function render_loop_header() { $classes = $this->get_loop_header_widget_classes(); /** @var \WP_Query $e_wp_query */ $e_wp_query = $this->parent->get_query(); // Use grid only if found posts. if ( isset( $e_wp_query->found_posts ) || Taxonomy_Loop_Provider::is_loop_taxonomy() ) { $classes[] = 'elementor-grid'; } $render_attributes = apply_filters( 'elementor/skin/loop_header_attributes', [ 'class' => $classes, ] ); $this->parent->add_render_attribute( 'container', $render_attributes ); ?> <div <?php $this->parent->print_render_attribute_string( 'container' ); ?>> <?php } protected function render_message() { $settings = $this->parent->get_settings_for_display(); ?> <div class="e-load-more-message"><?php echo esc_html( $settings['load_more_no_posts_custom_message'] ); ?></div> <?php } protected function render_loop_footer() { ?> </div> <?php $parent_settings = $this->parent->get_settings_for_display(); // If the skin has no pagination, there's nothing to render in the loop footer. if ( ! isset( $parent_settings['pagination_type'] ) ) { return; } $using_ajax_pagination = in_array( $parent_settings['pagination_type'], [ Posts_Base::LOAD_MORE_ON_CLICK, Posts_Base::LOAD_MORE_INFINITE_SCROLL, ], true); if ( $using_ajax_pagination && ! empty( $parent_settings['load_more_spinner']['value'] ) ) : ?> <span class="e-load-more-spinner"> <?php Icons_Manager::render_icon( $parent_settings['load_more_spinner'], [ 'aria-hidden' => 'true' ] ); ?> </span> <?php endif; ?> <?php if ( '' === $parent_settings['pagination_type'] ) { return; } $page_limit = $this->parent->get_query()->max_num_pages; // Page limit control should not effect in load more mode. if ( '' !== $parent_settings['pagination_page_limit'] && ! $using_ajax_pagination ) { $page_limit = min( $parent_settings['pagination_page_limit'], $page_limit ); } if ( 2 > $page_limit ) { return; } $this->parent->add_render_attribute( 'pagination', 'class', 'elementor-pagination' ); $has_numbers = in_array( $parent_settings['pagination_type'], [ 'numbers', 'numbers_and_prev_next' ] ); $has_prev_next = in_array( $parent_settings['pagination_type'], [ 'prev_next', 'numbers_and_prev_next' ] ); $load_more_type = $parent_settings['pagination_type']; $current_page = $this->parent->get_current_page(); $next_page = intval( $current_page ) + 1; $this->parent->add_render_attribute( 'load_more_anchor', [ 'data-page' => $current_page, 'data-max-page' => $this->parent->get_query()->max_num_pages, 'data-next-page' => $this->parent->get_wp_link_page( $next_page ), ] ); ?> <div class="e-load-more-anchor" <?php $this->parent->print_render_attribute_string( 'load_more_anchor' ); ?>></div> <?php if ( $using_ajax_pagination ) { if ( 'load_more_on_click' === $load_more_type ) { // The link-url control is hidden, so default value is added to keep the same style like button widget. $this->parent->set_settings( 'link', [ 'url' => '#' ] ); $this->render_button( $this->parent ); } $this->render_message(); return; } $links = []; if ( $has_numbers ) { $paginate_args = [ 'type' => 'array', 'current' => $this->parent->get_current_page(), 'total' => $page_limit, 'prev_next' => false, 'show_all' => 'yes' !== $parent_settings['pagination_numbers_shorten'], 'before_page_number' => '<span class="elementor-screen-only">' . esc_html__( 'Page', 'elementor-pro' ) . '</span>', ]; if ( is_singular() && ! is_front_page() && ! $this->parent->is_rest_request() ) { $paginate_args = $this->get_paginate_args_for_singular_post( $paginate_args ); } if ( is_archive() && $this->parent->current_url_contains_taxonomy_filter() ) { $paginate_args = $this->get_paginate_args_for_archive_with_filters( $paginate_args ); } if ( $this->parent->is_rest_request() ) { $paginate_args = $this->get_paginate_args_for_rest_request( $paginate_args ); } if ( $this->parent->is_allow_to_use_custom_page_option() ) { $paginate_args['format'] = $this->get_pagination_format( $paginate_args ); } $links = paginate_links( $paginate_args ); } if ( $has_prev_next ) { $prev_next = $this->parent->get_posts_nav_link( $page_limit ); array_unshift( $links, $prev_next['prev'] ); $links[] = $prev_next['next']; } // PHPCS - Seems that `$links` is safe. ?> <nav class="elementor-pagination" aria-label="<?php esc_attr_e( 'Pagination', 'elementor-pro' ); ?>"> <?php echo implode( PHP_EOL, $links ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </nav> <?php } protected function get_pagination_format( $paginate_args ) { $query_string_connector = ! empty( $paginate_args['base'] ) && strpos( $paginate_args['base'], '?' ) ? '&' : '?'; return $query_string_connector . 'e-page-' . $this->parent->get_id() . '=%#%'; } protected function get_paginate_args_for_singular_post( $paginate_args ) { global $wp_rewrite; if ( $wp_rewrite->using_permalinks() ) { $paginate_args['base'] = trailingslashit( get_permalink() ) . '%_%'; $paginate_args['format'] = user_trailingslashit( '%#%', 'single_paged' ); } else { $paginate_args['format'] = '?page=%#%'; } return $paginate_args; } protected function get_paginate_args_for_archive_with_filters( $paginate_args ) { global $wp_rewrite; if ( ! $wp_rewrite->using_permalinks() ) { $paginate_args['format'] = '?page=%#%'; } return $paginate_args; } protected function get_paginate_args_for_rest_request( $paginate_args ) { global $wp_rewrite; $link_unescaped = wp_get_referer(); $url_components = wp_parse_url( $link_unescaped ); $add_args = []; if ( isset( $url_components['query'] ) ) { wp_parse_str( $url_components['query'], $add_args ); } $url_to_post_id = url_to_postid( $link_unescaped ); $pagination_base_url = 0 !== $url_to_post_id ? get_permalink( $url_to_post_id ) : get_query_var( 'pagination_base_url' ); if ( $wp_rewrite->using_permalinks() ) { $paginate_args['base'] = trailingslashit( $pagination_base_url ) . '%_%'; $paginate_args['format'] = user_trailingslashit( '%#%', 'single_paged' ); $paginate_args['add_args'] = $add_args; if ( 0 === $url_to_post_id ) { unset( $paginate_args['format'] ); } } else { $base = $this->parent->is_allow_to_use_custom_page_option() ? $pagination_base_url . '&%_%' : trailingslashit( $pagination_base_url ) . '%_%'; $paginate_args['base'] = $base; $paginate_args['format'] = '&page=%#%'; $paginate_args['add_args'] = $add_args; } return $paginate_args; } protected function render_meta_data() { /** @var array $settings e.g. [ 'author', 'date', ... ] */ $settings = $this->get_instance_value( 'meta_data' ); if ( empty( $settings ) ) { return; } ?> <div class="elementor-post__meta-data"> <?php if ( in_array( 'author', $settings ) ) { $this->render_author(); } if ( in_array( 'date', $settings ) ) { $this->render_date_by_type(); } if ( in_array( 'time', $settings ) ) { $this->render_time(); } if ( in_array( 'comments', $settings ) ) { $this->render_comments(); } if ( in_array( 'modified', $settings ) ) { $this->render_date_by_type( 'modified' ); } ?> </div> <?php } protected function render_author() { ?> <span class="elementor-post-author"> <?php the_author(); ?> </span> <?php } protected function render_date_by_type( $type = 'publish' ) { ?> <span class="elementor-post-date"> <?php switch ( $type ) : case 'modified': $date = get_the_modified_date(); break; default: $date = get_the_date(); endswitch; /** This filter is documented in wp-includes/general-template.php */ // PHPCS - The date is safe. echo apply_filters( 'the_date', $date, get_option( 'date_format' ), '', '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </span> <?php } protected function render_time() { ?> <span class="elementor-post-time"> <?php the_time(); ?> </span> <?php } /** * Check if the Read More links needs to be displayed at the bottom of the Post item. * * Conditions: * 1) Read More aligned to the bottom * 2) Masonry layout not used. * 3) Display Read More link. * * @since 3.7.0 * * @return boolean */ protected function display_read_more_bottom() { $settings = $this->parent->get_settings(); if ( 'full_content' === $settings['_skin'] ) { return false; } return 'yes' === $settings[ $this->get_control_id( 'read_more_alignment' ) ] && 'yes' === $settings[ $this->get_control_id( 'show_read_more' ) ] && 'yes' !== $settings[ $this->get_control_id( 'masonry' ) ]; } protected function render_comments() { ?> <span class="elementor-post-avatar"> <?php comments_number(); ?> </span> <?php } protected function render_post() { $this->render_post_header(); $this->render_thumbnail(); $this->render_text_header(); $this->render_title(); $this->render_meta_data(); $this->render_excerpt(); $this->render_read_more(); $this->render_text_footer(); $this->render_post_footer(); } } skins/skin-classic.php 0000644 00000010741 14720516621 0010776 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Skins; use Elementor\Controls_Manager; use Elementor\Group_Control_Box_Shadow; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Skin_Classic extends Skin_Base { protected function _register_controls_actions() { parent::_register_controls_actions(); add_action( 'elementor/element/posts/classic_section_design_layout/after_section_end', [ $this, 'register_additional_design_controls' ] ); } public function get_id() { return 'classic'; } public function get_title() { return esc_html__( 'Classic', 'elementor-pro' ); } public function register_additional_design_controls() { $this->start_controls_section( 'section_design_box', [ 'label' => esc_html__( 'Box', 'elementor-pro' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'box_border_width', [ 'label' => esc_html__( 'Border Width', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'selectors' => [ '{{WRAPPER}} .elementor-post' => 'border-style: solid; border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}', ], ] ); $this->add_responsive_control( 'box_border_radius', [ 'label' => esc_html__( 'Border Radius', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ], 'range' => [ 'px' => [ 'max' => 200, ], 'em' => [ 'max' => 20, ], 'rem' => [ 'max' => 20, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post' => 'border-radius: {{SIZE}}{{UNIT}}', ], ] ); $this->add_responsive_control( 'box_padding', [ 'label' => esc_html__( 'Padding', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}', ], ] ); $this->add_responsive_control( 'content_padding', [ 'label' => esc_html__( 'Content Padding', 'elementor-pro' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ 'px' => [ 'max' => 50, ], 'em' => [ 'max' => 5, ], 'rem' => [ 'max' => 5, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-post__text' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}', ], 'separator' => 'after', ] ); $this->start_controls_tabs( 'bg_effects_tabs' ); $this->start_controls_tab( 'classic_style_normal', [ 'label' => esc_html__( 'Normal', 'elementor-pro' ), ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'box_shadow', 'selector' => '{{WRAPPER}} .elementor-post', ] ); $this->add_control( 'box_bg_color', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post' => 'background-color: {{VALUE}}', ], ] ); $this->add_control( 'box_border_color', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post' => 'border-color: {{VALUE}}', ], ] ); $this->end_controls_tab(); $this->start_controls_tab( 'classic_style_hover', [ 'label' => esc_html__( 'Hover', 'elementor-pro' ), ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'box_shadow_hover', 'selector' => '{{WRAPPER}} .elementor-post:hover', ] ); $this->add_control( 'box_bg_color_hover', [ 'label' => esc_html__( 'Background Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post:hover' => 'background-color: {{VALUE}}', ], ] ); $this->add_control( 'box_border_color_hover', [ 'label' => esc_html__( 'Border Color', 'elementor-pro' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .elementor-post:hover' => 'border-color: {{VALUE}}', ], ] ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->end_controls_section(); } } skins/skin-content-base.php 0000644 00000022675 14720516621 0011750 0 ustar 00 <?php namespace ElementorPro\Modules\Posts\Skins; use Elementor\Controls_Manager; use Elementor\Group_Control_Image_Size; use Elementor\Utils; use Elementor\Widget_Base; use ElementorPro\Modules\ThemeBuilder\Module as ThemeBuilder; use ElementorPro\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } trait Skin_Content_Base { protected function _register_controls_actions() { $widget_name = $this->parent->get_name(); add_action( 'elementor/element/' . $widget_name . '/section_layout/before_section_end', [ $this, 'register_skin_controls' ] ); if ( 'archive-posts' === $widget_name ) { add_action( 'elementor/element/archive-posts/section_layout/after_section_end', [ $this, 'register_style_sections' ] ); } else { add_action( 'elementor/element/posts/section_query/after_section_end', [ $this, 'register_style_sections' ] ); } } public function get_title() { return esc_html__( 'Full Content', 'elementor-pro' ); } public function register_skin_controls( Widget_Base $widget ) { $this->parent = $widget; $this->register_post_count_control(); $this->register_row_gap_control(); $this->register_thumbnail_controls(); $this->register_title_controls(); $this->register_meta_data_controls(); $this->register_link_controls(); } public function register_thumbnail_controls() { $this->add_control( 'thumbnail', [ 'label' => esc_html__( 'Show Thumbnail', 'elementor-pro' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'thumbnail', 'prefix_class' => 'elementor-posts--show-', 'separator' => 'before', ] ); $this->add_group_control( Group_Control_Image_Size::get_type(), [ 'name' => 'thumbnail_size', 'default' => 'medium', 'exclude' => [ 'custom' ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => '', ], 'prefix_class' => 'elementor-posts--thumbnail-size-', ] ); $this->add_responsive_control( 'item_ratio', [ 'label' => esc_html__( 'Image Ratio', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'default' => [ 'size' => 0.66, ], 'tablet_default' => [ 'size' => '', ], 'mobile_default' => [ 'size' => 0.5, ], 'range' => [ 'px' => [ 'min' => 0.1, 'max' => 2, 'step' => 0.01, ], ], 'selectors' => [ '{{WRAPPER}} .elementor-posts-container .elementor-post__thumbnail' => 'padding-bottom: calc( {{SIZE}} * 100% );', '{{WRAPPER}}:after' => 'content: "{{SIZE}}"; position: absolute; color: transparent;', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => '', ], ] ); $this->add_responsive_control( 'image_width', [ 'label' => esc_html__( 'Image Width', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ], 'range' => [ 'px' => [ 'max' => 600, ], 'em' => [ 'max' => 6, ], 'rem' => [ 'max' => 6, ], ], 'default' => [ 'size' => 100, 'unit' => '%', ], 'tablet_default' => [ 'size' => '', 'unit' => '%', ], 'mobile_default' => [ 'size' => 100, 'unit' => '%', ], 'selectors' => [ '{{WRAPPER}} .elementor-post__thumbnail__link' => 'width: {{SIZE}}{{UNIT}};', ], 'condition' => [ $this->get_control_id( 'thumbnail!' ) => '', ], ] ); } public function register_design_controls() { $this->register_additional_design_controls(); $this->register_design_image_controls(); $this->register_design_content_controls(); $this->update_image_spacing_control(); } public function register_row_gap_control() { $this->add_control( 'row_gap', [ 'label' => esc_html__( 'Rows Gap', 'elementor-pro' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px', 'em', 'rem', 'custom' ], 'default' => [ 'size' => 35, ], 'range' => [ 'px' => [ 'max' => 100, ], 'em' => [ 'max' => 10, ], 'rem' => [ 'max' => 10, ], ], 'frontend_available' => true, 'selectors' => [ '{{WRAPPER}} .elementor-posts-container article' => 'margin-bottom: {{SIZE}}{{UNIT}}', ], ] ); } // Update selectors for full content public function update_image_spacing_control() { $image_spacing_control = [ 'selectors' => [ '{{WRAPPER}} .elementor-posts--skin-full_content a.elementor-post__thumbnail__link' => 'margin-bottom: {{SIZE}}{{UNIT}}', '{{WRAPPER}} .elementor-posts--skin-archive_full_content a.elementor-post__thumbnail__link' => 'margin-bottom: {{SIZE}}{{UNIT}}', ], ]; $this->update_control( 'image_spacing', $image_spacing_control ); } protected function render_thumbnail() { $thumbnail = $this->get_instance_value( 'thumbnail' ); // In edit mode we render thumbnail to avoid server side rendering on each change. if ( empty( $thumbnail ) && ! Plugin::elementor()->editor->is_edit_mode() ) { return; } $settings = $this->parent->get_settings(); $setting_key = $this->get_control_id( 'thumbnail_size' ); $settings[ $setting_key ] = [ 'id' => get_post_thumbnail_id(), ]; $thumbnail_html = Group_Control_Image_Size::get_attachment_image_html( $settings, $setting_key ); if ( empty( $thumbnail_html ) ) { return; } $optional_attributes_html = $this->get_optional_link_attributes_html(); // PHPCS - `get_permalink` is safe. ?> <a class="elementor-post__thumbnail__link" href="<?php echo $this->current_permalink; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>" tabindex="-1" <?php Utils::print_unescaped_internal_string( $optional_attributes_html ); ?>> <div class="elementor-post__thumbnail"><?php echo wp_kses_post( $thumbnail_html ); ?></div> </a> <?php } /** * Render post content. * * @param boolean $with_wrapper - Whether to wrap the content with a div. * @param boolean $with_css - Decides whether to print inline CSS before the post content. * * @return void */ public function render_post_content( $with_wrapper = false, $with_css = true ) { static $did_posts = []; static $level = 0; $post = get_post(); if ( post_password_required( $post->ID ) ) { // PHPCS - `get_the_password_form`. is safe. echo get_the_password_form( $post->ID ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped return; } // Avoid recursion if ( isset( $did_posts[ $post->ID ] ) ) { return; } $level++; $did_posts[ $post->ID ] = true; // End avoid recursion $editor = Plugin::elementor()->editor; $is_edit_mode = $editor->is_edit_mode(); if ( Plugin::elementor()->preview->is_preview_mode( $post->ID ) ) { $content = Plugin::elementor()->preview->builder_wrapper( '' ); // XSS ok } else { /** * @var ThemeBuilder ThemeBuilder */ $document = ThemeBuilder::instance()->get_document( $post->ID ); // On view theme document show it's preview content. if ( $document ) { $preview_type = $document->get_settings( 'preview_type' ); $preview_id = $document->get_settings( 'preview_id' ); if ( 0 === strpos( $preview_type, 'single' ) && ! empty( $preview_id ) ) { $post = get_post( $preview_id ); if ( ! $post ) { $level--; return; } } } // Set edit mode as false, so don't render settings and etc. use the $is_edit_mode to indicate if we need the CSS inline $editor->set_edit_mode( false ); // Print manually (and don't use `the_content()`) because it's within another `the_content` filter, and the Elementor filter has been removed to avoid recursion. $content = Plugin::elementor()->frontend->get_builder_content( $post->ID, $with_css ); Plugin::elementor()->frontend->remove_content_filter(); if ( empty( $content ) ) { // Split to pages. setup_postdata( $post ); /** This filter is documented in wp-includes/post-template.php */ // PHPCS - `get_the_content` is safe. echo apply_filters( 'the_content', get_the_content() ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped wp_link_pages( [ 'before' => '<div class="page-links elementor-page-links"><span class="page-links-title elementor-page-links-title">' . esc_html__( 'Pages:', 'elementor-pro' ) . '</span>', 'after' => '</div>', 'link_before' => '<span>', 'link_after' => '</span>', 'pagelink' => '<span class="screen-reader-text">' . esc_html__( 'Page', 'elementor-pro' ) . ' </span>%', 'separator' => '<span class="screen-reader-text">, </span>', ] ); Plugin::elementor()->frontend->add_content_filter(); $level--; // Restore edit mode state Plugin::elementor()->editor->set_edit_mode( $is_edit_mode ); return; } else { Plugin::elementor()->frontend->remove_content_filters(); $content = apply_filters( 'the_content', $content ); Plugin::elementor()->frontend->restore_content_filters(); } } // End if(). // Restore edit mode state Plugin::elementor()->editor->set_edit_mode( $is_edit_mode ); if ( $with_wrapper ) { echo '<div class="elementor-post__content">' . balanceTags( $content, true ) . '</div>'; // XSS ok. } else { echo $content; // XSS ok. } $level--; if ( 0 === $level ) { $did_posts = []; } } protected function render_post() { $this->render_post_header(); $this->render_thumbnail(); $this->render_text_header(); $this->render_title(); $this->render_meta_data(); $this->render_post_content( true ); $this->render_text_footer(); $this->render_post_footer(); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка