'cat-post-widget', 'description' => __( 'List single category posts', 'category-posts' ), ); parent::__construct( WIDGET_BASE_ID, __( 'Category Posts', 'category-posts' ), $widget_ops ); } /** * Calculate the HTML for showing the thumb of a post item. * * Used as a filter for the thumb wordpress API to add css based stretching and cropping * when the image is not at the requested dimensions * * @param string $html The original HTML generated by the core APIS. * @param int $post_id the ID of the post of which the thumb is a featured image. * @param int $post_thumbnail_id The id of the featured image attachment. * @param string|array $size The requested size identified by name or (width, height) array. * @param mixed $attr ignored in this context. * @return string The HTML for the thumb related to the post * * @since 4.1 */ public function post_thumbnail_html( $html, $post_id, $post_thumbnail_id, $size, $attr ) { $use_css_cropping = isset( $this->instance['use_css_cropping'] ) && $this->instance['use_css_cropping']; $thumb = isset( $this->instance['template'] ) && preg_match( '/%thumb%/', $this->instance['template'] ); if ( ! ( $use_css_cropping && $thumb ) ) { return $html; } $meta = image_get_intermediate_size( $post_thumbnail_id, $size ); if ( empty( $meta ) ) { $post_img = wp_get_attachment_metadata( $post_thumbnail_id, $size ); $meta['file'] = basename( $post_img['file'] ); } $origfile = get_attached_file( $post_thumbnail_id, true ); // the location of the full file. $file = dirname( $origfile ) . '/' . $meta['file']; // the location of the file displayed as thumb. if ( file_exists( $file ) ) { list( $width, $height ) = getimagesize( $file ); // get actual size of the thumb file. if ( isset( $this->instance['use_css_cropping'] ) && $this->instance['use_css_cropping'] ) { $show_post_format = isset( $this->instance['show_post_format'] ) && ( 'none' !== $this->instance['show_post_format'] ); if ( $show_post_format || $this->instance['thumb_hover'] ) { $format = get_post_format() ? : 'standard'; $post_format_class = 'cat-post-format cat-post-format-' . $format; } $html = '' . $html . ''; } else { // use_css_cropping is not used. // wrap span. $html = '' . $html . ''; } } return $html; } /* * wrapper to execute the the_post_thumbnail with filters. */ /** * Calculate the HTML for showing the thumb of a post item. * * It is a wrapper to execute the the_post_thumbnail with filters * * @param string|array $size The requested size identified by name or (width, height) array. * * @return string The HTML for the thumb related to the post and empty string if it can not be calculated * * @since 4.1 */ public function the_post_thumbnail( $size = 'post-thumbnail' ) { if ( empty( $size ) ) { // if junk value, make it a normal thumb. $size = 'post-thumbnail'; } elseif ( is_array( $size ) && ( 2 === count( $size ) ) ) { // good format at least. // normalize to ints first. $size[0] = (int) $size[0]; $size[1] = (int) $size[1]; if ( ( 0 === $size[0] ) && ( 0 === $size[1] ) ) { // Both values zero then revert to thumbnail. $size = array( get_option( 'thumbnail_size_w', 150 ), get_option( 'thumbnail_size_h', 150 ) ); } elseif ( ( 0 === $size[0] ) && ( 0 !== $size[1] ) ) { // if thumb width 0 set to max/full widths for wp rendering $post_thumb = get_the_post_thumbnail( get_the_ID(), 'full' ); preg_match( '/(?<=width=")[\d]*/', $post_thumb, $thumb_full_w ); $size[0] = $thumb_full_w[0]; } elseif ( ( 0 !== $size[0] ) && ( 0 === $size[1] ) ) { // if thumb height 0 get full thumb for ratio and calc height with ratio $post_thumb = get_the_post_thumbnail( get_the_ID(), 'full' ); preg_match( '/(?<=width=")[\d]*/', $post_thumb, $thumb_full_w ); preg_match( '/(?<=height=")[\d]*/', $post_thumb, $thumb_full_h ); $ratio = $thumb_full_w[0] / $thumb_full_h[0]; $size[1] = intval( $size[0] / $ratio ); } } else { $size = array( get_option( 'thumbnail_size_w', 150 ), get_option( 'thumbnail_size_h', 150 ) ); // yet another form of junk. } $post_thumbnail_id = get_post_thumbnail_id( get_the_ID() ); if ( ! $post_thumbnail_id && $this->instance['default_thunmbnail'] ) { $post_thumbnail_id = $this->instance['default_thunmbnail']; } do_action( 'begin_fetch_post_thumbnail_html', get_the_ID(), $post_thumbnail_id, $size ); $html = wp_get_attachment_image( $post_thumbnail_id, $size, false, '' ); if ( ! $html ) { $ret = ''; } else { $ret = $this->post_thumbnail_html( $html, get_the_ID(), $post_thumbnail_id, $size, '' ); } do_action( 'end_fetch_post_thumbnail_html', get_the_ID(), $post_thumbnail_id, $size ); return $ret; } /** * Excerpt more link filter * * @param string $more The "more" text passed by the filter. * * @return string The link to the post with the "more" text configured in the widget. */ public function excerpt_more_filter( $more ) { return ' ' . esc_html( $this->instance['excerpt_more_text'] ) . ''; } /** * Apply the_content filter for excerpt * This should show sharing buttons which comes with other widgets in the widget output in the same way as on the main content * * @param string $text The HTML with other applied excerpt filters. * * @return string If option hide_social_buttons is unchecked applay the_content filter. * * @since 4.6 */ public function apply_the_excerpt( $text ) { $ret = apply_filters( 'the_content', $text ); return $ret; } /** * Calculate the wp-query arguments matching the filter settings of the widget * * @param array $instance Array which contains the various settings. * @return array The array that can be fed to wp_Query to get the relevant posts * * @since 4.6 */ public function queryArgs( $instance ) { $valid_sort_orders = array( 'date', 'title', 'comment_count', 'rand' ); if ( isset( $instance['sort_by'] ) && in_array( $instance['sort_by'], $valid_sort_orders, true ) ) { $sort_by = $instance['sort_by']; } else { $sort_by = 'date'; } $sort_order = ( isset( $instance['asc_sort_order'] ) && $instance['asc_sort_order'] ) ? 'ASC' : 'DESC'; // Get array of post info. $args = array( 'orderby' => $sort_by, 'order' => $sort_order, 'ignore_sticky_posts' => 1, // Make sure we do not get stickies out of order. 'no_found_rows' => true, // Do not count the total numbers of rows by default. ); $non_default_valid_status = array( 'publish', 'future', 'publish,future', 'private', 'private,publish', 'private,publish,future', ); if ( isset( $instance['status'] ) && in_array( $instance['status'], $non_default_valid_status, true ) ) { $args['post_status'] = $instance['status']; } if ( isset( $instance['num'] ) ) { $args['showposts'] = (int) $instance['num']; } if ( isset( $instance['offset'] ) && ( (int) $instance['offset'] > 1 ) ) { $args['offset'] = (int) $instance['offset'] - 1; } if ( isset( $instance['cat'] ) ) { if ( isset( $instance['no_cat_childs'] ) && $instance['no_cat_childs'] ) { $args['category__in'] = (int) $instance['cat']; } else { $args['cat'] = (int) $instance['cat']; } } if ( is_singular() && isset( $instance['exclude_current_post'] ) && $instance['exclude_current_post'] ) { $args['post__not_in'] = array( get_the_ID() ); } if ( isset( $instance['hideNoThumb'] ) && $instance['hideNoThumb'] ) { $args = array_merge( $args, array( 'meta_query' => array( array( 'key' => '_thumbnail_id', 'compare' => 'EXISTS', ), ), ) ); } switch ( $instance['date_range'] ) { case 'days_ago': $ago = (int) $instance['days_ago']; // If there is no valid integer value given, bail. if ( 0 === $ago ) { break; } $date = date( 'Y-m-d', strtotime( '-' . $ago . ' days' ) ); $args['date_query'] = array( 'after' => $date, 'inclusive' => true, ); break; case 'between_dates': // Validation note - not doing any, assuming the query will // fail gracefully enough for now as it is not clear what Should // the validation be right now. $start_date = $instance['start_date']; $end_date = $instance['end_date']; $args['date_query'] = array( 'after' => $start_date, 'before' => $end_date, 'inclusive' => true, ); break; } return $args; } /** * Calculate the HTML of the title based on the widget settings * * @param string $before_title The sidebar configured HTML that should come * before the title itself. * @param string $after_title The sidebar configured HTML that should come * after the title itself. * @param array $instance Array which contains the various settings. * @return string The HTML for the title area * * @since 4.6 */ public function titleHTML( $before_title, $after_title, $instance ) { $ret = ''; // If no title, use the name of the category. if ( ! isset( $instance['title'] ) || ! $instance['title'] ) { $instance['title'] = ''; if ( 0 !== (int) $instance['cat'] ) { $category_info = get_category( $instance['cat'] ); if ( $category_info && ! is_wp_error( $category_info ) ) { $instance['title'] = $category_info->name; } else { $instance['cat'] = 0; // For further processing treat it like "all categories". $instance['title'] = __( 'Recent Posts', 'category-posts' ); } } else { $instance['title'] = __( 'Recent Posts', 'category-posts' ); } } if ( ! ( isset( $instance['hide_title'] ) && $instance['hide_title'] ) ) { $ret = $before_title; if ( isset( $instance['is_shortcode'] ) ) { $title = esc_html( $instance['title'] ); } else { $title = apply_filters( 'widget_title', $instance['title'] ); } if ( isset( $instance['title_link'] ) && $instance['title_link'] ) { if ( 0 !== $instance['cat'] ) { $ret .= '' . $title . ''; } elseif ( isset( $instance['title_link_url'] ) && $instance['title_link_url'] ) { $ret .= '' . $title . ''; } else { $ret .= '' . $title . ''; } } else { $ret .= $title; } $ret .= $after_title; } return $ret; } /** * Get the URL of the blog page or home page if no explicit blog page is defined. * * @return string The URL of the blog page * * @since 4.8 */ private function blog_page_url() { $blog_page = get_option( 'page_for_posts' ); if ( $blog_page ) { $url = get_permalink( $blog_page ); } else { $url = home_url(); } return $url; } /** * Calculate the HTML of the load more button based on the widget settings * * @param array $instance Array which contains the various settings. * * @return string The HTML for the load more area * * @since 4.9 */ public function loadMoreHTML( $instance ) { if ( ! $instance['enable_loadmore'] ) { return ''; } $ret = '
get_checkbox_block_html( $instance, 'no_cat_childs', esc_html__( 'Exclude child categories', 'category-posts' ), ! empty( $instance['cat'] ) ); echo $this->get_select_block_html( $instance, 'status', esc_html__( 'Status', 'category-posts' ), array( 'default' => esc_html__( 'WordPress Default', 'category-posts' ), 'publish' => esc_html__( 'Published', 'category-posts' ), 'future' => esc_html__( 'Scheduled', 'category-posts' ), 'private' => esc_html__( 'Private', 'category-posts' ), 'publish,future' => esc_html__( 'Published or Scheduled', 'category-posts' ), 'private,publish' => esc_html__( 'Published or Private', 'category-posts' ), 'private,future' => esc_html__( 'Private or Scheduled', 'category-posts' ), 'private,publish,future' => esc_html__( 'Published, Private or Scheduled', 'category-posts' ), ), 'default', true ); echo $this->get_number_input_block_html( $instance, 'num', esc_html__( 'Number of posts to show', 'category-posts' ), 1, '', '', true ); echo $this->get_number_input_block_html( $instance, 'offset', esc_html__( 'Start with post', 'category-posts' ), 1, '', '', true ); echo $this->get_select_block_html( $instance, 'date_range', esc_html__( 'Date Range', 'category-posts' ), array( 'off' => esc_html__( 'Off', 'category-posts' ), 'days_ago' => esc_html__( 'Days ago', 'category-posts' ), 'between_dates' => esc_html__( 'Between dates', 'category-posts' ), ), 'off', true ); ?>