Display Posts Shortcode - Version 2.5

Version Description

Download this release

Release Info

Developer billerickson
Plugin Icon 128x128 Display Posts Shortcode
Version 2.5
Comparing to
See all releases

Code changes from version 2.4 to 2.5

Files changed (2) hide show
  1. display-posts-shortcode.php +367 -58
  2. readme.txt +10 -2
display-posts-shortcode.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Display Posts Shortcode
4
  * Plugin URI: http://www.billerickson.net/shortcode-to-display-posts/
5
  * Description: Display a listing of posts using the [display-posts] shortcode
6
- * Version: 2.4
7
  * Author: Bill Erickson
8
  * Author URI: http://www.billerickson.net
9
  *
@@ -15,7 +15,7 @@
15
  * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
  *
17
  * @package Display Posts
18
- * @version 2.4
19
  * @author Bill Erickson <bill@billerickson.net>
20
  * @copyright Copyright (c) 2011, Bill Erickson
21
  * @link http://www.billerickson.net/shortcode-to-display-posts/
@@ -26,6 +26,9 @@
26
  /**
27
  * To Customize, use the following filters:
28
  *
 
 
 
29
  * `display_posts_shortcode_args`
30
  * For customizing the $args passed to WP_Query
31
  *
@@ -52,7 +55,16 @@ function be_display_posts_shortcode( $atts ) {
52
  'title' => '',
53
  'author' => '',
54
  'category' => '',
 
 
55
  'date_format' => '(n/j/Y)',
 
 
 
 
 
 
 
56
  'display_posts_off' => false,
57
  'exclude_current' => false,
58
  'id' => false,
@@ -77,6 +89,7 @@ function be_display_posts_shortcode( $atts ) {
77
  'tax_operator' => 'IN',
78
  'tax_term' => false,
79
  'taxonomy' => false,
 
80
  'wrapper' => 'ul',
81
  'wrapper_class' => 'display-posts-listing',
82
  'wrapper_id' => false,
@@ -86,42 +99,52 @@ function be_display_posts_shortcode( $atts ) {
86
  if( $atts['display_posts_off'] )
87
  return;
88
 
89
- $shortcode_title = sanitize_text_field( $atts['title'] );
90
- $author = sanitize_text_field( $atts['author'] );
91
- $category = sanitize_text_field( $atts['category'] );
92
- $date_format = sanitize_text_field( $atts['date_format'] );
93
- $exclude_current = be_display_posts_bool( $atts['exclude_current'] );
94
- $id = $atts['id']; // Sanitized later as an array of integers
95
- $ignore_sticky_posts = be_display_posts_bool( $atts['ignore_sticky_posts'] );
96
- $image_size = sanitize_key( $atts['image_size'] );
97
- $include_title = be_display_posts_bool( $atts['include_title'] );
98
- $include_author = be_display_posts_bool( $atts['include_author'] );
99
- $include_content = be_display_posts_bool( $atts['include_content'] );
100
- $include_date = be_display_posts_bool( $atts['include_date'] );
101
- $include_excerpt = be_display_posts_bool( $atts['include_excerpt'] );
102
- $meta_key = sanitize_text_field( $atts['meta_key'] );
103
- $meta_value = sanitize_text_field( $atts['meta_value'] );
104
- $no_posts_message = sanitize_text_field( $atts['no_posts_message'] );
105
- $offset = intval( $atts['offset'] );
106
- $order = sanitize_key( $atts['order'] );
107
- $orderby = sanitize_key( $atts['orderby'] );
108
- $post_parent = $atts['post_parent']; // Validated later, after check for 'current'
109
- $post_status = $atts['post_status']; // Validated later as one of a few values
110
- $post_type = sanitize_text_field( $atts['post_type'] );
111
- $posts_per_page = intval( $atts['posts_per_page'] );
112
- $tag = sanitize_text_field( $atts['tag'] );
113
- $tax_operator = $atts['tax_operator']; // Validated later as one of a few values
114
- $tax_term = sanitize_text_field( $atts['tax_term'] );
115
- $taxonomy = sanitize_key( $atts['taxonomy'] );
116
- $wrapper = sanitize_text_field( $atts['wrapper'] );
117
- $wrapper_class = sanitize_html_class( $atts['wrapper_class'] );
 
 
 
 
 
 
 
 
 
 
 
118
  if( !empty( $wrapper_class ) )
119
  $wrapper_class = ' class="' . $wrapper_class . '"';
120
  $wrapper_id = sanitize_html_class( $atts['wrapper_id'] );
121
  if( !empty( $wrapper_id ) )
122
  $wrapper_id = ' id="' . $wrapper_id . '"';
123
-
124
-
125
  // Set up initial query for post
126
  $args = array(
127
  'category_name' => $category,
@@ -131,7 +154,87 @@ function be_display_posts_shortcode( $atts ) {
131
  'posts_per_page' => $posts_per_page,
132
  'tag' => $tag,
133
  );
134
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  // Ignore Sticky Posts
136
  if( $ignore_sticky_posts )
137
  $args['ignore_sticky_posts'] = true;
@@ -151,7 +254,7 @@ function be_display_posts_shortcode( $atts ) {
151
  }
152
 
153
  // If Exclude Current
154
- if( $exclude_current )
155
  $args['post__not_in'] = array( get_the_ID() );
156
 
157
  // Post Author
@@ -176,8 +279,17 @@ function be_display_posts_shortcode( $atts ) {
176
  // If taxonomy attributes, create a taxonomy query
177
  if ( !empty( $taxonomy ) && !empty( $tax_term ) ) {
178
 
179
- // Term string to array
180
- $tax_term = explode( ', ', $tax_term );
 
 
 
 
 
 
 
 
 
181
 
182
  // Validate operator
183
  if( !in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) )
@@ -231,7 +343,7 @@ function be_display_posts_shortcode( $atts ) {
231
  }
232
 
233
  // If post parent attribute, set up parent
234
- if( $post_parent ) {
235
  if( 'current' == $post_parent ) {
236
  global $post;
237
  $post_parent = get_the_ID();
@@ -246,19 +358,36 @@ function be_display_posts_shortcode( $atts ) {
246
  $wrapper = 'ul';
247
  $inner_wrapper = 'div' == $wrapper ? 'div' : 'li';
248
 
249
-
 
 
 
 
 
 
 
250
  $listing = new WP_Query( apply_filters( 'display_posts_shortcode_args', $args, $original_atts ) );
251
- if ( ! $listing->have_posts() )
 
 
 
 
 
 
 
252
  return apply_filters( 'display_posts_shortcode_no_results', wpautop( $no_posts_message ) );
 
253
 
254
  $inner = '';
255
  while ( $listing->have_posts() ): $listing->the_post(); global $post;
256
 
257
  $image = $date = $author = $excerpt = $content = '';
258
 
259
- if ( $include_title )
 
260
  $title = '<a class="title" href="' . apply_filters( 'the_permalink', get_permalink() ) . '">' . get_the_title() . '</a>';
261
-
 
262
  if ( $image_size && has_post_thumbnail() )
263
  $image = '<a class="image" href="' . get_permalink() . '">' . get_the_post_thumbnail( get_the_ID(), $image_size ) . '</a> ';
264
 
@@ -266,36 +395,118 @@ function be_display_posts_shortcode( $atts ) {
266
  $date = ' <span class="date">' . get_the_date( $date_format ) . '</span>';
267
 
268
  if( $include_author )
 
 
 
 
 
 
 
269
  $author = apply_filters( 'display_posts_shortcode_author', ' <span class="author">by ' . get_the_author() . '</span>' );
270
 
271
  if ( $include_excerpt )
272
- $excerpt = ' <span class="excerpt-dash">-</span> <span class="excerpt">' . get_the_excerpt() . '</span>';
273
 
274
  if( $include_content ) {
275
  add_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
276
- $content = '<div class="content">' . apply_filters( 'the_content', get_the_content() ) . '</div>';
 
277
  remove_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
278
  }
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  $class = array( 'listing-item' );
281
- $class = sanitize_html_class( apply_filters( 'display_posts_shortcode_post_class', $class, $post, $listing, $original_atts ) );
282
- $output = '<' . $inner_wrapper . ' class="' . implode( ' ', $class ) . '">' . $image . $title . $date . $author . $excerpt . $content . '</' . $inner_wrapper . '>';
 
 
 
 
 
 
 
 
 
 
 
283
 
284
  // If post is set to private, only show to logged in users
285
  if( 'private' == get_post_status( get_the_ID() ) && !current_user_can( 'read_private_posts' ) )
286
  $output = '';
287
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  $inner .= apply_filters( 'display_posts_shortcode_output', $output, $original_atts, $image, $title, $date, $excerpt, $inner_wrapper, $content, $class );
289
 
290
  endwhile; wp_reset_postdata();
291
-
 
 
 
 
 
 
 
 
292
  $open = apply_filters( 'display_posts_shortcode_wrapper_open', '<' . $wrapper . $wrapper_class . $wrapper_id . '>', $original_atts );
 
 
 
 
 
 
 
 
 
293
  $close = apply_filters( 'display_posts_shortcode_wrapper_close', '</' . $wrapper . '>', $original_atts );
294
 
295
  $return = $open;
296
 
297
  if( $shortcode_title ) {
298
 
 
 
 
 
 
 
 
 
299
  $title_tag = apply_filters( 'display_posts_shortcode_title_tag', 'h2', $original_atts );
300
 
301
  $return .= '<' . $title_tag . ' class="display-posts-title">' . $shortcode_title . '</' . $title_tag . '>' . "\n";
@@ -306,6 +517,103 @@ function be_display_posts_shortcode( $atts ) {
306
  return $return;
307
  }
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  /**
310
  * Turn off display posts shortcode
311
  * If display full post content, any uses of [display-posts] are disabled
@@ -316,15 +624,16 @@ function be_display_posts_shortcode( $atts ) {
316
  * @return array $out
317
  */
318
  function be_display_posts_off( $out, $pairs, $atts ) {
319
- $out['display_posts_off'] = true;
 
 
 
 
 
 
 
 
 
 
320
  return $out;
321
  }
322
-
323
- /**
324
- * Convert string to boolean
325
- * because (bool) "false" == true
326
- *
327
- */
328
- function be_display_posts_bool( $value ) {
329
- return !empty( $value ) && 'true' == $value ? true : false;
330
- }
3
  * Plugin Name: Display Posts Shortcode
4
  * Plugin URI: http://www.billerickson.net/shortcode-to-display-posts/
5
  * Description: Display a listing of posts using the [display-posts] shortcode
6
+ * Version: 2.5
7
  * Author: Bill Erickson
8
  * Author URI: http://www.billerickson.net
9
  *
15
  * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
  *
17
  * @package Display Posts
18
+ * @version 2.5
19
  * @author Bill Erickson <bill@billerickson.net>
20
  * @copyright Copyright (c) 2011, Bill Erickson
21
  * @link http://www.billerickson.net/shortcode-to-display-posts/
26
  /**
27
  * To Customize, use the following filters:
28
  *
29
+ * `shortcode_atts_display-posts`
30
+ * For customizing the default shortode arguments
31
+ *
32
  * `display_posts_shortcode_args`
33
  * For customizing the $args passed to WP_Query
34
  *
55
  'title' => '',
56
  'author' => '',
57
  'category' => '',
58
+ 'category_display' => '',
59
+ 'category_label' => 'Posted in: ',
60
  'date_format' => '(n/j/Y)',
61
+ 'date' => '',
62
+ 'date_column' => 'post_date',
63
+ 'date_compare' => '=',
64
+ 'date_query_before' => '',
65
+ 'date_query_after' => '',
66
+ 'date_query_column' => '',
67
+ 'date_query_compare' => '',
68
  'display_posts_off' => false,
69
  'exclude_current' => false,
70
  'id' => false,
89
  'tax_operator' => 'IN',
90
  'tax_term' => false,
91
  'taxonomy' => false,
92
+ 'time' => '',
93
  'wrapper' => 'ul',
94
  'wrapper_class' => 'display-posts-listing',
95
  'wrapper_id' => false,
99
  if( $atts['display_posts_off'] )
100
  return;
101
 
102
+ $shortcode_title = sanitize_text_field( $atts['title'] );
103
+ $author = sanitize_text_field( $atts['author'] );
104
+ $category = sanitize_text_field( $atts['category'] );
105
+ $category_display = 'true' == $atts['category_display'] ? 'category' : sanitize_text_field( $atts['category_display'] );
106
+ $category_label = sanitize_text_field( $atts['category_label'] );
107
+ $date_format = sanitize_text_field( $atts['date_format'] );
108
+ $date = sanitize_text_field( $atts['date'] );
109
+ $date_column = sanitize_text_field( $atts['date_column'] );
110
+ $date_compare = sanitize_text_field( $atts['date_compare'] );
111
+ $date_query_before = sanitize_text_field( $atts['date_query_before'] );
112
+ $date_query_after = sanitize_text_field( $atts['date_query_after'] );
113
+ $date_query_column = sanitize_text_field( $atts['date_query_column'] );
114
+ $date_query_compare = sanitize_text_field( $atts['date_query_compare'] );
115
+ $exclude_current = filter_var( $atts['exclude_current'], FILTER_VALIDATE_BOOLEAN );
116
+ $id = $atts['id']; // Sanitized later as an array of integers
117
+ $ignore_sticky_posts = filter_var( $atts['ignore_sticky_posts'], FILTER_VALIDATE_BOOLEAN );
118
+ $image_size = sanitize_key( $atts['image_size'] );
119
+ $include_title = filter_var( $atts['include_title'], FILTER_VALIDATE_BOOLEAN );
120
+ $include_author = filter_var( $atts['include_author'], FILTER_VALIDATE_BOOLEAN );
121
+ $include_content = filter_var( $atts['include_content'], FILTER_VALIDATE_BOOLEAN );
122
+ $include_date = filter_var( $atts['include_date'], FILTER_VALIDATE_BOOLEAN );
123
+ $include_excerpt = filter_var( $atts['include_excerpt'], FILTER_VALIDATE_BOOLEAN );
124
+ $meta_key = sanitize_text_field( $atts['meta_key'] );
125
+ $meta_value = sanitize_text_field( $atts['meta_value'] );
126
+ $no_posts_message = sanitize_text_field( $atts['no_posts_message'] );
127
+ $offset = intval( $atts['offset'] );
128
+ $order = sanitize_key( $atts['order'] );
129
+ $orderby = sanitize_key( $atts['orderby'] );
130
+ $post_parent = $atts['post_parent']; // Validated later, after check for 'current'
131
+ $post_status = $atts['post_status']; // Validated later as one of a few values
132
+ $post_type = sanitize_text_field( $atts['post_type'] );
133
+ $posts_per_page = intval( $atts['posts_per_page'] );
134
+ $tag = sanitize_text_field( $atts['tag'] );
135
+ $tax_operator = $atts['tax_operator']; // Validated later as one of a few values
136
+ $tax_term = sanitize_text_field( $atts['tax_term'] );
137
+ $taxonomy = sanitize_key( $atts['taxonomy'] );
138
+ $time = sanitize_text_field( $atts['time'] );
139
+ $wrapper = sanitize_text_field( $atts['wrapper'] );
140
+ $wrapper_class = sanitize_html_class( $atts['wrapper_class'] );
141
+
142
  if( !empty( $wrapper_class ) )
143
  $wrapper_class = ' class="' . $wrapper_class . '"';
144
  $wrapper_id = sanitize_html_class( $atts['wrapper_id'] );
145
  if( !empty( $wrapper_id ) )
146
  $wrapper_id = ' id="' . $wrapper_id . '"';
147
+
 
148
  // Set up initial query for post
149
  $args = array(
150
  'category_name' => $category,
154
  'posts_per_page' => $posts_per_page,
155
  'tag' => $tag,
156
  );
157
+
158
+ // Date query.
159
+ if ( ! empty( $date ) || ! empty( $time ) || ! empty( $date_query_after ) || ! empty( $date_query_before ) ) {
160
+ $initial_date_query = $date_query_top_lvl = array();
161
+
162
+ $valid_date_columns = array(
163
+ 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt',
164
+ 'comment_date', 'comment_date_gmt'
165
+ );
166
+
167
+ $valid_compare_ops = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' );
168
+
169
+ // Sanitize and add date segments.
170
+ $dates = be_sanitize_date_time( $date );
171
+ if ( ! empty( $dates ) ) {
172
+ if ( is_string( $dates ) ) {
173
+ $timestamp = strtotime( $dates );
174
+ $dates = array(
175
+ 'year' => date( 'Y', $timestamp ),
176
+ 'month' => date( 'm', $timestamp ),
177
+ 'day' => date( 'd', $timestamp ),
178
+ );
179
+ }
180
+ foreach ( $dates as $arg => $segment ) {
181
+ $initial_date_query[ $arg ] = $segment;
182
+ }
183
+ }
184
+
185
+ // Sanitize and add time segments.
186
+ $times = be_sanitize_date_time( $time, 'time' );
187
+ if ( ! empty( $times ) ) {
188
+ foreach ( $times as $arg => $segment ) {
189
+ $initial_date_query[ $arg ] = $segment;
190
+ }
191
+ }
192
+
193
+ // Date query 'before' argument.
194
+ $before = be_sanitize_date_time( $date_query_before, 'date', true );
195
+ if ( ! empty( $before ) ) {
196
+ $initial_date_query['before'] = $before;
197
+ }
198
+
199
+ // Date query 'after' argument.
200
+ $after = be_sanitize_date_time( $date_query_after, 'date', true );
201
+ if ( ! empty( $after ) ) {
202
+ $initial_date_query['after'] = $after;
203
+ }
204
+
205
+ // Date query 'column' argument.
206
+ if ( ! empty( $date_query_column ) && in_array( $date_query_column, $valid_date_columns ) ) {
207
+ $initial_date_query['column'] = $date_query_column;
208
+ }
209
+
210
+ // Date query 'compare' argument.
211
+ if ( ! empty( $date_query_compare ) && in_array( $date_query_compare, $valid_compare_ops ) ) {
212
+ $initial_date_query['compare'] = $date_query_compare;
213
+ }
214
+
215
+ //
216
+ // Top-level date_query arguments. Only valid arguments will be added.
217
+ //
218
+
219
+ // 'column' argument.
220
+ if ( ! empty( $date_column ) && in_array( $date_column, $valid_date_columns ) ) {
221
+ $date_query_top_lvl['column'] = $date_column;
222
+ }
223
+
224
+ // 'compare' argument.
225
+ if ( ! empty( $date_compare ) && in_array( $date_compare, $valid_compare_ops ) ) {
226
+ $date_query_top_lvl['compare'] = $date_compare;
227
+ }
228
+
229
+ // Bring in the initial date query.
230
+ if ( ! empty( $initial_date_query ) ) {
231
+ $date_query_top_lvl[] = $initial_date_query;
232
+ }
233
+
234
+ // Date queries.
235
+ $args['date_query'] = $date_query_top_lvl;
236
+ }
237
+
238
  // Ignore Sticky Posts
239
  if( $ignore_sticky_posts )
240
  $args['ignore_sticky_posts'] = true;
254
  }
255
 
256
  // If Exclude Current
257
+ if( is_singular() && $exclude_current )
258
  $args['post__not_in'] = array( get_the_ID() );
259
 
260
  // Post Author
279
  // If taxonomy attributes, create a taxonomy query
280
  if ( !empty( $taxonomy ) && !empty( $tax_term ) ) {
281
 
282
+ if( 'current' == $tax_term ) {
283
+ global $post;
284
+ $terms = wp_get_post_terms(get_the_ID(), $taxonomy);
285
+ $tax_term = array();
286
+ foreach ($terms as $term) {
287
+ $tax_term[] = $term->slug;
288
+ }
289
+ }else{
290
+ // Term string to array
291
+ $tax_term = explode( ', ', $tax_term );
292
+ }
293
 
294
  // Validate operator
295
  if( !in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) )
343
  }
344
 
345
  // If post parent attribute, set up parent
346
+ if( $post_parent !== false ) {
347
  if( 'current' == $post_parent ) {
348
  global $post;
349
  $post_parent = get_the_ID();
358
  $wrapper = 'ul';
359
  $inner_wrapper = 'div' == $wrapper ? 'div' : 'li';
360
 
361
+ /**
362
+ * Filter the arguments passed to WP_Query.
363
+ *
364
+ * @since 1.7
365
+ *
366
+ * @param array $args Parsed arguments to pass to WP_Query.
367
+ * @param array $original_atts Original attributes passed to the shortcode.
368
+ */
369
  $listing = new WP_Query( apply_filters( 'display_posts_shortcode_args', $args, $original_atts ) );
370
+ if ( ! $listing->have_posts() ) {
371
+ /**
372
+ * Filter content to display if no posts match the current query.
373
+ *
374
+ * @since 1.8
375
+ *
376
+ * @param string $no_posts_message Content to display, returned via {@see wpautop()}.
377
+ */
378
  return apply_filters( 'display_posts_shortcode_no_results', wpautop( $no_posts_message ) );
379
+ }
380
 
381
  $inner = '';
382
  while ( $listing->have_posts() ): $listing->the_post(); global $post;
383
 
384
  $image = $date = $author = $excerpt = $content = '';
385
 
386
+ if ( $include_title ) {
387
+ /** This filter is documented in wp-includes/link-template.php */
388
  $title = '<a class="title" href="' . apply_filters( 'the_permalink', get_permalink() ) . '">' . get_the_title() . '</a>';
389
+ }
390
+
391
  if ( $image_size && has_post_thumbnail() )
392
  $image = '<a class="image" href="' . get_permalink() . '">' . get_the_post_thumbnail( get_the_ID(), $image_size ) . '</a> ';
393
 
395
  $date = ' <span class="date">' . get_the_date( $date_format ) . '</span>';
396
 
397
  if( $include_author )
398
+ /**
399
+ * Filter the HTML markup to display author information for the current post.
400
+ *
401
+ * @since Unknown
402
+ *
403
+ * @param string $author_output HTML markup to display author information.
404
+ */
405
  $author = apply_filters( 'display_posts_shortcode_author', ' <span class="author">by ' . get_the_author() . '</span>' );
406
 
407
  if ( $include_excerpt )
408
+ $excerpt = ' <span class="excerpt-dash">-</span> <span class="excerpt">' . wp_trim_excerpt() . '</span>';
409
 
410
  if( $include_content ) {
411
  add_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
412
+ /** This filter is documented in wp-includes/post-template.php */
413
+ $content = '<div class="content">' . apply_filters( 'the_content', get_the_content() ) . '</div>';
414
  remove_filter( 'shortcode_atts_display-posts', 'be_display_posts_off', 10, 3 );
415
  }
416
 
417
+ // Display categories the post is in
418
+ $category_display_text = '';
419
+ if( $category_display && is_object_in_taxonomy( get_post_type(), $category_display ) ) {
420
+ $terms = get_the_terms( get_the_ID(), $category_display );
421
+ $term_output = array();
422
+ foreach( $terms as $term )
423
+ $term_output[] = '<a href="' . get_term_link( $term, $category_display ) . '">' . $term->name . '</a>';
424
+ $category_display_text = ' <span class="category-display"><span class="category-display-label">' . $category_label . '</span> ' . implode( ', ', $term_output ) . '</span>';
425
+
426
+ /**
427
+ * Filter the list of categories attached to the current post.
428
+ *
429
+ * @since 2.4.2
430
+ *
431
+ * @param string $category_display Current Category Display text
432
+ */
433
+ $category_display_text = apply_filters( 'display_posts_shortcode_category_display', $category_display_text );
434
+
435
+ // If they pass a taxonomy that doesn't exist on this post type
436
+ }elseif( $category_display ) {
437
+ $category_display = '';
438
+ }
439
+
440
  $class = array( 'listing-item' );
441
+
442
+ /**
443
+ * Filter the post classes for the inner wrapper element of the current post.
444
+ *
445
+ * @since 2.2
446
+ *
447
+ * @param array $class Post classes.
448
+ * @param WP_Post $post Post object.
449
+ * @param WP_Query $listing WP_Query object for the posts listing.
450
+ * @param array $original_atts Original attributes passed to the shortcode.
451
+ */
452
+ $class = array_map( 'sanitize_html_class', apply_filters( 'display_posts_shortcode_post_class', $class, $post, $listing, $original_atts ) );
453
+ $output = '<' . $inner_wrapper . ' class="' . implode( ' ', $class ) . '">' . $image . $title . $date . $author . $category_display_text . $excerpt . $content . '</' . $inner_wrapper . '>';
454
 
455
  // If post is set to private, only show to logged in users
456
  if( 'private' == get_post_status( get_the_ID() ) && !current_user_can( 'read_private_posts' ) )
457
  $output = '';
458
+
459
+ /**
460
+ * Filter the HTML markup for output via the shortcode.
461
+ *
462
+ * @since 0.1.5
463
+ *
464
+ * @param string $output The shortcode's HTML output.
465
+ * @param array $original_atts Original attributes passed to the shortcode.
466
+ * @param string $image HTML markup for the post's featured image element.
467
+ * @param string $title HTML markup for the post's title element.
468
+ * @param string $date HTML markup for the post's date element.
469
+ * @param string $excerpt HTML markup for the post's excerpt element.
470
+ * @param string $inner_wrapper Type of container to use for the post's inner wrapper element.
471
+ * @param string $content The post's content.
472
+ * @param string $class Space-separated list of post classes to supply to the $inner_wrapper element.
473
+ */
474
  $inner .= apply_filters( 'display_posts_shortcode_output', $output, $original_atts, $image, $title, $date, $excerpt, $inner_wrapper, $content, $class );
475
 
476
  endwhile; wp_reset_postdata();
477
+
478
+ /**
479
+ * Filter the shortcode output's opening outer wrapper element.
480
+ *
481
+ * @since 1.7
482
+ *
483
+ * @param string $wrapper_open HTML markup for the opening outer wrapper element.
484
+ * @param array $original_atts Original attributes passed to the shortcode.
485
+ */
486
  $open = apply_filters( 'display_posts_shortcode_wrapper_open', '<' . $wrapper . $wrapper_class . $wrapper_id . '>', $original_atts );
487
+
488
+ /**
489
+ * Filter the shortcode output's closing outer wrapper element.
490
+ *
491
+ * @since 1.7
492
+ *
493
+ * @param string $wrapper_close HTML markup for the closing outer wrapper element.
494
+ * @param array $original_atts Original attributes passed to the shortcode.
495
+ */
496
  $close = apply_filters( 'display_posts_shortcode_wrapper_close', '</' . $wrapper . '>', $original_atts );
497
 
498
  $return = $open;
499
 
500
  if( $shortcode_title ) {
501
 
502
+ /**
503
+ * Filter the shortcode output title tag element.
504
+ *
505
+ * @since 2.3
506
+ *
507
+ * @param string $tag Type of element to use for the output title tag. Default 'h2'.
508
+ * @param array $original_atts Original attributes passed to the shortcode.
509
+ */
510
  $title_tag = apply_filters( 'display_posts_shortcode_title_tag', 'h2', $original_atts );
511
 
512
  $return .= '<' . $title_tag . ' class="display-posts-title">' . $shortcode_title . '</' . $title_tag . '>' . "\n";
517
  return $return;
518
  }
519
 
520
+ /**
521
+ * Sanitize the segments of a given date or time for a date query.
522
+ *
523
+ * Accepts times entered in the 'HH:MM:SS' or 'HH:MM' formats, and dates
524
+ * entered in the 'YYYY-MM-DD' format.
525
+ *
526
+ * @param string $date_time Date or time string to sanitize the parts of.
527
+ * @param string $type Optional. Type of value to sanitize. Accepts
528
+ * 'date' or 'time'. Default 'date'.
529
+ * @param bool $accepts_string Optional. Whether the return value accepts a string.
530
+ * Default false.
531
+ * @return array|string Array of valid date or time segments, a timestamp, otherwise
532
+ * an empty array.
533
+ */
534
+ function be_sanitize_date_time( $date_time, $type = 'date', $accepts_string = false ) {
535
+ if ( empty( $date_time ) || ! in_array( $type, array( 'date', 'time' ) ) ) {
536
+ return array();
537
+ }
538
+
539
+ $segments = array();
540
+
541
+ /*
542
+ * If $date_time is not a strictly-formatted date or time, attempt to salvage it with
543
+ * as strototime()-ready string. This is supported by the 'date', 'date_query_before',
544
+ * and 'date_query_after' attributes.
545
+ */
546
+ if (
547
+ true === $accepts_string
548
+ && ( false !== strpos( $date_time, ' ' ) || false === strpos( $date_time, '-' ) )
549
+ ) {
550
+ if ( false !== $timestamp = strtotime( $date_time ) ) {
551
+ return $date_time;
552
+ }
553
+ }
554
+
555
+ $parts = array_map( 'absint', explode( 'date' == $type ? '-' : ':', $date_time ) );
556
+
557
+ // Date.
558
+ if ( 'date' == $type ) {
559
+ // Defaults to 2001 for years, January for months, and 1 for days.
560
+ $year = $month = $day = 1;
561
+
562
+ if ( count( $parts >= 3 ) ) {
563
+ list( $year, $month, $day ) = $parts;
564
+
565
+ $year = ( $year >= 1 && $year <= 9999 ) ? $year : 1;
566
+ $month = ( $month >= 1 && $month <= 12 ) ? $month : 1;
567
+ $day = ( $day >= 1 && $day <= 31 ) ? $day : 1;
568
+ }
569
+
570
+ $segments = array(
571
+ 'year' => $year,
572
+ 'month' => $month,
573
+ 'day' => $day
574
+ );
575
+
576
+ // Time.
577
+ } elseif ( 'time' == $type ) {
578
+ // Defaults to 0 for all segments.
579
+ $hour = $minute = $second = 0;
580
+
581
+ switch( count( $parts ) ) {
582
+ case 3 :
583
+ list( $hour, $minute, $second ) = $parts;
584
+ $hour = ( $hour >= 0 && $hour <= 23 ) ? $hour : 0;
585
+ $minute = ( $minute >= 0 && $minute <= 60 ) ? $minute : 0;
586
+ $second = ( $second >= 0 && $second <= 60 ) ? $second : 0;
587
+ break;
588
+ case 2 :
589
+ list( $hour, $minute ) = $parts;
590
+ $hour = ( $hour >= 0 && $hour <= 23 ) ? $hour : 0;
591
+ $minute = ( $minute >= 0 && $minute <= 60 ) ? $minute : 0;
592
+ break;
593
+ default : break;
594
+ }
595
+
596
+ $segments = array(
597
+ 'hour' => $hour,
598
+ 'minute' => $minute,
599
+ 'second' => $second
600
+ );
601
+ }
602
+
603
+ /**
604
+ * Filter the sanitized segments for the given date or time string.
605
+ *
606
+ * @since 2.5
607
+ *
608
+ * @param array $segments Array of sanitized date or time segments, e.g. hour, minute, second,
609
+ * or year, month, day, depending on the value of the $type parameter.
610
+ * @param string $date_time Date or time string. Dates are formatted 'YYYY-MM-DD', and times are
611
+ * formatted 'HH:MM:SS' or 'HH:MM'.
612
+ * @param string $type Type of string to sanitize. Can be either 'date' or 'time'.
613
+ */
614
+ return apply_filters( 'display_posts_shortcode_sanitized_segments', $segments, $date_time, $type );
615
+ }
616
+
617
  /**
618
  * Turn off display posts shortcode
619
  * If display full post content, any uses of [display-posts] are disabled
624
  * @return array $out
625
  */
626
  function be_display_posts_off( $out, $pairs, $atts ) {
627
+ /**
628
+ * Filter whether to disable the display-posts shortcode.
629
+ *
630
+ * The function and filter were added for backward-compatibility with
631
+ * 2.3 behavior in certain circumstances.
632
+ *
633
+ * @since 2.4
634
+ *
635
+ * @param bool $disable Whether to disable the display-posts shortcode. Default true.
636
+ */
637
+ $out['display_posts_off'] = apply_filters( 'display_posts_shortcode_inception_override', true );
638
  return $out;
639
  }
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: billerickson
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MQKRBRFVRUV8C
4
  Tags: shortcode, pages, posts, page, query, display, list
5
  Requires at least: 3.0
6
- Tested up to: 3.9
7
- Stable tag: 2.4
8
 
9
  Display a listing of posts using the [display-posts] shortcode
10
 
@@ -29,6 +29,14 @@ See the [WordPress Codex](http://codex.wordpress.org/Class_Reference/WP_Query) f
29
 
30
  == Changelog ==
31
 
 
 
 
 
 
 
 
 
32
  **Version 2.4**
33
 
34
  * Add 'include_author' parameter
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MQKRBRFVRUV8C
4
  Tags: shortcode, pages, posts, page, query, display, list
5
  Requires at least: 3.0
6
+ Tested up to: 4.3
7
+ Stable tag: 2.5
8
 
9
  Display a listing of posts using the [display-posts] shortcode
10
 
29
 
30
  == Changelog ==
31
 
32
+ **Version 2.5**
33
+
34
+ * Add support for date queries
35
+ * Exclude child pages with post_parent="0"
36
+ * Query by current taxonomy terms. Ex: [display-posts taxonomy="category" tax_term="current"]
37
+ * Display the post's categories with [display-posts category_display="true"]
38
+ * Many more fixes. See GitHub for a full list of changes.
39
+
40
  **Version 2.4**
41
 
42
  * Add 'include_author' parameter