List category posts - Version 0.84

Version Description

= 0.66 = Full release notes: https://github.com/picandocodigo/List-Category-Posts/releases/tag/0.66

= 0.65 = Full release notes here: https://github.com/picandocodigo/List-Category-Posts/releases/tag/0.65

= 0.37 =

When using content=yes, if the post has a more tag, the plugin will only show the content previous to the more tag and not all the content as it used before (it now supports the more tag the same way as WordPress).

= 0.34 = * Now the plugin accepts either class or tag or both for styling elements (such as date, author, etc. to display). When just using a tag, it will sorround the element with that tag. When using just a class, it will sorround the element between span tags and the given CSS class. Check Other notes under HTML & CSS Customization for more info. * Fixed bug on post_status, it used to show all published posts and if user was logged in, all private ones too. Now you can specify 'private' to just display private posts, and draft, publish, draft, etc (See post_status param on the instructions for more info).

= 0.25 = * Translation support.

= 0.18 = Template system was upgraded with new options. Backwards compatible, but you can better customize the way the post contents are displayed. Check templates/default.php.

= 0.17 = Upgrade your templates: Templates system was rewritten, so your current templates will probably not work. Check out the new default.php file on /templates to see the simpler new way to work with templates.

= 0.13.2 = Thumbnail parameter 'thumbnails' changed to 'thumbnail.

= 0.7.2 = Template system has changed. Now the posts loop must be defined inside the template. Check templates/default.php for an example.

= 0.8 = Widget built for WordPress 2.8's Widget API, so you need at least WP 2.8 to use the widget.

= 0.9 = Template system has changed. Custom templates should be stored in WordPress theme folder.

Download this release

Release Info

Developer fernandobt
Plugin Icon 128x128 List category posts
Version 0.84
Comparing to
See all releases

Code changes from version 0.83.1 to 0.84

include/lcp-catlist.php CHANGED
@@ -18,6 +18,7 @@ class CatList{
18
  private $posts_count = 0;
19
  private $instance = 0;
20
  private $utils;
 
21
 
22
  /**
23
  * Constructor gets the shortcode attributes as parameter
@@ -31,6 +32,7 @@ class CatList{
31
  );
32
  $this->params = $atts;
33
  $this->utils = new LcpUtils($this->params);
 
34
 
35
  if ( $this->utils->lcp_not_empty('instance') ){
36
  $this->instance = $atts['instance'];
@@ -90,7 +92,7 @@ class CatList{
90
  global $wp_query;
91
  $this->posts_count = $wp_query->found_posts;
92
  remove_all_filters('posts_orderby');
93
- remove_filter('posts_where', array( $this, 'starting_with'));
94
  }
95
 
96
  /* Should I return posts or show that the tag/category or whatever
@@ -102,12 +104,12 @@ class CatList{
102
 
103
  /** HELPER FUNCTIONS **/
104
 
105
- private function check_pagination($args){
106
- if ( LcpUtils::lcp_show_pagination($this->params['pagination']) ){
107
- if( array_key_exists('QUERY_STRING', $_SERVER) && null !== $_SERVER['QUERY_STRING'] ){
108
  $query = $_SERVER['QUERY_STRING'];
109
  if ($query !== '' && preg_match('/lcp_page' . preg_quote($this->instance) .
110
- '=([0-9]+)/i', $query, $match) ) {
111
  $this->page = $match[1];
112
  $offset = ($this->page - 1) * $this->params['numberposts'];
113
  $args = array_merge($args, array('offset' => $offset));
@@ -117,10 +119,14 @@ class CatList{
117
  return $args;
118
  }
119
 
120
- public function get_category_id(){
121
  return $this->lcp_category_id;
122
  }
123
 
 
 
 
 
124
  public function get_categories_posts(){
125
  global $wp_query;
126
  return $wp_query->get_posts();
@@ -129,23 +135,21 @@ class CatList{
129
  /**
130
  * Load category name and link to the category:
131
  */
132
- public function get_category_link(){
133
- if(($this->utils->lcp_not_empty('catlink') &&
134
- $this->params['catlink'] == 'yes' ||
135
- $this->utils->lcp_not_empty('catname') &&
136
  $this->params['catname'] == 'yes') &&
137
  $this->lcp_category_id != 0){
138
  // Check for one id or several:
139
  $ids = null;
140
- if (is_array($this->lcp_category_id)){
141
  $ids = $this->lcp_category_id;
142
- } else{
143
  $ids = explode(",", $this->lcp_category_id);
144
  }
145
 
146
  $link = array();
147
  // Loop on several categories:
148
- foreach($ids as $lcp_id){
149
  $cat_link = get_category_link($lcp_id);
150
  $cat_title = get_cat_name($lcp_id);
151
 
@@ -157,10 +161,12 @@ class CatList{
157
  }
158
 
159
  // Do we want the link or just the title?
160
- if ($this->params['catlink'] == 'yes'){
161
- $cat_string = '<a href="' . $cat_link . '" title="' . $cat_title . '">' .
162
- $cat_string .
163
- $this->get_category_count() . '</a>';
 
 
164
  }
165
 
166
  array_push($link, $cat_string);
@@ -174,43 +180,44 @@ class CatList{
174
  /**
175
  * Load morelink name and link to the category:
176
  */
177
- public function get_morelink(){
178
- if (!empty($this->params['morelink'])) :
179
- $href = 'href="' . get_category_link($this->lcp_category_id) . '"';
180
- $readmore = ($this->params['morelink'] !== '' ? $this->params['morelink'] : 'More posts');
181
- return '<a ' . $href . ' >' . $readmore . '</a>';
182
- else:
183
  return null;
184
- endif;
185
  }
186
 
187
  public function get_posts_morelink($single, $css_class) {
188
- if(!empty($this->params['posts_morelink'])){
189
- $href = 'href="' . get_permalink($single->ID) . '"';
190
  $class = $css_class ?: "";
191
- if ( $class ):
192
- $class = 'class="' . $class . '" ';
193
- endif;
194
  $readmore = $this->params['posts_morelink'];
195
- return ' <a ' . $href . ' ' . $class . ' >' . $readmore . '</a>';
196
  }
197
  }
198
 
199
- public function get_category_count(){
200
- if($this->utils->lcp_not_empty('category_count') && $this->params['category_count'] == 'yes'):
201
  return ' ' . get_category($this->lcp_category_id)->category_count;
202
- endif;
203
  }
204
 
205
- public function get_category_description(){
206
- if ($this->utils->lcp_not_empty('category_description') && $this->params['category_description'] == 'yes'){
207
- return '<p>' . category_description( $this->lcp_category_id) . '</p>';
208
  }
209
  }
210
- public function get_conditional_title(){
211
- if($this->utils->lcp_not_empty('conditional_title') && $this->get_posts_count() > 0):
 
212
  return trim($this->params['conditional_title']);
213
- endif;
214
  }
215
 
216
  /**
@@ -219,29 +226,29 @@ class CatList{
219
  * @param string $custom_key
220
  * @param int $post_id
221
  */
222
- public function get_custom_fields($custom_key, $post_id){
223
- if ( $this->utils->lcp_not_empty( 'customfield_display' ) ) :
224
  $lcp_customs = array();
225
 
226
  //Doesn't work for many custom fields when having spaces:
227
- $custom_key = trim( $custom_key );
228
 
229
  //Create array for many fields:
230
- $custom_array = explode( ',', $custom_key );
231
 
232
  //Get post custom fields:
233
- $custom_fields = get_post_custom( $post_id );
234
 
235
  //Loop on custom fields and if there's a value, add it:
236
- foreach ( $custom_array as $user_customfield ) {
237
  // Check that the custom field is wanted:
238
- if ( isset( $custom_fields[$user_customfield] )) {
239
  //Browse through the custom field values:
240
- foreach ( $custom_fields[$user_customfield] as $key => $value ) {
241
- if ( $this->params['customfield_display_name'] != 'no' && $value !== '' ){
242
  $value = $user_customfield . $this->params['customfield_display_name_glue'] . $value;
243
  }
244
- if($value != ''){
245
  $lcp_customs[] = $value;
246
  }
247
  }
@@ -255,40 +262,43 @@ class CatList{
255
  }
256
 
257
  return $lcp_customs;
258
- else:
259
  return null;
260
- endif;
261
  }
262
 
263
- public function get_comments_count($single){
264
  if (isset($this->params['comments']) &&
265
- $this->params['comments'] == 'yes'):
266
  return ' (' . $single->comment_count . ')';
267
- else:
268
  return null;
269
- endif;
270
  }
271
 
272
- public function get_author_to_show($single){
273
- if ($this->params['author'] == 'yes'):
274
  $lcp_userdata = get_userdata($single->post_author);
275
- $author_name = $lcp_userdata->display_name;
276
- if($this->utils->lcp_not_empty('author_posts_link') &&
277
- $this->params['author_posts_link'] == 'yes'){
278
- $link = get_author_posts_url($lcp_userdata->ID);
279
- return "<a href='" . $link . "' title='" . $author_name .
280
- "'>" . $author_name . "</a>";
 
 
 
 
 
 
281
  } else {
282
- return $author_name;
283
- }
284
- else:
285
  return null;
286
- endif;
287
  }
288
 
289
 
290
  /** Pagination **/
291
- public function get_page(){
292
  return $this->page;
293
  }
294
 
@@ -297,119 +307,126 @@ class CatList{
297
  $this->page = $page;
298
  }
299
 
300
- public function get_posts_count(){
301
  return $this->posts_count;
302
  }
303
 
304
- public function get_number_posts(){
305
  return $this->params['numberposts'];
306
  }
307
 
308
- public function get_instance(){
309
  return $this->instance;
310
  }
311
 
312
- public function get_date_to_show($single){
313
- if ($this->params['date'] == 'yes'):
314
  //by Verex, great idea!
315
  return ' ' . get_the_time($this->params['dateformat'], $single);
316
- else:
317
  return null;
318
- endif;
319
  }
320
 
321
- public function get_modified_date_to_show($single){
322
- if ($this->params['date_modified'] == 'yes'):
323
  return " " . get_the_modified_time($this->params['dateformat'], $single);
324
- else:
325
  return null;
326
- endif;
327
  }
328
 
329
  public function get_display_id($single) {
330
- if (!empty($this->params['display_id']) && $this->params['display_id'] == 'yes'){
331
- $lcp_display_output .= $single->ID;
332
  }
333
  }
334
 
335
  public function get_no_posts_text() {
336
- if ( ($this->get_posts_count() == 0) &&
337
- ($this->params["no_posts_text"] != '') ) {
338
  return $this->params["no_posts_text"];
339
  }
340
  }
341
 
342
- public function get_content($single){
343
  if (isset($this->params['content']) &&
344
- ($this->params['content'] =='yes' || $this->params['content'] == 'full') &&
345
- $single->post_content){
346
- // get_extended - get content split by <!--more-->
347
- $lcp_extended = get_extended($single->post_content);
348
- $lcp_content = $lcp_extended['main'];
349
- $lcp_content = apply_filters('the_content', $lcp_content);
350
- $lcp_content = str_replace(']]>', ']]&gt', $lcp_content);
351
-
352
- if ($this->params['content'] == 'full') {
353
- $lcp_extended_content = str_replace(']]>', ']]&gt', apply_filters('the_content', $lcp_extended['extended']) );
354
- $lcp_content .= $lcp_extended_content;
355
- } else {
356
- if( empty($this->params['posts_morelink']) ){
357
- $lcp_more = __('Continue reading &rarr;', 'list-category-posts');
358
- $lcp_content .= ' <a href="' . get_permalink($single->ID) . '" title="' . "$lcp_more" . '">' .
359
- $lcp_more . '</a>';
360
- }
 
 
 
 
 
361
  }
362
- return $lcp_content;
363
- }else {
 
364
  return null;
365
  }
366
  }
367
 
368
- public function get_excerpt($single){
369
- if ( !empty( $this->params['excerpt'] ) &&
370
- ( $this->params['excerpt']=='yes' || $this->params['excerpt']=='full') ){
371
 
372
- if( $single->post_excerpt == "" ||
373
- ( !empty($this->params['excerpt_overwrite']) && $this->params['excerpt_overwrite'] == 'yes' ) ){
374
  // No explicit excerpt or excerpt_overwrite=yes, so generate from content:
375
  $lcp_content = $single->post_content;
376
  // <!--more--> tag?
377
- if( $this->params['excerpt']=='full' &&
378
- preg_match('/[\S\s]+(<!--more(.*?)?-->)[\S\s]+/', $lcp_content, $matches) ) {
379
  $lcp_excerpt = explode($matches[1], $lcp_content);
380
  $lcp_excerpt = $lcp_excerpt[0];
381
- }else{
 
382
  $lcp_excerpt = $this->lcp_trim_excerpt($lcp_content);
383
  }
384
- }else{
385
  // Explicit excerpt and excerpt_overwrite=no:
386
- if( $this->params['excerpt']=='full' ){
387
  $lcp_excerpt = $single->post_excerpt;
388
  } else {
389
  $lcp_excerpt = $this->lcp_trim_excerpt($single->post_excerpt);
390
  }
391
  }
392
- if( strlen($lcp_excerpt) < 1 ){
393
  $lcp_excerpt = $single->post_title;
394
  }
395
  return $lcp_excerpt;
396
  }
397
  }
398
 
399
- private function lcp_trim_excerpt($text = ''){
400
- $excerpt_length = intval( $this->params['excerpt_size'] );
401
 
402
  $text = strip_shortcodes($text);
403
  $text = apply_filters('the_excerpt', $text);
404
  $text = str_replace(']]>',']]&gt;', $text);
405
 
406
- if( $this->utils->lcp_not_empty('excerpt_strip') &&
407
- $this->params['excerpt_strip'] == 'yes' ){
408
  $text = strip_tags($text);
409
  }
410
 
411
  $words = explode(' ', $text, $excerpt_length + 1);
412
- if(count($words) > $excerpt_length){
413
  array_pop($words);
414
  array_push($words, '...');
415
  $text = implode(' ', $words);
@@ -417,8 +434,8 @@ class CatList{
417
  return $text;
418
  }
419
 
420
- public function get_thumbnail($single, $lcp_thumb_class = null){
421
- if ($this->utils->lcp_not_empty('force_thumbnail')){
422
  $force_thumbnail = $this->params['force_thumbnail'];
423
  } else {
424
  $force_thumbnail = 'no';
@@ -428,56 +445,55 @@ class CatList{
428
  $this->params['thumbnail'],
429
  $this->params['thumbnail_size'],
430
  $force_thumbnail,
431
- $lcp_thumb_class);
 
432
  }
433
 
434
  public function get_outer_tag($tag, $css_class) {
435
  $css_class = $this->params['class'] ?: $css_class;
436
 
437
- $tag_string = '<' . $tag;
438
  if ($tag == 'ol' && !empty($this->params['ol_offset'])) {
439
- $tag_string .= ' start="' . $this->params['ol_offset'] . '"';
440
  }
441
 
442
  // Follow the number of posts in an ordered list with pagination.
443
- if( 'ol' === $tag && $this->page > 1 ) {
444
- $start = $this->get_number_posts() * ( $this->page - 1 ) + 1;
445
- $tag_string .= ' start="' . $start . '"';
446
  }
447
  //Give a class to wrapper tag
448
- $tag_string .= ' class="' . $css_class . '"';
449
 
450
  //Give id to wrapper tag
451
- $tag_string .= ' id="lcp_instance_' . $this->instance . '"';
452
-
453
- $tag_string .= '>';
454
 
455
- return $tag_string;
456
  }
457
 
458
- public function get_inner_tag( $single, $parent, $tag, $css_class='' ) {
459
  $class = $css_class;
460
- $tag_css = '';
461
- if ( is_object( $parent ) && is_object( $single ) &&
462
- $parent->ID === $single->ID ) {
463
  $class .= 'current';
464
  }
465
 
466
- if ( $this->params['tags_as_class'] === 'yes' ) {
467
- $post_tags = wp_get_post_Tags( $single->ID );
468
- if ( !empty( $post_tags ) ) {
469
- foreach ( $post_tags as $post_tag ) {
470
  $class .= " $post_tag->slug ";
471
  }
472
  }
473
  }
474
- if ( !empty($class) ) {
475
- $tag_css = 'class="' . $class . '"';
476
  }
477
- return '<'. $tag . ' ' . $tag_css . '>';
478
  }
479
 
480
- public function get_pagination(){
481
  $paginator_params = array(
482
  'bookmarks' => $this->params['pagination_bookmarks'],
483
  'instance' => $this->get_instance(),
18
  private $posts_count = 0;
19
  private $instance = 0;
20
  private $utils;
21
+ private $wrapper;
22
 
23
  /**
24
  * Constructor gets the shortcode attributes as parameter
32
  );
33
  $this->params = $atts;
34
  $this->utils = new LcpUtils($this->params);
35
+ $this->wrapper = LcpWrapper::get_instance();
36
 
37
  if ( $this->utils->lcp_not_empty('instance') ){
38
  $this->instance = $atts['instance'];
92
  global $wp_query;
93
  $this->posts_count = $wp_query->found_posts;
94
  remove_all_filters('posts_orderby');
95
+ remove_filter('posts_where', array(LcpParameters::get_instance(), 'starting_with'));
96
  }
97
 
98
  /* Should I return posts or show that the tag/category or whatever
104
 
105
  /** HELPER FUNCTIONS **/
106
 
107
+ private function check_pagination($args) {
108
+ if (LcpUtils::lcp_show_pagination($this->params['pagination'])) {
109
+ if(array_key_exists('QUERY_STRING', $_SERVER) && null !== $_SERVER['QUERY_STRING'] ) {
110
  $query = $_SERVER['QUERY_STRING'];
111
  if ($query !== '' && preg_match('/lcp_page' . preg_quote($this->instance) .
112
+ '=([0-9]+)/i', $query, $match)) {
113
  $this->page = $match[1];
114
  $offset = ($this->page - 1) * $this->params['numberposts'];
115
  $args = array_merge($args, array('offset' => $offset));
119
  return $args;
120
  }
121
 
122
+ public function get_category_id() {
123
  return $this->lcp_category_id;
124
  }
125
 
126
+ /**
127
+ * This is no longer used by templates. Keeping for
128
+ * backward compatibility with old templates.
129
+ */
130
  public function get_categories_posts(){
131
  global $wp_query;
132
  return $wp_query->get_posts();
135
  /**
136
  * Load category name and link to the category:
137
  */
138
+ public function get_category_link() {
139
+ if(($this->params['catlink'] == 'yes' ||
 
 
140
  $this->params['catname'] == 'yes') &&
141
  $this->lcp_category_id != 0){
142
  // Check for one id or several:
143
  $ids = null;
144
+ if (is_array($this->lcp_category_id)) {
145
  $ids = $this->lcp_category_id;
146
+ } else {
147
  $ids = explode(",", $this->lcp_category_id);
148
  }
149
 
150
  $link = array();
151
  // Loop on several categories:
152
+ foreach($ids as $lcp_id) {
153
  $cat_link = get_category_link($lcp_id);
154
  $cat_title = get_cat_name($lcp_id);
155
 
161
  }
162
 
163
  // Do we want the link or just the title?
164
+ if ($this->params['catlink'] == 'yes') {
165
+ $cat_string = $this->wrapper->to_html(
166
+ 'a',
167
+ ['href' => $cat_link, 'title' => $cat_title],
168
+ $cat_string . $this->get_category_count()
169
+ );
170
  }
171
 
172
  array_push($link, $cat_string);
180
  /**
181
  * Load morelink name and link to the category:
182
  */
183
+ public function get_morelink() {
184
+ if (!empty($this->params['morelink'])) {
185
+ $props = ['href=' => get_category_link($this->lcp_category_id)];
186
+ $readmore = ($this->params['morelink'] !== '' ? $this->params['morelink'] : 'More posts');
187
+ return $this->wrapper->to_html('a', $props, $readmore);
188
+ } else {
189
  return null;
190
+ }
191
  }
192
 
193
  public function get_posts_morelink($single, $css_class) {
194
+ if(!empty($this->params['posts_morelink'])) {
195
+ $props = ['href' => get_permalink($single->ID)];
196
  $class = $css_class ?: "";
197
+ if ($class) {
198
+ $props['class'] = $class;
199
+ }
200
  $readmore = $this->params['posts_morelink'];
201
+ return $this->wrapper->to_html('a', $props, $readmore);
202
  }
203
  }
204
 
205
+ public function get_category_count() {
206
+ if($this->utils->lcp_not_empty('category_count') && $this->params['category_count'] == 'yes') {
207
  return ' ' . get_category($this->lcp_category_id)->category_count;
208
+ }
209
  }
210
 
211
+ public function get_category_description() {
212
+ if ($this->utils->lcp_not_empty('category_description') && $this->params['category_description'] == 'yes') {
213
+ return get_term_field('description', $this->lcp_category_id, '', 'raw');
214
  }
215
  }
216
+
217
+ public function get_conditional_title() {
218
+ if($this->utils->lcp_not_empty('conditional_title') && $this->get_posts_count() > 0) {
219
  return trim($this->params['conditional_title']);
220
+ }
221
  }
222
 
223
  /**
226
  * @param string $custom_key
227
  * @param int $post_id
228
  */
229
+ public function get_custom_fields($custom_key, $post_id) {
230
+ if ($this->utils->lcp_not_empty('customfield_display')) {
231
  $lcp_customs = array();
232
 
233
  //Doesn't work for many custom fields when having spaces:
234
+ $custom_key = trim($custom_key);
235
 
236
  //Create array for many fields:
237
+ $custom_array = explode(',', $custom_key);
238
 
239
  //Get post custom fields:
240
+ $custom_fields = get_post_custom($post_id);
241
 
242
  //Loop on custom fields and if there's a value, add it:
243
+ foreach ($custom_array as $user_customfield) {
244
  // Check that the custom field is wanted:
245
+ if (isset( $custom_fields[$user_customfield])) {
246
  //Browse through the custom field values:
247
+ foreach ($custom_fields[$user_customfield] as $key => $value) {
248
+ if ($this->params['customfield_display_name'] != 'no' && $value !== '' ){
249
  $value = $user_customfield . $this->params['customfield_display_name_glue'] . $value;
250
  }
251
+ if($value != '') {
252
  $lcp_customs[] = $value;
253
  }
254
  }
262
  }
263
 
264
  return $lcp_customs;
265
+ } else {
266
  return null;
267
+ }
268
  }
269
 
270
+ public function get_comments_count($single) {
271
  if (isset($this->params['comments']) &&
272
+ $this->params['comments'] == 'yes') {
273
  return ' (' . $single->comment_count . ')';
274
+ } else {
275
  return null;
276
+ }
277
  }
278
 
279
+ public function get_author_to_show($single) {
280
+ if ($this->params['author'] == 'yes') {
281
  $lcp_userdata = get_userdata($single->post_author);
282
+ $author_name = $lcp_userdata->display_name;
283
+ if($this->utils->lcp_not_empty('author_posts_link') &&
284
+ $this->params['author_posts_link'] == 'yes') {
285
+ $link = get_author_posts_url($lcp_userdata->ID);
286
+ return $this->wrapper->to_html(
287
+ 'a',
288
+ ['href' => $link, 'title' => $author_name],
289
+ $author_name
290
+ );
291
+ } else {
292
+ return $author_name;
293
+ }
294
  } else {
 
 
 
295
  return null;
296
+ }
297
  }
298
 
299
 
300
  /** Pagination **/
301
+ public function get_page() {
302
  return $this->page;
303
  }
304
 
307
  $this->page = $page;
308
  }
309
 
310
+ public function get_posts_count() {
311
  return $this->posts_count;
312
  }
313
 
314
+ public function get_number_posts() {
315
  return $this->params['numberposts'];
316
  }
317
 
318
+ public function get_instance() {
319
  return $this->instance;
320
  }
321
 
322
+ public function get_date_to_show($single) {
323
+ if ($this->params['date'] == 'yes') {
324
  //by Verex, great idea!
325
  return ' ' . get_the_time($this->params['dateformat'], $single);
326
+ } else {
327
  return null;
328
+ }
329
  }
330
 
331
+ public function get_modified_date_to_show($single) {
332
+ if ($this->params['date_modified'] == 'yes') {
333
  return " " . get_the_modified_time($this->params['dateformat'], $single);
334
+ } else {
335
  return null;
336
+ }
337
  }
338
 
339
  public function get_display_id($single) {
340
+ if (!empty($this->params['display_id']) && $this->params['display_id'] == 'yes') {
341
+ return $single->ID;
342
  }
343
  }
344
 
345
  public function get_no_posts_text() {
346
+ if (($this->get_posts_count() == 0) &&
347
+ ($this->params["no_posts_text"] != '')) {
348
  return $this->params["no_posts_text"];
349
  }
350
  }
351
 
352
+ public function get_content($single) {
353
  if (isset($this->params['content']) &&
354
+ ($this->params['content'] =='yes' || $this->params['content'] == 'full') &&
355
+ $single->post_content){
356
+ // get_extended - get content split by <!--more-->
357
+ $lcp_extended = get_extended($single->post_content);
358
+ $lcp_content = $lcp_extended['main'];
359
+ $lcp_content = apply_filters('the_content', $lcp_content);
360
+ $lcp_content = str_replace(']]>', ']]&gt', $lcp_content);
361
+
362
+ if ($this->params['content'] == 'full') {
363
+ $lcp_extended_content = str_replace(
364
+ ']]>',
365
+ ']]&gt', apply_filters('the_content', $lcp_extended['extended'])
366
+ );
367
+ $lcp_content .= $lcp_extended_content;
368
+ } else {
369
+ if (empty($this->params['posts_morelink'])) {
370
+ $lcp_more = __('Continue reading &rarr;', 'list-category-posts');
371
+ $lcp_content .= $this->wrapper->to_html(
372
+ 'a',
373
+ ['href' => get_permalink($single->ID), 'title' => $lcp_more],
374
+ $lcp_more
375
+ );
376
  }
377
+ }
378
+ return $lcp_content;
379
+ } else {
380
  return null;
381
  }
382
  }
383
 
384
+ public function get_excerpt($single) {
385
+ if (!empty( $this->params['excerpt']) &&
386
+ ($this->params['excerpt']=='yes' || $this->params['excerpt']=='full')) {
387
 
388
+ if($single->post_excerpt == "" ||
389
+ (!empty($this->params['excerpt_overwrite']) && $this->params['excerpt_overwrite'] == 'yes')) {
390
  // No explicit excerpt or excerpt_overwrite=yes, so generate from content:
391
  $lcp_content = $single->post_content;
392
  // <!--more--> tag?
393
+ if($this->params['excerpt']=='full' &&
394
+ preg_match('/[\S\s]+(<!--more(.*?)?-->)[\S\s]+/', $lcp_content, $matches)) {
395
  $lcp_excerpt = explode($matches[1], $lcp_content);
396
  $lcp_excerpt = $lcp_excerpt[0];
397
+ $lcp_excerpt = apply_filters('the_excerpt', $lcp_excerpt);
398
+ } else {
399
  $lcp_excerpt = $this->lcp_trim_excerpt($lcp_content);
400
  }
401
+ } else {
402
  // Explicit excerpt and excerpt_overwrite=no:
403
+ if($this->params['excerpt']=='full') {
404
  $lcp_excerpt = $single->post_excerpt;
405
  } else {
406
  $lcp_excerpt = $this->lcp_trim_excerpt($single->post_excerpt);
407
  }
408
  }
409
+ if(strlen($lcp_excerpt) < 1 ) {
410
  $lcp_excerpt = $single->post_title;
411
  }
412
  return $lcp_excerpt;
413
  }
414
  }
415
 
416
+ private function lcp_trim_excerpt($text = '') {
417
+ $excerpt_length = intval($this->params['excerpt_size']);
418
 
419
  $text = strip_shortcodes($text);
420
  $text = apply_filters('the_excerpt', $text);
421
  $text = str_replace(']]>',']]&gt;', $text);
422
 
423
+ if($this->utils->lcp_not_empty('excerpt_strip') &&
424
+ $this->params['excerpt_strip'] == 'yes') {
425
  $text = strip_tags($text);
426
  }
427
 
428
  $words = explode(' ', $text, $excerpt_length + 1);
429
+ if(count($words) > $excerpt_length) {
430
  array_pop($words);
431
  array_push($words, '...');
432
  $text = implode(' ', $words);
434
  return $text;
435
  }
436
 
437
+ public function get_thumbnail($single, $lcp_thumb_class = null) {
438
+ if ($this->utils->lcp_not_empty('force_thumbnail')) {
439
  $force_thumbnail = $this->params['force_thumbnail'];
440
  } else {
441
  $force_thumbnail = 'no';
445
  $this->params['thumbnail'],
446
  $this->params['thumbnail_size'],
447
  $force_thumbnail,
448
+ $lcp_thumb_class
449
+ );
450
  }
451
 
452
  public function get_outer_tag($tag, $css_class) {
453
  $css_class = $this->params['class'] ?: $css_class;
454
 
455
+ $props = [];
456
  if ($tag == 'ol' && !empty($this->params['ol_offset'])) {
457
+ $props['start'] = $this->params['ol_offset'];
458
  }
459
 
460
  // Follow the number of posts in an ordered list with pagination.
461
+ if('ol' === $tag && $this->page > 1) {
462
+ $start = $this->get_number_posts() * ($this->page - 1) + 1;
463
+ $props['start'] = $start;
464
  }
465
  //Give a class to wrapper tag
466
+ $props['class'] = $css_class;
467
 
468
  //Give id to wrapper tag
469
+ $props['id'] = 'lcp_instance_' . $this->instance;
 
 
470
 
471
+ return $this->wrapper->to_html($tag, $props, null, false);
472
  }
473
 
474
+ public function get_inner_tag($single, $parent, $tag, $css_class='') {
475
  $class = $css_class;
476
+ $props = [];
477
+ if (is_object( $parent) && is_object($single) &&
478
+ $parent->ID === $single->ID) {
479
  $class .= 'current';
480
  }
481
 
482
+ if ($this->params['tags_as_class'] === 'yes') {
483
+ $post_tags = wp_get_post_Tags($single->ID);
484
+ if (!empty($post_tags)) {
485
+ foreach ($post_tags as $post_tag) {
486
  $class .= " $post_tag->slug ";
487
  }
488
  }
489
  }
490
+ if (!empty($class)) {
491
+ $props['class'] = $class;
492
  }
493
+ return $this->wrapper->to_html($tag, $props, null, false);
494
  }
495
 
496
+ public function get_pagination() {
497
  $paginator_params = array(
498
  'bookmarks' => $this->params['pagination_bookmarks'],
499
  'instance' => $this->get_instance(),
include/lcp-catlistdisplayer.php CHANGED
@@ -72,8 +72,8 @@ class CatListDisplayer {
72
  return $this->catlist->get_category_count();
73
  }
74
 
75
- public function get_category_description(){
76
- return $this->catlist->get_category_description();
77
  }
78
 
79
  private function get_no_posts_text() {
@@ -176,6 +176,9 @@ class CatListDisplayer {
176
  case 'customfield':
177
  $info = $this->catlist->get_custom_fields($this->params['customfield_display'], $post->ID);
178
  break;
 
 
 
179
  case 'date':
180
  $info = $this->catlist->get_date_to_show($post);
181
  if ( !empty($this->params['link_dates']) && ( 'yes' === $this->params['link_dates'] || 'true' === $this->params['link_dates'] ) ):
@@ -199,65 +202,60 @@ class CatListDisplayer {
199
  }
200
 
201
  private function get_post_link($single, $text, $class = null){
202
- $info = '<a href="' . get_permalink($single->ID) . '" title="' . wptexturize($single->post_title) . '"';
203
 
204
- if ( !empty($this->params['link_target']) ):
205
- $info .= ' target="' . $this->params['link_target'] . '"';
206
- endif;
 
 
 
 
 
 
 
 
207
 
208
- if ( !empty($class ) ):
209
- $info .= ' class="' . $class . '"';
210
- endif;
211
 
212
- $info .= '>' . $text . '</a>';
213
- if($single->post_status == 'private'):
214
- $info .= '<span class="lcp_private"> private</span>';
215
- endif;
216
 
217
- return $info;
218
  }
219
 
220
  // Link is a parameter here in case you want to use it on a template
221
  // and not show the links for all the shortcodes using this template:
222
- private function get_post_title($single, $tag = null, $css_class = null, $link = true){
 
223
  // Don't do anything if no_post_titles is specified.
224
- if ( 'yes' === $this->params['no_post_titles'] ) {
225
  return;
226
  }
227
 
228
- $lcp_post_title = apply_filters('the_title', $single->post_title, $single->ID);
 
 
 
229
 
230
- $lcp_post_title = $this->lcp_title_limit( $lcp_post_title );
231
-
232
- if ( !empty($this->params['title_tag']) ) {
233
- $pre = "<" . $this->params['title_tag'];
234
- if (!empty($this->params['title_class'])){
235
- $pre .= ' class="' . $this->params['title_class'] . '"';
236
- }
237
- $pre .= '>';
238
- $post = "</" . $this->params['title_tag'] . ">";
239
- }else{
240
- $pre = $post = '';
241
- }
242
-
243
- if ( !$link || ( !empty($this->params['link_titles'] ) &&
244
- ( $this->params['link_titles'] === "false" || $this->params['link_titles'] === "no" ) ) ) {
245
- return $pre . $lcp_post_title . $post;
246
  }
247
 
248
- $info = $this->get_post_link($single, $lcp_post_title, (!empty($this->params['title_class']) && empty($this->params['title_tag'])) ? $this->params['title_class'] : null);
249
-
250
- if( !empty($this->params['post_suffix']) ):
251
- $info .= " " . $this->params['post_suffix'];
252
- endif;
253
-
254
- $info = $pre . $info . $post;
255
-
256
- if( $tag !== null || $css_class !== null){
257
- $info = $this->wrapper->wrap($info, $tag, $css_class);
 
258
  }
259
 
260
- return $info;
261
  }
262
 
263
  // Transform the title into the sub string if `title_limit` is present
72
  return $this->catlist->get_category_count();
73
  }
74
 
75
+ public function get_category_description($tag = null, $css_class = null) {
76
+ return $this->content_getter('category_description', null, $tag, $css_class);
77
  }
78
 
79
  private function get_no_posts_text() {
176
  case 'customfield':
177
  $info = $this->catlist->get_custom_fields($this->params['customfield_display'], $post->ID);
178
  break;
179
+ case 'category_description':
180
+ $info = $this->catlist->get_category_description();
181
+ break;
182
  case 'date':
183
  $info = $this->catlist->get_date_to_show($post);
184
  if ( !empty($this->params['link_dates']) && ( 'yes' === $this->params['link_dates'] || 'true' === $this->params['link_dates'] ) ):
202
  }
203
 
204
  private function get_post_link($single, $text, $class = null){
 
205
 
206
+ $props = ['href' => get_permalink($single->ID)];
207
+
208
+ if (!empty($class)) {
209
+ $props['class'] = $class;
210
+ }
211
+
212
+ if (!empty($this->params['link_target'])) {
213
+ $props['target'] = $this->params['link_target'];
214
+ }
215
+
216
+ $props['title'] = wptexturize($single->post_title);
217
 
218
+ $output = $this->wrapper->to_html('a', $props, $text);
 
 
219
 
220
+ if ($single->post_status == 'private') {
221
+ $output .= $this->wrapper->wrap(' private', 'span', 'lcp_private');
222
+ }
 
223
 
224
+ return $output;
225
  }
226
 
227
  // Link is a parameter here in case you want to use it on a template
228
  // and not show the links for all the shortcodes using this template:
229
+ public function get_post_title($single, $tag = null, $css_class = null, $link = true) {
230
+
231
  // Don't do anything if no_post_titles is specified.
232
+ if ('yes' === $this->params['no_post_titles']) {
233
  return;
234
  }
235
 
236
+ // Shortcode parameters take precedence.
237
+ $tag = $this->params['title_tag'] ?: $tag;
238
+ $css_class = $this->params['title_class'] ?: $css_class;
239
+ $suffix = $this->params['post_suffix'] ? ' ' . $this->params['post_suffix'] : '';
240
 
241
+ if (in_array($this->params['link_titles'], ['false', 'no'], true)) {
242
+ $link = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
+ $post_title = apply_filters('the_title', $single->post_title, $single->ID);
246
+ $post_title = $this->lcp_title_limit($post_title);
247
+
248
+ if (!$link) {
249
+ $post_title .= $suffix;
250
+ $output = $this->wrapper->wrap($post_title, $tag, $css_class);
251
+ } else if (empty($tag)) {
252
+ $output = $this->get_post_link($single, $post_title, $css_class) . $suffix;
253
+ } else if (!empty($tag)) {
254
+ $output = $this->get_post_link($single, $post_title) . $suffix;
255
+ $output = $this->wrapper->wrap($output, $tag, $css_class);
256
  }
257
 
258
+ return $output;
259
  }
260
 
261
  // Transform the title into the sub string if `title_limit` is present
include/lcp-meta-query.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file defines the LcpMetaQuery trait.
4
+ */
5
+
6
+ /**
7
+ * The LcpMetaQuery trait is inteded to be used in
8
+ * the LcpParameters class. It contains code that builds
9
+ * WP_Meta_Query.
10
+ *
11
+ * All customfield related code should be in this trait (except
12
+ * customfield display).
13
+ *
14
+ * @see WP_Meta_Query
15
+ */
16
+ trait LcpMetaQuery {
17
+
18
+ /**
19
+ * Parses customfield related shortcode parameters.
20
+ *
21
+ * This is the only method of this trait that is inteded to be called
22
+ * directly. It calls helper methods to parse shortcode parameters that
23
+ * select posts by custom fields and to build a WP_Meta_Query compatible
24
+ * array of arguments. The 'meta_query' array is only appended to $args
25
+ * if it is not empty i.e. at least one relevant shortcode parameter was used.
26
+ *
27
+ * @param array $args Array of WP_Query arguments.
28
+ * @param array $params Shortcode parameters.
29
+ * @return array The original `$args` with a new 'meta_query' array
30
+ * appended if any customfield options were specified.
31
+ */
32
+ public function create_meta_query_args($args, $params) {
33
+ $meta_query = array();
34
+ /*
35
+ * 'AND' is the default relation, keeping this line
36
+ * for better readability.
37
+ */
38
+ $meta_query['relation'] = 'AND';
39
+
40
+ $this->check_simple_customfield($params, $meta_query);
41
+ $this->check_customfield_orderby($params, $meta_query);
42
+ $this->check_customfield_compare($params, $meta_query);
43
+
44
+ /*
45
+ * If any query clauses were added to $meta_query,
46
+ * it needs to be added to args.
47
+ */
48
+ if ( !empty($meta_query) ) {
49
+ $args['meta_query'] = $meta_query;
50
+ // Adjust args for customfield_orderby if necessary.
51
+ if ( isset($meta_query['orderby_clause']) ) {
52
+ $args['orderby'] = 'orderby_clause';
53
+ }
54
+ }
55
+
56
+ return $args;
57
+ }
58
+
59
+ /**
60
+ * Handles the customfield_name and customfield_value shortcode parameters.
61
+ *
62
+ * @param array $params Shortcode parameters.
63
+ * @param array &$meta_query WP_Meta_Query compatible arguments.
64
+ */
65
+ private function check_simple_customfield($params, &$meta_query) {
66
+ /*
67
+ * 'customfield_name' & 'customfield_value'
68
+ * should both be defined
69
+ */
70
+ if( $params['customfield_name'] ) {
71
+ $meta_query['select_clause'] = array(
72
+ 'key' => $params['customfield_name'],
73
+ 'value' => $params['customfield_value'],
74
+ );
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Handles the customfield_orderby shortcode parameter.
80
+ *
81
+ * @param array $params Shortcode parameters.
82
+ * @param array &$meta_query WP_Meta_Query compatible arguments.
83
+ */
84
+ private function check_customfield_orderby($params, &$meta_query) {
85
+ if ( $params['customfield_orderby'] ) {
86
+ $meta_query['orderby_clause'] = array(
87
+ 'key' => $params['customfield_orderby'],
88
+ 'compare' => 'EXISTS',
89
+ );
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Handles the customfield_compare shortcode parameter.
95
+ *
96
+ * @param array $params Shortcode parameters.
97
+ * @param array &$meta_query WP_Meta_Query compatible arguments.
98
+ */
99
+ private function check_customfield_compare($params, &$meta_query) {
100
+ if ($params['customfield_compare']) {
101
+
102
+ // customfield_compare=key,compare,value,type;key,compare,value,type...
103
+ $compare_queries = explode(';', $params['customfield_compare']);
104
+
105
+ /*
106
+ * Start building a nested array query.
107
+ * 'AND' is the default relation. Arrays with user defined queries
108
+ * will be appended to $compare_clauses.
109
+ */
110
+ $compare_clauses = ['relation' => 'AND'];
111
+
112
+ foreach ($compare_queries as $query) {
113
+ // Get an array in the format: [key,compare,value,type].
114
+ $compare_args = explode(',', $query);
115
+ $compare_clause = [];
116
+
117
+ // Determine type first because it is needed for $format_value below.
118
+ if (isset($compare_args[3])) {
119
+ // If not set, defaults to 'CHAR' (as per WP docs).
120
+ $compare_clause['type'] = strtoupper($compare_args[3]);
121
+ } else {
122
+ $compare_clause['type'] = 'CHAR';
123
+ }
124
+
125
+ /*
126
+ * Prepare a value formatter to use in customfield comparisons.
127
+ * this returns a function that takes field value as an argument.
128
+ */
129
+ $format_value = call_user_func(
130
+ 'LcpUtils::lcp_format_customfield',
131
+ $compare_clause['type']
132
+ );
133
+
134
+ $compare_clause['key'] = $compare_args[0];
135
+ // If not set, defaults to '=' but in this implementation we make it required.
136
+ $compare_clause['compare'] = $this->customfield_compare_convert($compare_args[1]);
137
+ // value is not required and should not be used for the EXISTS comparison.
138
+ if (isset($compare_args[2])) {
139
+ $compare_clause['value'] = $format_value($compare_args[2]);
140
+ }
141
+
142
+ $compare_clauses[] = $compare_clause;
143
+ }
144
+
145
+ $meta_query[] = $compare_clauses;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Converts user input to WP_Meta_Query compatible values.
151
+ *
152
+ * Symbols like `<` and any other HTML are not allowed in shortcodes.
153
+ * This is why we must provide users with simple text values they can
154
+ * use and then convert them to what WP_Meta_Query needs.
155
+ *
156
+ * @link https://codex.wordpress.org/Shortcode_API#HTML
157
+ *
158
+ * @param string $value Value to be converted.
159
+ * @return string Converted output or initial input
160
+ * if no match is found.
161
+ */
162
+ private function customfield_compare_convert($value) {
163
+ $conversion_table = [
164
+ 'greaterthan' => '>',
165
+ 'greaterthanequal' => '>=',
166
+ 'lessthan' => '<',
167
+ 'lessthanequal' => '<=',
168
+ 'equals' => '=',
169
+ 'not_equals' => '!=',
170
+ // This is just so that users do not have to use spaces.
171
+ 'not_exists' => 'NOT EXISTS',
172
+ ];
173
+ if (isset($conversion_table[$value])) {
174
+ return $conversion_table[$value];
175
+ } else {
176
+ return $value;
177
+ }
178
+ }
179
+ }
include/lcp-parameters.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
- require_once ( LCP_PATH . 'lcp-utils.php' );
3
- require_once ( LCP_PATH . 'lcp-date-query.php' );
 
4
 
5
  class LcpParameters{
6
  // Singleton implementation
@@ -11,6 +12,8 @@ class LcpParameters{
11
 
12
  // Use Trait for before/after date queries:
13
  use LcpDateQuery;
 
 
14
 
15
  public static function get_instance(){
16
  if( !isset( self::$instance ) ){
@@ -21,7 +24,6 @@ class LcpParameters{
21
 
22
  public function get_query_params($params){
23
  $this->params = $params;
24
- $meta_query = array();
25
  # Essential parameters:
26
  $args = array(
27
  'numberposts' => $params['numberposts'],
@@ -35,6 +37,11 @@ class LcpParameters{
35
  // Check posts to exclude
36
  $args = $this->lcp_check_excludes($args);
37
 
 
 
 
 
 
38
  // Check type, status, parent params
39
  $args = $this->lcp_types_and_statuses($args);
40
 
@@ -62,16 +69,7 @@ class LcpParameters{
62
  // Only generate date_query args if a before/after paramater was found
63
  $args = $this->create_date_query_args($args, $params);
64
 
65
- /*
66
- * Custom fields 'customfield_name' & 'customfield_value'
67
- * should both be defined
68
- */
69
- if( $this->utils->lcp_not_empty('customfield_name') ){
70
- $meta_query['select_clause'] = array(
71
- 'key' => $params['customfield_name'],
72
- 'value' => $params['customfield_value']
73
- );
74
- }
75
 
76
  //Get private posts
77
  if( is_user_logged_in() ){
@@ -133,20 +131,6 @@ class LcpParameters{
133
  $args['category__not_in'] = array($params['exclude']);
134
  }
135
 
136
- if ( $this->utils->lcp_not_empty('customfield_orderby') ){
137
- $meta_query['orderby_clause'] = array(
138
- 'key' => $params['customfield_orderby'],
139
- 'compare' => 'EXISTS',
140
- );
141
- $args['orderby'] = 'orderby_clause';
142
- }
143
-
144
- // If either select_clause or orderby_clause were added to $meta_query,
145
- // it needs to be added to args.
146
- if ( !empty($meta_query) ) {
147
- $args['meta_query'] = $meta_query;
148
- }
149
-
150
  // Posts that start with a given letter:
151
  if ( $this->utils->lcp_not_empty('starting_with') ){
152
  $this->starting_with = $params['starting_with'];
1
  <?php
2
+ require_once LCP_PATH . 'lcp-utils.php';
3
+ require_once LCP_PATH . 'lcp-date-query.php';
4
+ require_once LCP_PATH . 'lcp-meta-query.php';
5
 
6
  class LcpParameters{
7
  // Singleton implementation
12
 
13
  // Use Trait for before/after date queries:
14
  use LcpDateQuery;
15
+ // Use Trait for meta query
16
+ use LcpMetaQuery;
17
 
18
  public static function get_instance(){
19
  if( !isset( self::$instance ) ){
24
 
25
  public function get_query_params($params){
26
  $this->params = $params;
 
27
  # Essential parameters:
28
  $args = array(
29
  'numberposts' => $params['numberposts'],
37
  // Check posts to exclude
38
  $args = $this->lcp_check_excludes($args);
39
 
40
+ // Check posts to include
41
+ if( $this->utils->lcp_not_empty('includeposts') ){
42
+ $args['post__in'] = explode(",", $this->params['includeposts']);
43
+ }
44
+
45
  // Check type, status, parent params
46
  $args = $this->lcp_types_and_statuses($args);
47
 
69
  // Only generate date_query args if a before/after paramater was found
70
  $args = $this->create_date_query_args($args, $params);
71
 
72
+ $args = $this->create_meta_query_args($args, $params);
 
 
 
 
 
 
 
 
 
73
 
74
  //Get private posts
75
  if( is_user_logged_in() ){
131
  $args['category__not_in'] = array($params['exclude']);
132
  }
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  // Posts that start with a given letter:
135
  if ( $this->utils->lcp_not_empty('starting_with') ){
136
  $this->starting_with = $params['starting_with'];
include/lcp-templater.php CHANGED
@@ -22,7 +22,7 @@ class LcpTemplater {
22
  *
23
  * @var array
24
  */
25
- private static $paths = null;
26
 
27
  /**
28
  * Path to the template file being used.
@@ -81,13 +81,15 @@ class LcpTemplater {
81
  * @return array Paths to template directory.
82
  */
83
  private static function get_template_paths() {
84
- if (null === self::$paths) {
85
- self::$paths = array_unique(
86
  [
87
  get_stylesheet_directory() . '/list-category-posts/',
88
  get_template_directory() . '/list-category-posts/',
89
  ]
90
  );
 
 
91
  }
92
  return self::$paths;
93
  }
22
  *
23
  * @var array
24
  */
25
+ private static $paths = [];
26
 
27
  /**
28
  * Path to the template file being used.
81
  * @return array Paths to template directory.
82
  */
83
  private static function get_template_paths() {
84
+ if ([] === self::$paths) {
85
+ $paths = array_unique(
86
  [
87
  get_stylesheet_directory() . '/list-category-posts/',
88
  get_template_directory() . '/list-category-posts/',
89
  ]
90
  );
91
+ $paths = array_filter($paths, 'is_dir');
92
+ self::$paths = $paths;
93
  }
94
  return self::$paths;
95
  }
include/lcp-utils.php CHANGED
@@ -37,4 +37,25 @@ class LcpUtils{
37
  ($pagination !== 'no')
38
  );
39
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
37
  ($pagination !== 'no')
38
  );
39
  }
40
+
41
+ public static function lcp_format_customfield($type) {
42
+ $format = null;
43
+ switch ($type) {
44
+ case 'DATETIME':
45
+ $format = 'c';
46
+ break;
47
+ case 'DATE':
48
+ $format = 'Y-m-d';
49
+ break;
50
+ case 'TIME':
51
+ $format = 'H:i:s';
52
+ }
53
+
54
+ return function($value) use ($format) {
55
+ // When necessary, format the string, if not
56
+ // return it as is.
57
+ if ($format) return date($format, strtotime($value));
58
+ return $value;
59
+ };
60
+ }
61
  }
include/lcp-widget-form.php CHANGED
@@ -16,6 +16,7 @@
16
  'excerpt_size' =>'',
17
  'exclude'=>'',
18
  'excludeposts'=>'',
 
19
  'thumbnail' =>'',
20
  'thumbnail_size' =>'',
21
  'offset'=>'',
@@ -37,6 +38,7 @@
37
  $showauthor = strip_tags($instance['show_author']);
38
  $exclude = strip_tags($instance['exclude']);
39
  $excludeposts = strip_tags($instance['excludeposts']);
 
40
  $offset = strip_tags($instance['offset']);
41
  $showcatlink = strip_tags($instance['show_catlink']);
42
  $categoryid = strip_tags($instance['categoryid']);
@@ -166,6 +168,16 @@
166
  value="<?php echo esc_attr($excludeposts); ?>" />
167
  </p>
168
 
 
 
 
 
 
 
 
 
 
 
169
  <p>
170
  <?php $image_sizes = get_intermediate_image_sizes() ?>
171
  <label><?php _e("Show", 'list-category-posts')?>: </label><br/>
16
  'excerpt_size' =>'',
17
  'exclude'=>'',
18
  'excludeposts'=>'',
19
+ 'includeposts'=>'',
20
  'thumbnail' =>'',
21
  'thumbnail_size' =>'',
22
  'offset'=>'',
38
  $showauthor = strip_tags($instance['show_author']);
39
  $exclude = strip_tags($instance['exclude']);
40
  $excludeposts = strip_tags($instance['excludeposts']);
41
+ $includeposts = strip_tags($instance['includeposts']);
42
  $offset = strip_tags($instance['offset']);
43
  $showcatlink = strip_tags($instance['show_catlink']);
44
  $categoryid = strip_tags($instance['categoryid']);
168
  value="<?php echo esc_attr($excludeposts); ?>" />
169
  </p>
170
 
171
+ <p>
172
+ <label for="<?php echo $this->get_field_id('includeposts'); ?>">
173
+ <?php _e("Include posts (id's)", 'list-category-posts')?>
174
+ </label>
175
+ <br/>
176
+ <input id="<?php echo $this->get_field_id('includeposts'); ?>"
177
+ name="<?php echo $this->get_field_name('includeposts'); ?>" type="text"
178
+ value="<?php echo esc_attr($includeposts); ?>" />
179
+ </p>
180
+
181
  <p>
182
  <?php $image_sizes = get_intermediate_image_sizes() ?>
183
  <label><?php _e("Show", 'list-category-posts')?>: </label><br/>
include/lcp-widget.php CHANGED
@@ -25,6 +25,8 @@ class ListCategoryPostsWidget extends WP_Widget{
25
  $excludeposts = $post->ID;
26
  if(!isset($excludeposts))
27
  $excludeposts = ($instance['excludeposts'] != '') ? $instance['excludeposts'] : 0;
 
 
28
  $offset = (is_numeric($instance['offset'])) ? $instance['offset'] : 0;
29
  $category_id = $instance['categoryid'];
30
  $dateformat = ($instance['dateformat']) ? $instance['dateformat'] : get_option('date_format');
@@ -58,6 +60,7 @@ class ListCategoryPostsWidget extends WP_Widget{
58
  'excerpt_size' => $excerptsize,
59
  'exclude' => $exclude,
60
  'excludeposts' => $excludeposts,
 
61
  'offset' => $offset,
62
  'catlink' => $showcatlink,
63
  'thumbnail' => $thumbnail,
@@ -114,6 +117,7 @@ class ListCategoryPostsWidget extends WP_Widget{
114
  $instance['order'] = strip_tags($new_instance['order']);
115
  $instance['exclude'] = strip_tags($new_instance['exclude']);
116
  $instance['excludeposts'] = strip_tags($new_instance['excludeposts']);
 
117
  $instance['offset'] = strip_tags($new_instance['offset']);
118
  $instance['categoryid'] = strip_tags($new_instance['categoryid']);
119
  $instance['dateformat'] = strip_tags($new_instance['dateformat']);
25
  $excludeposts = $post->ID;
26
  if(!isset($excludeposts))
27
  $excludeposts = ($instance['excludeposts'] != '') ? $instance['excludeposts'] : 0;
28
+ if(!isset($includeposts))
29
+ $includeposts = ($instance['includeposts'] != '') ? $instance['includeposts'] : 0;
30
  $offset = (is_numeric($instance['offset'])) ? $instance['offset'] : 0;
31
  $category_id = $instance['categoryid'];
32
  $dateformat = ($instance['dateformat']) ? $instance['dateformat'] : get_option('date_format');
60
  'excerpt_size' => $excerptsize,
61
  'exclude' => $exclude,
62
  'excludeposts' => $excludeposts,
63
+ 'includeposts' => $includeposts,
64
  'offset' => $offset,
65
  'catlink' => $showcatlink,
66
  'thumbnail' => $thumbnail,
117
  $instance['order'] = strip_tags($new_instance['order']);
118
  $instance['exclude'] = strip_tags($new_instance['exclude']);
119
  $instance['excludeposts'] = strip_tags($new_instance['excludeposts']);
120
+ $instance['includeposts'] = strip_tags($new_instance['includeposts']);
121
  $instance['offset'] = strip_tags($new_instance['offset']);
122
  $instance['categoryid'] = strip_tags($new_instance['categoryid']);
123
  $instance['dateformat'] = strip_tags($new_instance['dateformat']);
include/lcp-wrapper.php CHANGED
@@ -32,10 +32,10 @@ class LcpWrapper {
32
  elseif (empty($tag)):
33
  return $info;
34
  elseif (!empty($tag) && empty($css_class)) :
35
- return '<' . $tag . '>' . $info . '</' . $tag . '>';
36
  endif;
37
  $css_class = sanitize_html_class($css_class);
38
- return '<' . $tag . ' class="' . $css_class . '">' . $info . '</' . $tag . '>';
39
  endif;
40
  }
41
 
@@ -62,4 +62,31 @@ class LcpWrapper {
62
  }
63
  return $wrapped;
64
  }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  elseif (empty($tag)):
33
  return $info;
34
  elseif (!empty($tag) && empty($css_class)) :
35
+ return $this->to_html($tag, [], $info);
36
  endif;
37
  $css_class = sanitize_html_class($css_class);
38
+ return $this->to_html($tag, ['class' => $css_class], $info);
39
  endif;
40
  }
41
 
62
  }
63
  return $wrapped;
64
  }
65
+
66
+ /**
67
+ * Builds HTML elements.
68
+ *
69
+ * Wraps $content in HTML tag specified in $tag. If $close is false
70
+ * the closing tag is omitted (useful when $content is null and we only
71
+ * want to open the tag). $properties is an associative array with HTML
72
+ * properties.
73
+ *
74
+ * @param string $tag HTML tag (ex. 'p', 'div', 'li').
75
+ * @param array $properties Optional. HTML element properties in
76
+ * `'property_name' => value` format.
77
+ * @param string $content Optional. HTML element text content.
78
+ * @param boolean $close Optional. If false, closing tag is omitted.
79
+ * @return string Generated HTML.
80
+ */
81
+ public function to_html($tag, $properties=[], $content=null, $close=true) {
82
+ $props_str = '';
83
+ foreach ($properties as $property => $value) {
84
+ $props_str .= ' ' . $property . '="' . $value . '"';
85
+ }
86
+
87
+ $html = "<{$tag}" . $props_str . ">{$content}";
88
+ if ($close) $html .= "</{$tag}>";
89
+
90
+ return $html;
91
+ }
92
+ }
languages/list-category-posts-ga.po ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Translation of List category posts in Irish
2
+ # This file is distributed under the same license as the List category posts package.
3
+ msgid ""
4
+ msgstr ""
5
+ "PO-Revision-Date: 2017-04-10 14:49:20+0000\n"
6
+ "MIME-Version: 1.0\n"
7
+ "Content-Type: text/plain; charset=UTF-8\n"
8
+ "Content-Transfer-Encoding: 8bit\n"
9
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
10
+ "X-Generator: translate.foe-services.de/ReGlot/0.1\n"
11
+ "Project-Id-Version: List category posts\n"
12
+ "Language-Team: ChameleonJohn.com <jordan.silaen@chameleonjohn.com>\n"
13
+ "Language: Irish\n"
14
+
15
+ #: include/lcp_widget_form.php:40
16
+ msgid "Title"
17
+ msgstr "Teideal"
18
+
19
+ #: include/lcp_widget_form.php:47
20
+ msgid "Category"
21
+ msgstr "Catagóir"
22
+
23
+ #: include/lcp_widget_form.php:65
24
+ msgid "Number of posts"
25
+ msgstr "Líon na bpost"
26
+
27
+ #: include/lcp_widget_form.php:72
28
+ msgid "Offset"
29
+ msgstr "Fritháireamh"
30
+
31
+ #: include/lcp_widget_form.php:78
32
+ msgid "Order by"
33
+ msgstr "Ordú ag"
34
+
35
+ #: include/lcp_widget_form.php:81 include/lcp_widget_form.php:123
36
+ msgid "Date"
37
+ msgstr "Dáta"
38
+
39
+ #: include/lcp_widget_form.php:82
40
+ msgid "Post title"
41
+ msgstr "Post teideal"
42
+
43
+ #: include/lcp_widget_form.php:83 include/lcp_widget_form.php:127
44
+ msgid "Author"
45
+ msgstr "údar"
46
+
47
+ #: include/lcp_widget_form.php:84
48
+ msgid "Random"
49
+ msgstr "Randamach"
50
+
51
+ #: include/lcp_widget_form.php:88
52
+ msgid "Order"
53
+ msgstr "Ordú"
54
+
55
+ #: include/lcp_widget_form.php:91
56
+ msgid "Descending"
57
+ msgstr "Ag dul síos"
58
+
59
+ #: include/lcp_widget_form.php:92
60
+ msgid "Ascending"
61
+ msgstr "Ag dul suas"
62
+
63
+ #: include/lcp_widget_form.php:96
64
+ msgid "Exclude categories (id's)"
65
+ msgstr "Catagóirí Fág amach (id s)"
66
+
67
+ #: include/lcp_widget_form.php:102
68
+ msgid "Exclude posts (id's)"
69
+ msgstr "post Fág amach (id s)"
70
+
71
+ #: include/lcp_widget_form.php:109
72
+ msgid "Show"
73
+ msgstr "Taispeáin"
74
+
75
+ #: include/lcp_widget_form.php:112
76
+ msgid "Thumbnail - size"
77
+ msgstr "Mionsamhail - Méid"
78
+
79
+ #: include/lcp_widget_form.php:131
80
+ msgid "Link to category"
81
+ msgstr "Nasc le catagóir"
82
+
83
+ #: include/lcp_widget_form.php:135
84
+ msgid "Excerpt"
85
+ msgstr "sliocht"
86
+
87
+ #: include/lcp_widget_form.php:138
88
+ msgid "More link"
89
+ msgstr "níos mó link"
90
+
91
+ #: include/ListCategoryPostsWidget.php:5
92
+ msgid "List Category Posts allows you to list posts from a category into a post/page using the [catlist] shortcode. This shortcode accepts a category name or id, the order in which you want the posts to display, and the number of posts to display. You can use [catlist] as many times as needed with different arguments. Usage: [catlist argument1=value1 argument2=value2]."
93
+ msgstr "Liosta Category Poist is féidir leat chun poist ó aicme liosta isteach ar phost / leathanach ag baint úsáide as an [Catlist] shortcode. Glacann an shortcode ainm catagóir nó id, an t-ord inar mian leat na poist a chur ar taispeáint, agus an líon post a chur ar taispeáint. Is féidir leat úsáid a bhaint [Catlist] mar a mhéad uair mar is gá le hargóintí éagsúla. Úsáid: [Catlist argument1 = value1 argument2 = value2]."
94
+
95
+ #: include/ListCategoryPostsWidget.php:11
96
+ msgid "List posts from a specified category"
97
+ msgstr "post Liosta ó earnáil shonraithe"
98
+
99
+ #: include/ListCategoryPostsWidget.php:12
100
+ msgid "List Category Posts"
101
+ msgstr "Liosta Category Poist"
102
+
list-category-posts.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: List category posts
4
  Plugin URI: https://github.com/picandocodigo/List-Category-Posts
5
  Description: List Category Posts allows you to list posts by category in a post/page using the [catlist] shortcode. This shortcode accepts a category name or id, the order in which you want the posts to display, the number of posts to display and many more parameters. You can use [catlist] as many times as needed with different arguments. Usage: [catlist argument1=value1 argument2=value2].
6
- Version: 0.83.1
7
  Author: Fernando Briano
8
  Author URI: http://fernandobriano.com
9
 
@@ -64,6 +64,7 @@ class ListCategoryPosts{
64
  'excerpt_class' =>'',
65
  'exclude' => '0',
66
  'excludeposts' => '0',
 
67
  'offset' => '0',
68
  'tags' => '',
69
  'exclude_tags' => '',
@@ -109,6 +110,7 @@ class ListCategoryPosts{
109
  'customfield_orderby' =>'',
110
  'customfield_tag' => '',
111
  'customfield_class' => '',
 
112
  'taxonomy' => '',
113
  'taxonomies_and' => '',
114
  'taxonomies_or' => '',
@@ -116,6 +118,8 @@ class ListCategoryPosts{
116
  'categorypage' => '',
117
  'category_count' => '',
118
  'category_description' => 'no',
 
 
119
  'morelink' => '',
120
  'morelink_class' => '',
121
  'morelink_tag' => '',
3
  Plugin Name: List category posts
4
  Plugin URI: https://github.com/picandocodigo/List-Category-Posts
5
  Description: List Category Posts allows you to list posts by category in a post/page using the [catlist] shortcode. This shortcode accepts a category name or id, the order in which you want the posts to display, the number of posts to display and many more parameters. You can use [catlist] as many times as needed with different arguments. Usage: [catlist argument1=value1 argument2=value2].
6
+ Version: 0.84
7
  Author: Fernando Briano
8
  Author URI: http://fernandobriano.com
9
 
64
  'excerpt_class' =>'',
65
  'exclude' => '0',
66
  'excludeposts' => '0',
67
+ 'includeposts' => '0',
68
  'offset' => '0',
69
  'tags' => '',
70
  'exclude_tags' => '',
110
  'customfield_orderby' =>'',
111
  'customfield_tag' => '',
112
  'customfield_class' => '',
113
+ 'customfield_compare' => '',
114
  'taxonomy' => '',
115
  'taxonomies_and' => '',
116
  'taxonomies_or' => '',
118
  'categorypage' => '',
119
  'category_count' => '',
120
  'category_description' => 'no',
121
+ 'category_description_tag' => '',
122
+ 'category_description_class' => '',
123
  'morelink' => '',
124
  'morelink_class' => '',
125
  'morelink_tag' => '',
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: fernandobt, zymeth25
3
  Donate Link: http://picandocodigo.net/programacion/wordpress/list-category-posts-wordpress-plugin-english/#support
4
  Tags: list, categories, posts, cms
5
  Requires at least: 3.3
6
- Tested up to: 5.4.2
7
  Requires PHP: 5.4
8
- Stable tag: 0.83.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -60,7 +60,7 @@ Some users have made videos on how to use the plugin (thank you, you are awesome
60
 
61
  **Support the plugin**
62
 
63
- Klemens Starybrat has been writing lots of amazing code for this plugin, so if you've found it useful and want to pay it forward, consider sponsoring him on GitHub: https://github.com/sponsors/zymeth25
64
 
65
  I have a [PayPal account](http://picandocodigo.net/programacion/wordpress/list-category-posts-wordpress-plugin-english/#support "Donate via PayPal") where you can donate too.
66
 
@@ -232,6 +232,19 @@ Template system has changed. Custom templates should be stored in WordPress them
232
 
233
  == Changelog ==
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  = 0.83.1 =
236
 
237
  * Fixes bug with order parameter after refactor: https://wordpress.org/support/topic/notice-undefined-variable-params/
3
  Donate Link: http://picandocodigo.net/programacion/wordpress/list-category-posts-wordpress-plugin-english/#support
4
  Tags: list, categories, posts, cms
5
  Requires at least: 3.3
6
+ Tested up to: 5.7.1
7
  Requires PHP: 5.4
8
+ Stable tag: 0.84
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
60
 
61
  **Support the plugin**
62
 
63
+ Klemens Starybrat has been writing lots of amazing code for this plugin, so if you've found it useful and want to pay it forward, consider sponsoring him on GitHub: https://github.com/sponsors/klemens-st
64
 
65
  I have a [PayPal account](http://picandocodigo.net/programacion/wordpress/list-category-posts-wordpress-plugin-english/#support "Donate via PayPal") where you can donate too.
66
 
232
 
233
  == Changelog ==
234
 
235
+ = 0.84.0 =
236
+
237
+ * **New feature**: Select specific posts by IDs: `[catlist includeposts="2,97"]`. Thanks @hvianna!
238
+ * **New feature:** Advanced customfield filtering with `customfield_compare`, see [the docs](https://github.com/picandocodigo/List-Category-Posts/wiki/How-to-select-which-posts-to-show#other-ways-of-selecting-what-posts-to-show) for instructions.
239
+ * **New feature:** It is now possible to style `category_description` with `category_description_tag` and `category_description_class`.
240
+ * Changed the default wrapper tag for `content=yes` to `<div>` to avoid generating invalid HTML (previously `<p>`).
241
+ * Fixed `excerpt_full` not being run through `the_excerpt` filters (thanks @StefanXRoos!). The filters are now applied same as for `excerpt_yes`. **Please check your setup** if you are using `excerpt_full`.
242
+ * Fixed `display_id` bug, thanks for reporting @fiestoforo!
243
+ * Fixed PHP warnings in WP admin caused by the widget, thanks for reporting @hiskingdomprophecy (#420).
244
+ * Fixed `posts_where` filter not being properly removed when using `starting_with`.
245
+ * Full refactor of HTML generation making it easier to maintain.
246
+ * Upgraded PHP to 7.4 in the Vagrant machine.
247
+
248
  = 0.83.1 =
249
 
250
  * Fixes bug with order parameter after refactor: https://wordpress.org/support/topic/notice-undefined-variable-params/
templates/default.php CHANGED
@@ -41,7 +41,7 @@ $lcp_display_output = '';
41
  $lcp_display_output .= $this->get_category_link('strong');
42
 
43
  // Show category description:
44
- $lcp_display_output .= $this->get_category_description();
45
 
46
  // Show the conditional title:
47
  $lcp_display_output .= $this->get_conditional_title();
@@ -96,9 +96,9 @@ while ( have_posts() ):
96
 
97
  /**
98
  * Post content - Example of how to use tag and class parameters:
99
- * This will produce:<p class="lcp_content">The content</p>
100
  */
101
- $lcp_display_output .= $this->get_content($post, 'p', 'lcp_content');
102
 
103
  /**
104
  * Post content - Example of how to use tag and class parameters:
41
  $lcp_display_output .= $this->get_category_link('strong');
42
 
43
  // Show category description:
44
+ $lcp_display_output .= $this->get_category_description('p');
45
 
46
  // Show the conditional title:
47
  $lcp_display_output .= $this->get_conditional_title();
96
 
97
  /**
98
  * Post content - Example of how to use tag and class parameters:
99
+ * This will produce:<div class="lcp_content">The content</div>
100
  */
101
+ $lcp_display_output .= $this->get_content($post, 'div', 'lcp_content');
102
 
103
  /**
104
  * Post content - Example of how to use tag and class parameters: