PluginProbe
Same Category Posts / 1.1.4
Same Category Posts v1.1.4
1.2.0 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 trunk 1.0 1.0.1 1.0.10 1.0.11 1.0.12 All 36 releases
same-category-posts / same-category-posts.php

same-category-posts.php in Same Category Posts 1.1.4, at same-category-posts.php

1,007 lines 40.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Same Category Posts
4 Plugin URI: https://wordpress.org/plugins/same-category-posts/
5 Description: Adds a widget that shows the most recent posts from a single category.
6 Author: Daniel Floeter
7 Version: 1.1.4
8 Author URI: https://profiles.wordpress.org/kometschuh/
9 */
10
11 namespace sameCategoryPosts;
12
13 // Don't call the file directly
14 if ( !defined( 'ABSPATH' ) ) exit;
15
16 define( 'SAME_CATEGORY_POSTS_VERSION', "1.1.1");
17
18 /**
19 * Register our styles
20 *
21 * @return void
22 */
23 function same_category_posts_styles() {
24 wp_register_style( 'same-category-posts', plugins_url( 'same-category-posts/same-category-posts.css' ) );
25 wp_enqueue_style( 'same-category-posts' );
26 }
27 add_action( 'wp_enqueue_scripts', __NAMESPACE__.'\same_category_posts_styles' );
28
29 /**
30 * Register our admin scripts
31 *
32 * @return void
33 */
34 function same_category_posts_admin_scripts($hook) {
35 wp_register_script( 'same_category-posts-admin-js', plugins_url( 'same-category-posts/js/admin/same-category-posts.js' ), array('jquery') , SAME_CATEGORY_POSTS_VERSION , true );
36 wp_enqueue_script( 'same_category-posts-admin-js' );
37 }
38 add_action('admin_enqueue_scripts', __NAMESPACE__.'\same_category_posts_admin_scripts');
39
40 /**
41 * Add styles for widget sections
42 *
43 */
44 function admin_styles() {
45 ?>
46 <style>
47 .same-category-widget-cont h4 {
48 padding: 12px 15px;
49 cursor: pointer;
50 margin: 5px 0;
51 border: 1px solid #E5E5E5;
52 }
53 .same-category-widget-cont h4:first-child {
54 margin-top: 10px;
55 }
56 .same-category-widget-cont h4:last-of-type {
57 margin-bottom: 10px;
58 }
59 .same-category-widget-cont h4:after {
60 float:right;
61 font-family: "dashicons";
62 content: '\f140';
63 -ms-transform: translate(-1px,1px);
64 -webkit-transform: translate(-1px,1px);
65 -moz-transform: translate(-1px,1px);
66 transform: translate(-1px,1px);
67 -ms-transition: all 600ms;
68 -webkit-transition: all 600ms;
69 -moz-transition: all 600ms;
70 transition: all 600ms;
71 }
72 .same-category-widget-cont h4.open:after {
73 -ms-transition: all 600ms;
74 -webkit-transition: all 600ms;
75 -moz-transition: all 600ms;
76 transition: all 600ms;
77 -ms-transform: rotate(180deg);
78 -webkit-transform: rotate(180deg);
79 -moz-transform: rotate(180deg);
80 transform: rotate(180deg);
81 }
82 .same-category-widget-cont > div {
83 display:none;
84 overflow: hidden;
85 }
86 .same-category-widget-cont > div.open {
87 display:block;
88 }
89 <?php //disable taxterms?>
90 select[disabled] {
91 background: #ececec !important;
92 }
93
94 select[disabled] option {
95 color: #c3c3c3;
96 }
97 </style>
98 <?php
99 }
100
101 add_action( 'admin_print_styles-widgets.php', __NAMESPACE__.'\admin_styles' );
102
103 /**
104 * Get image size
105 *
106 * $thumb_w, $thumb_h - the width and height of the thumbnail in the widget settings
107 * $image_w,$image_h - the width and height of the actual image being displayed
108 *
109 * return: an array with the width and height of the element containing the image
110 */
111 function same_category_posts_get_image_size( $thumb_w,$thumb_h,$image_w,$image_h) {
112
113 $image_size = array('image_h' => $thumb_h, 'image_w' => $thumb_w, 'marginAttr' => '', 'marginVal' => '');
114 $relation_thumbnail = $thumb_w / $thumb_h;
115 $relation_cropped = $image_w / $image_h;
116
117 if ($relation_thumbnail < $relation_cropped) {
118 // crop left and right site
119 // thumbnail width/height ration is smaller, need to inflate the height of the image to thumb height
120 // and adjust width to keep aspect ration of image
121 $image_size['image_h'] = $thumb_h;
122 $image_size['image_w'] = $thumb_h / $image_h * $image_w;
123 $image_size['marginAttr'] = 'margin-left';
124 $image_size['marginVal'] = ($image_size['image_w'] - $thumb_w) / 2;
125 } else {
126 // crop top and bottom
127 // thumbnail width/height ration is bigger, need to inflate the width of the image to thumb width
128 // and adjust height to keep aspect ration of image
129 $image_size['image_w'] = $thumb_w;
130 $image_size['image_h'] = $thumb_w / $image_w * $image_h;
131 $image_size['marginAttr'] = 'margin-top';
132 $image_size['marginVal'] = ($image_size['image_h'] - $thumb_h) / 2;
133 }
134
135 return $image_size;
136 }
137
138 /**
139 * Related Posts Widget Class
140 *
141 * Shows posts from same category with some configurable options
142 */
143 class Widget extends \WP_Widget {
144
145 function __construct() {
146 $widget_ops = array('classname' => 'same-category-posts', 'description' => __('List posts from same category in sidebar based on shown post\'s category'));
147 parent::__construct('same-category-posts', __('Same Category Posts'), $widget_ops);
148 }
149
150 /*
151 override the thumbnail htmo to insert cropping when needed
152 */
153 function post_thumbnail_html($html, $post_id, $post_thumbnail_id, $size, $attr){
154 if ( empty($this->instance['thumb_w']) || empty($this->instance['thumb_h']))
155 return $html; // bail out if no full dimensions defined
156
157 $meta = image_get_intermediate_size($post_thumbnail_id,$size);
158
159 if ( empty( $meta )) {
160 $post_img = wp_get_attachment_metadata($post_thumbnail_id, $size);
161 $meta['file'] = basename( $post_img['file'] );
162 }
163
164 $origfile = get_attached_file( $post_thumbnail_id, true); // the location of the full file
165 $file = dirname($origfile) .'/'.$meta['file']; // the location of the file displayed as thumb
166 list( $width, $height ) = getimagesize($file); // get actual size of the thumb file
167
168 if ($width / $height == $this->instance['thumb_w'] / $this->instance['thumb_h']) {
169 // image is same ratio as asked for, nothing to do here as the browser will handle it correctly
170 ;
171 } else if (isset($this->instance['use_css_cropping'])) {
172 $image = same_category_posts_get_image_size($this->instance['thumb_w'],$this->instance['thumb_h'],$width,$height);
173
174 // replace srcset
175 $array = array();
176 preg_match( '/width="([^"]*)"/i', $html, $array ) ;
177 $pattern = "/".$array[1]."w/";
178 $html = preg_replace($pattern, $image['image_w']."w", $html);
179 // replace size
180 $pattern = "/".$array[1]."px/";
181 $html = preg_replace($pattern, $image['image_w']."px", $html);
182 // replace width
183 $pattern = "/width=\"[0-9]*\"/";
184 $html = preg_replace($pattern, "width='".$image['image_w']."'", $html);
185 // replace height
186 $pattern = "/height=\"[0-9]*\"/";
187 $html = preg_replace($pattern, "height='".$image['image_h']."'", $html);
188 // set margin
189 $html = str_replace('<img ','<img style="'.$image['marginAttr'].':-'.$image['marginVal'].'px;height:'.$image['image_h']
190 .'px;clip:rect(auto,'.($this->instance['thumb_w']+$image['marginVal']).'px,auto,'.$image['marginVal']
191 .'px);width:auto;max-width:initial;" ',$html);
192 // wrap span
193 $html = '<span style="width:'.$this->instance['thumb_w'].'px;height:'.$this->instance['thumb_h'].'px;">'
194 .$html.'</span>';
195 } else {
196 // if use_css_cropping not used
197 // no interface changes: leave without change
198 }
199 return $html;
200 }
201
202 /*
203 wrapper to execute the the_post_thumbnail with filters
204 */
205 function the_post_thumbnail($size= 'post-thumbnail',$attr='') {
206 if (empty($size)) // if junk value, make it a normal thumb
207 $size= 'post-thumbnail';
208 else if (is_array($size) && (count($size)==2)) { // good format at least
209 // normalize to ints first
210 $size[0] = (int) $size[0];
211 $size[1] = (int) $size[1];
212 if (($size[0] == 0) && ($size[1] == 0)) //both values zero then revert to thumbnail
213 $size= 'post-thumbnail';
214 // if one value is zero make a square using the other value
215 else if (($size[0] == 0) && ($size[1] != 0))
216 $size[0] = $size[1];
217 else if (($size[0] != 0) && ($size[1] == 0))
218 $size[1] = $size[0];
219 } else
220 $size= 'post-thumbnail'; // yet another form of junk
221
222 add_filter('post_thumbnail_html',array($this,'post_thumbnail_html'),1,5);
223 $ret = get_the_post_thumbnail( null,$size,'');
224 remove_filter('post_thumbnail_html',array($this,'post_thumbnail_html'),1,5);
225 return $ret;
226 }
227
228 /**
229 * Calculate the HTML for showing the thumb of a post item.
230 * Expected to be called from a loop with globals properly set
231 *
232 * @param array $instance Array which contains the various settings
233 * @return string The HTML for the thumb related to the post
234 *
235 * @since 1.0.8
236 */
237 function show_thumb($instance) {
238 $ret = '';
239
240 if ( function_exists('the_post_thumbnail') &&
241 current_theme_supports("post-thumbnails") &&
242 isset ( $this->instance["thumb"] ) &&
243 has_post_thumbnail() ) {
244 $ret .= '<a ';
245 $use_css_cropping = isset($this->instance['use_css_cropping']) ? "same-category-post-css-cropping" : "";
246 $ret .= 'class="same-category-post-thumbnail ' . $use_css_cropping . '"';
247 $ret .= 'href="' . get_the_permalink() . '" title="' . get_the_title() . '">';
248 $ret .= $this->the_post_thumbnail( array($this->instance['thumb_w'],$this->instance['thumb_h']));
249 $ret .= '</a>';
250 }
251 return $ret;
252 }
253
254 /**
255 * Excerpt more link filter
256 */
257 function excerpt_more_filter($more) {
258 return ' <a class="cat-post-excerpt-more" href="'. get_permalink() . '">' . esc_html($this->instance["excerpt_more_text"]) . '</a>';
259 }
260
261 /**
262 * Calculate the HTML for a post item based on the widget settings and post.
263 * Expected to be called in an active loop with all the globals set
264 *
265 * @param array $instance Array which contains the various settings
266 * $param null|integer $current_post_id If on singular page specifies the id of
267 * the post, otherwise null
268 * @return string The HTML for item related to the post
269 *
270 * @since 1.0.8
271 */
272 function itemHTML($instance,$current_post_id) {
273 global $post;
274
275 $ret = '<li class="same-category-post-item ' . ($post->ID == $current_post_id ? 'same-category-post-current' : '') . '">';
276
277 if( isset( $instance["thumbTop"] ) ) :
278 $ret .= $this->show_thumb($instance);
279 endif;
280
281 $ret .= '<a class="post-title" href="' . get_the_permalink() . '" rel="bookmark" title="Permanent Link to ' . get_the_title() . '">' . get_the_title() . '</a>';
282
283 if ( isset( $instance['date'] ) ) {
284 if (isset($instance['date_format']) && strlen(trim($instance['date_format'])) > 0)
285 $date_format = $instance['date_format'];
286 else if (isset($instance['use_wp_date_format']) && strlen(trim($instance['use_wp_date_format'])) > 0)
287 $date_format = "";
288 else
289 $date_format = "j M Y";
290
291 $ret .= '<p class="post-date">';
292
293 if (isset($instance["date_link"]) && $instance["date_link"])
294 $ret .= '<a href="'.get_the_permalink().'">';
295
296 $ret .= get_the_date($date_format);
297
298 if (isset($instance["date_link"]) && $instance["date_link"])
299 $ret .= '</a>';
300
301 $ret .= '</p>';
302 }
303
304 if( !isset( $instance["thumbTop"] ) ) :
305 $ret .= $this->show_thumb($instance);
306 endif;
307
308 if ( isset ( $instance['excerpt'] ) ) {
309 $ret .= apply_filters('the_excerpt', get_the_excerpt());;
310 }
311
312 if ( isset ( $instance['comment_num'] ) ) {
313 $ret .= '<p class="same-category-post-comment-num">(' . get_comments_number() . ')</p>';
314 }
315
316 if ( isset( $instance['author'] ) ) {
317 $ret .= '<p class="post-author cat-post-author">';
318 $ret .= get_the_author_posts_link();
319 $ret .= '</p>';
320 }
321
322 $ret .= '</li>';
323 return $ret;
324 }
325 /**
326
327 * Set for each object_taxonomy the hierarchical post_type as default, if no tax is selected
328 *
329 * @param array &$instance
330 * @return by ref
331 */
332 function initPostTypesAndTaxes(&$instance) {
333 $post_types = get_post_types( array( 'publicly_queryable' => true ) );
334 foreach ($post_types as $post_type) {
335 $object_taxes = get_object_taxonomies( $post_type, 'objects' );
336
337 $set_default = true;
338 foreach ( $object_taxes as $tax ) {
339 if (isset($instance['include_tax'][$post_type]) && $instance['include_tax'][$post_type]) {
340 if ($tax->name == $instance['include_tax'][$post_type])
341 $set_default = false;
342 }
343 // put all taxes and the associated post_type
344 if ($tax->hierarchical) {
345 $instance['post_types'][$tax->name] = array( 'post_type'=>$post_type, 'hierarchical'=>true );
346 } else {
347 $instance['post_types'][$tax->name] = array( 'post_type'=>$post_type, 'hierarchical'=>false );
348 }
349 }
350 // put and set only 'default' taxes
351 if ($set_default) {
352 foreach ( $object_taxes as $tax ) {
353 if ($tax->hierarchical) {
354 $instance['include_tax'][$post_type] = $tax->name; // set as 'default'
355 }
356 }
357 }
358 }
359 }
360
361 // Displays a list of posts from same category on single post pages.
362 function widget($args, $instance) {
363 // Only show widget if on a post page.
364 if ( !is_single() ) return;
365
366 global $wp_query;
367 $post_old = $post; // Save the post object.
368 $post = $wp_query->post;
369 $current_post_id = $post->ID;
370
371 extract( $args );
372 $this->instance = $instance;
373
374 $this->initPostTypesAndTaxes($instance);
375
376 // Get taxonomies
377 $taxonomies = null;
378 $taxes = get_object_taxonomies( $post );
379 $categories = null;
380 foreach ($taxes as $tax) {
381 $post_type = $instance['post_types'][$tax]['post_type'];
382 if ($tax == $instance['include_tax'][$post_type]) {
383 $terms = get_the_terms($post->ID, $tax);
384 if ($terms) {
385 foreach ($terms as $term) {
386 $taxonomies[$tax][] = $term->term_id;
387 }
388 }
389 $categories = get_the_terms($post->ID,$tax);
390 }
391 }
392
393 // Excerpt length filter
394 if ( isset($instance["excerpt_length"]) && $instance["excerpt_length"] > 0 ) {
395 $new_excerpt_length = create_function('$length', "return " . $instance["excerpt_length"] . ";");
396 add_filter('excerpt_length', $new_excerpt_length);
397 }
398
399 $valid_sort_orders = array('date', 'title', 'comment_count', 'rand');
400 if ( isset($instance['sort_by']) && in_array($instance['sort_by'], $valid_sort_orders) ) {
401 $sort_by = $instance['sort_by'];
402 $sort_order = (bool) isset( $instance['asc_sort_order'] ) ? 'ASC' : 'DESC';
403 } else {
404 // by default, display latest first
405 $sort_by = 'date';
406 $sort_order = 'DESC';
407 }
408
409 // Excerpt more_text
410 if( isset($instance["excerpt_more_text"]) && ltrim($instance["excerpt_more_text"]) != '' )
411 {
412 add_filter('excerpt_more', array($this,'excerpt_more_filter'));
413 }
414
415 // deprecate >= 1.0.12: 'exclude_categories' get 'exclude_terms'
416 // Exclude categories
417 if (!isset($instance['exclude_terms']['category']) && isset($instance['exclude_categories']) && $instance['exclude_categories'])
418 $instance['exclude_terms'] = array( 'category' => $instance['exclude_categories']);
419
420 // Query args
421 $args = array(
422 'orderby' => $sort_by,
423 'order' => $sort_order
424 );
425
426 $args['post_type'] = array( get_post_type( $post ) );
427
428 if ($taxonomies) {
429 $term_query_in = array('relation' => 'OR');
430 foreach ( $taxonomies as $tax=>$terms) {
431 if ( isset($instance['exclude_terms']) && $instance['exclude_terms'] && array_key_exists($tax, $instance['exclude_terms']) )
432 $terms = array_diff($terms, $instance['exclude_terms'][$tax]);
433 if ($terms) {
434 $term_query_in[] = array(
435 'taxonomy' => $tax,
436 'field' => 'term_id',
437 'terms' => $terms,
438 'include_children' => isset($instance['exclude_children']) && $instance['exclude_children'] ? false : true,
439 'operator' => 'IN',
440 );
441 }
442 }
443 }
444
445 $term_query_not_in = null;
446 if ( isset($instance['exclude_terms']) && $instance['exclude_terms'] ) {
447 foreach ( $instance['exclude_terms'] as $tax=>$terms) {
448 $post_type = $instance['post_types'][$tax]['post_type'];
449 if ($tax == $instance['include_tax'][$post_type]) {
450 $term_query_not_in[] = array(
451 'taxonomy' => $tax,
452 'field' => 'term_id',
453 'terms' => $instance['exclude_terms'][$tax],
454 'include_children' => isset($instance['exclude_no_children']) && $instance['exclude_no_children'] ? false : true,
455 'operator' => 'NOT IN',
456 );
457 }
458 }
459 }
460
461 $term_query[] = array('relation' => 'AND');
462 $term_query[] = $term_query_in;
463 $term_query[] = $term_query_not_in;
464
465 if (is_array($term_query))
466 $args['tax_query'] = $term_query;
467
468 $args['post__not_in'] = array();
469 if (isset( $instance['exclude_current_post'] ) && $instance['exclude_current_post']) {
470 $args['post__not_in'] = array( $current_post_id );
471 }
472
473 if(isset( $instance['exclude_sticky_posts'] ) && $instance['exclude_sticky_posts']) {
474 foreach (get_option( 'sticky_posts' ) as $value) {
475 $args['post__not_in'][] = $value;
476 }
477 }
478
479 $args['posts_per_page'] = (isset($instance['num']) && $instance['num']) ? $instance['num'] : -1;
480
481 $my_query = new \WP_Query($args);
482
483 if( $my_query->have_posts() )
484 {
485 echo $before_widget;
486
487 // Widget title
488 if( !isset ( $instance["hide_title"] ) ) {
489 if( isset( $instance["separate_categories"] ) && $instance["separate_categories"] ) {
490 // Separate categories: title to array
491 foreach($categories as $cat) {
492 $widgetHTML[$cat->name]['ID'] = $cat->term_id;
493 if( isset ( $instance["title_link"] ) ) {
494 $title = '<a href="' . get_category_link( $cat ) . '">'. $cat->name . '</a>';
495 if(isset($instance['title']) && strpos($instance['title'], '%cat-all%') !== false)
496 $title = str_replace( "%cat-all%", $title, $instance['title']);
497 else if(isset($instance['title']) && strpos($instance['title'], '%cat%') !== false)
498 $title = str_replace( "%cat%", $title, $instance['title']);
499 $widgetHTML[$cat->name]['title'] = $title;
500 } else {
501 $title = $cat->name;
502 if(isset($instance['title']) && strpos($instance['title'], '%cat-all%') !== false)
503 $title = str_replace( "%cat-all%", $title, $instance['title']);
504 else if(isset($instance['title']) && strpos($instance['title'], '%cat%') !== false)
505 $title = str_replace( "%cat%", $title, $instance['title']);
506 $widgetHTML[$cat->name]['title'] = $title;
507 }
508 }
509 } else {
510 // ! Separate categories: echo
511 echo $before_title;
512 if( isset ( $instance["title_link"] ) ) {
513 $linkList = "";
514 foreach($categories as $cat) {
515 if(isset($instance['exclude_terms']) && $instance['exclude_terms'] && in_array($cat->term_id,$instance['exclude_terms']))
516 continue;
517 $linkList .= '<a href="' . get_category_link( $cat ) . '">'. $cat->name . '</a>, ';
518 }
519 $linkList = trim($linkList, ", ");
520 if( isset($instance['title']) && $instance['title'] ) { // use placeholders if title is not empty
521 if(strpos($instance['title'], '%cat-all%') !== false ||
522 strpos($instance['title'], '%cat%') !== false) { // all-category placeholder is used
523 if(strpos($instance['title'], '%cat-all%') !== false)
524 $linkList = str_replace( "%cat-all%", $linkList, $instance['title']);
525 else if(strpos($instance['title'], '%cat%') !== false)
526 $linkList = str_replace( "%cat%", '<a href="' . get_category_link( $categories[0] ) . '">'. $categories[0]->name . '</a>', $instance['title']);
527 } else // no category placeholder is used
528 $linkList = '<a href="' . get_category_link( $categories[0] ) . '">'. $instance['title'] . '</a>';
529 }
530 echo htmlspecialchars_decode(apply_filters('widget_title',$linkList));
531 } else {
532 $categoryNames = "";
533 if ($categories) {
534 foreach ($categories as $key => $val) {
535 if(isset($instance['exclude_terms']) && $instance['exclude_terms'] && in_array($val->term_id,$instance['exclude_terms'][$val->taxonomy]))
536 continue;
537 $categoryNames .= $val->name . ", ";
538 }
539 $categoryNames = trim($categoryNames, ", ");
540 }
541
542 if( isset($instance['title']) && $instance['title'] ) { // use placeholders if title is not empty
543 if(strpos($instance['title'], '%cat-all%') !== false) // all-category placeholder is used
544 $categoryNames = str_replace( "%cat-all%", $categoryNames, $instance['title']);
545 else if(strpos($instance['title'], '%cat%') !== false) // one-category placeholder is used
546 $categoryNames = str_replace( "%cat%", $categories[0]->name, $instance['title']);
547 else
548 $categoryNames = $instance['title'];
549 }
550 echo htmlspecialchars_decode(apply_filters('widget_title',$categoryNames));
551 }
552 echo $after_title;
553 }
554 }
555 // /Widget title
556
557 // Post list
558 echo "<ul>\n";
559 while ($my_query->have_posts())
560 {
561 $my_query->the_post();
562
563 if( isset( $instance["separate_categories"] ) && $instance["separate_categories"] ) {
564 // Separate categories: get itemHTML to array
565 $object_taxes = get_object_taxonomies( $post, 'objects' );
566 $post_categories = null;
567 foreach ( $object_taxes as $tax ) {
568 $post_type = $instance['post_types'][$tax->name]['post_type'];
569 if ($tax->name == $instance['include_tax'][$post_type]) {
570 $post_categories = get_the_terms($post->ID,$tax->name);
571 break;
572 }
573 }
574 foreach ($post_categories as $val) {
575 $widgetHTML[$val->name][$post->ID]['itemHTML'] = $this->itemHTML($instance,$current_post_id);
576 $widgetHTML[$val->name][$post->ID]['ID'] = $post->ID;
577 }
578 } else {
579 // ! Separate categories: get itemHTML and echo
580 echo $this->itemHTML($instance,$current_post_id);
581 }
582 } // end while
583
584 if (isset( $instance["separate_categories"] ) && $instance["separate_categories"]) {
585 // Separate categories: echo
586 $isOnPage = array();
587 foreach($widgetHTML as $val) {
588 // widget title
589 $haveItemHTML = false;
590 $ret = $before_title . htmlspecialchars_decode(apply_filters('widget_title',isset($val['title'])?$val['title']:"")) . $after_title;
591 $count = 1;
592 $num_per_cat = (isset($instance['num_per_cate'])&&$instance['num_per_cate']!=0?($instance['num_per_cate']):99999);
593 foreach($val as $key) {
594 if(is_array($key) && array_key_exists('itemHTML', $key)) {
595 if( !in_array($key['ID'], $isOnPage) ) {
596 if($count <= $num_per_cat) {
597 $ret .= $key['itemHTML'];
598 $haveItemHTML = true;
599 $isOnPage[] = $key['ID'];
600 } else
601 break;
602 $count++;
603 }
604 }
605 }
606 if ($haveItemHTML)
607 echo $ret;
608 }
609 }
610
611 echo "</ul>\n";
612 // end Post list
613
614 echo $after_widget;
615 }
616
617 if(isset($new_excerpt_length))
618 remove_filter('excerpt_length', $new_excerpt_length);
619 remove_filter('excerpt_more', array($this,'excerpt_more_filter'));
620
621 $post = $post_old; // Restore the post object.
622 }
623
624 /**
625 * Update the options
626 *
627 * @param array $new_instance
628 * @param array $old_instance
629 * @return array
630 */
631 function update($new_instance, $old_instance) {
632
633 return $new_instance;
634 }
635
636 /**
637 * The widget configuration form back end.
638 *
639 * @param array $instance
640 * @return void
641 */
642 function form($instance) {
643
644 // ToDo seperate_cat get seperate_tax (if update, settings)
645
646 $this->initPostTypesAndTaxes($instance);
647
648 $instance = wp_parse_args( ( array ) $instance, array(
649 'title' => '',
650 'hide_title' => '',
651 'separate_categories' => '',
652 'num_per_cate' => '',
653 'num' => '',
654 'exclude_no_children' => '',
655 'exclude_children' => '',
656 'sort_by' => '',
657 'asc_sort_order' => '',
658 'title_link' => '',
659 'exclude_categories' => '',
660 'exclude_terms' => array(),
661 'include_tax' => array(),
662 'post_types' => array(),
663 'exclude_current_post' => '',
664 'exclude_sticky_posts' => '',
665 'author' => '',
666 'date_format' => '',
667 'use_wp_date_format' => '',
668 'date_link' => '',
669 'excerpt' => '',
670 'excerpt_length' => '',
671 'excerpt_more_text' => '',
672 'comment_num' => '',
673 'date' => '',
674 'thumb' => '',
675 'thumbTop' => '',
676 'thumb_w' => '',
677 'thumb_h' => '',
678 'use_css_cropping' => ''
679 ) );
680
681 $title = $instance['title'];
682 $hide_title = $instance['hide_title'];
683 $separate_categories = $instance['separate_categories'];
684 $num_per_cate = $instance['num_per_cate'];
685 $num = $instance['num'];
686 $exclude_no_children = $instance['exclude_no_children'];
687 $exclude_children = $instance['exclude_children'];
688 $sort_by = $instance['sort_by'];
689 $asc_sort_order = $instance['asc_sort_order'];
690 $title_link = $instance['title_link'];
691 $exclude_categories = $instance['exclude_categories'];
692 $exclude_terms = $instance['exclude_terms'];
693 $include_tax = $instance['include_tax'];
694 $post_types = $instance['post_types'];
695 $exclude_current_post = $instance['exclude_current_post'];
696 $exclude_sticky_posts = $instance['exclude_sticky_posts'];
697 $author = $instance['author'];
698 $date_format = $instance['date_format'];
699 $use_wp_date_format = $instance['use_wp_date_format'];
700 $date_link = $instance['date_link'];
701 $excerpt = $instance['excerpt'];
702 $excerpt_length = $instance['excerpt_length'];
703 $excerpt_more_text = $instance['excerpt_more_text'];
704 $comment_num = $instance['comment_num'];
705 $date = $instance['date'];
706 $thumb = $instance['thumb'];
707 $thumbTop = $instance['thumbTop'];
708 $thumb_w = $instance['thumb_w'];
709 $thumb_h = $instance['thumb_h'];
710 $use_css_cropping = $instance['use_css_cropping'];
711
712 ?>
713 <div class="same-category-widget-cont">
714 <h4 data-panel="title"><?php _e('Title')?></h4>
715 <div>
716 <p>
717 <label for="<?php echo $this->get_field_id("title_link"); ?>">
718 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("title_link"); ?>" name="<?php echo $this->get_field_name("title_link"); ?>"<?php checked( (bool) $instance["title_link"], true ); ?> />
719 <?php _e( 'Make widget title link' ); ?>
720 </label>
721 </p>
722
723 <p>
724 <label for="<?php echo $this->get_field_id("hide_title"); ?>">
725 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("hide_title"); ?>" name="<?php echo $this->get_field_name("hide_title"); ?>"<?php checked( (bool) $instance["hide_title"], true ); ?> />
726 <?php _e( 'Hide title' ); ?>
727 </label>
728 </p>
729
730 <p>
731 <label for="<?php echo $this->get_field_id("title"); ?>">
732 <?php _e( 'Title *' ); ?>:
733 <input style="width:80%;" class="widefat" id="<?php echo $this->get_field_id("title"); ?>" name="<?php echo $this->get_field_name("title"); ?>" type="text" value="<?php echo esc_attr($instance['title']); ?>" />
734 <div style="border-left:5px solid #F1F1F1;padding-left:10px;">* Placeholder: </br>'%cat%' - One category (the first if more assigned)</br>'%cat-all%' - All assigned categories for the shown post</div>
735 </label>
736 </p>
737 </div>
738 <h4 data-panel="filter"><?php _e('Filter')?></h4>
739 <div>
740 <?php
741 // get taxonomies except for the built-in
742 $args = array(
743 'public' => true
744 );
745 $taxs = get_taxonomies( $args, 'objects' );
746
747 // now get all tags
748 $args = array(
749 'hide_empty' => false, // we want to show not yet populated terms as well
750 'fields' => 'id=>name' // return array of names matched to ids
751 );
752 $collect_post_types = "";
753 foreach ($taxs as $key=>$tax) {
754 $taxname = $tax->name;
755 $terms = get_terms($taxname,$args);
756 $post_type = $post_types[$taxname]['post_type'];
757
758 if ($terms) {
759 if ($collect_post_types != $post_type) {
760 echo ($collect_post_types == "")?'':'</div>';
761 echo 'Show <b>'.$post_type.'</b> with:<br>';
762 echo '<div style="border-left:5px solid #F1F1F1;padding-left:10px;">';
763 $collect_post_types = $post_type;
764 }
765 ?>
766 <p>
767 <label>
768 <input name="<?php echo $this->get_field_name('include_tax['.$post_type.']'); ?>" data-taxname-and-post-type="<?php echo $taxname.'-'.$post_type ?>" onchange="javascript:scpwp_namespace.toggleSelectTaxPanel(this)" type="radio" class="checkbox" id="<?php echo $this->get_field_id('include_tax['.$post_type.']'); ?>" value="<?php echo $taxname ?>"<?php checked( (bool) ($instance['include_tax'][$post_type] == $taxname), true ); ?> />
769 <?php printf( __( 'Same "%s" and exclude:' ), esc_html($tax->labels->name)); ?>
770 </label>
771 </p>
772 <?php
773
774 $selected = array();
775 if (isset($instance['exclude_terms'][$taxname]))
776 $selected = $instance['exclude_terms'][$taxname];
777 else if (isset($instance["exclude_categories"]) && $instance["exclude_categories"] && $taxname == 'category') // deprecate >= 1.0.12: 'exclude_categories' get 'exclude_terms'
778 $selected = $instance["exclude_categories"];
779
780 $style_display_attr = ($instance['include_tax'][$post_type] == $taxname)?'block':'none';
781
782 echo '<div data-post-type='.$post_type.' class=\'scpwp-exclude-taxterms-'.$taxname.'-panel\' style="display:'.$style_display_attr.'">';
783 echo '<select multiple="multiple" name="'.$this->get_field_name('exclude_terms').'['.$taxname.'][]" id="'.$this->get_field_id('exclude_terms['.$taxname.']').'">';
784 foreach ($terms as $id => $name) {
785 $sel = '';
786 if (in_array($id,$selected))
787 $sel = ' selected="selected"';
788 echo '<option value="'.$id.'"'.$sel.'>'.esc_html($name).'</option>';
789 }
790 echo '</select>';
791 echo '<p>(CTRL+Click: Multiselection and clear)</p>';
792 echo '</div>';
793 }
794 }
795 ?>
796
797 <p>
798 <label for="<?php echo $this->get_field_id("exclude_no_children"); ?>">
799 <input type="checkbox" class="checkbox"
800 id="<?php echo $this->get_field_id("exclude_no_children"); ?>"
801 name="<?php echo $this->get_field_name("exclude_no_children"); ?>"
802 <?php checked( (bool) $instance["exclude_no_children"], true ); ?> />
803 <?php _e( 'Perform the exclusion without children' ); ?>
804 </label>
805 </p>
806
807 </div>
808
809 <p>
810 <label for="<?php echo $this->get_field_id("sort_by"); ?>">
811 <?php _e('Sort by'); ?>:
812 <select id="<?php echo $this->get_field_id("sort_by"); ?>" name="<?php echo $this->get_field_name("sort_by"); ?>">
813 <option value="date"<?php selected( $instance["sort_by"], "date" ); ?>>Date</option>
814 <option value="title"<?php selected( $instance["sort_by"], "title" ); ?>>Title</option>
815 <option value="comment_count"<?php selected( $instance["sort_by"], "comment_count" ); ?>>Number of comments</option>
816 <option value="rand"<?php selected( $instance["sort_by"], "rand" ); ?>>Random</option>
817 </select>
818 </label>
819 </p>
820
821 <p>
822 <label for="<?php echo $this->get_field_id("asc_sort_order"); ?>">
823 <input type="checkbox" class="checkbox"
824 id="<?php echo $this->get_field_id("asc_sort_order"); ?>"
825 name="<?php echo $this->get_field_name("asc_sort_order"); ?>"
826 <?php checked( (bool) $instance["asc_sort_order"], true ); ?> />
827 <?php _e( 'Reverse sort order (ascending)' ); ?>
828 </label>
829 </p>
830
831 <p>
832 <label for="<?php echo $this->get_field_id("separate_categories"); ?>">
833 <input onchange="javascript:scpwp_namespace.toggleSeparateCategoriesPanel(this)" type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("separate_categories"); ?>" name="<?php echo $this->get_field_name("separate_categories"); ?>"<?php checked( (bool) $instance["separate_categories"], true ); ?> />
834 <?php _e( 'Separate terms (If more than one assigned)' ); ?>
835 </label>
836 </p>
837
838 <p class="scpwp-separate-categories-panel" style="border-left:5px solid #F1F1F1;padding-left:10px;display:<?php echo (isset($separate_categories) && $separate_categories) ? 'block' : 'none'?>">
839 <label for="<?php echo $this->get_field_id("num_per_cate"); ?>">
840 <?php _e('Max. number of posts per separated categories'); ?>:
841 <input style="width: 15%; text-align: center;" id="<?php echo $this->get_field_id("num_per_cate"); ?>" name="<?php echo $this->get_field_name("num_per_cate"); ?>" type="number" min="0" value="<?php echo absint($instance["num_per_cate"]); ?>" size='3' />
842 </label>
843 </p>
844
845 <p>
846 <label for="<?php echo $this->get_field_id("num"); ?>">
847 <?php _e('Number of posts to show (overall)'); ?>:
848 <input style="width:30%;" style="text-align: center;" id="<?php echo $this->get_field_id("num"); ?>" name="<?php echo $this->get_field_name("num"); ?>" type="number" min="0" value="<?php echo absint($instance["num"]); ?>" size='3' />
849 </label>
850 </p>
851
852 <p>
853 <label for="<?php echo $this->get_field_id("exclude_current_post"); ?>">
854 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("exclude_current_post"); ?>" name="<?php echo $this->get_field_name("exclude_current_post"); ?>"<?php checked( (bool) $instance["exclude_current_post"], true ); ?> />
855 <?php _e( 'Exclude current post' ); ?>
856 </label>
857 </p>
858
859 <p>
860 <label for="<?php echo $this->get_field_id("exclude_sticky_posts"); ?>">
861 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("exclude_sticky_posts"); ?>" name="<?php echo $this->get_field_name("exclude_sticky_posts"); ?>"<?php checked( (bool) $instance["exclude_sticky_posts"], true ); ?> />
862 <?php _e( 'Exclude sticky posts' ); ?>
863 </label>
864 </p>
865
866 <p>
867 <label for="<?php echo $this->get_field_id("exclude_children"); ?>">
868 <input type="checkbox" class="checkbox"
869 id="<?php echo $this->get_field_id("exclude_children"); ?>"
870 name="<?php echo $this->get_field_name("exclude_children"); ?>"
871 <?php checked( (bool) $instance["exclude_children"], true ); ?> />
872 <?php _e( 'Exclude children' ); ?>
873 </label>
874 </p>
875
876 </div>
877 <h4 data-panel="thumbnails"><?php _e('Thumbnails')?></h4>
878 <div>
879 <?php
880 if ( function_exists('the_post_thumbnail') && current_theme_supports("post-thumbnails") ) :
881 ?>
882 <p>
883 <label for="<?php echo $this->get_field_id("thumb"); ?>">
884 <input onchange="javascript:scpwp_namespace.toggleShowPostThumbnailPanel(this)" type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("thumb"); ?>" name="<?php echo $this->get_field_name("thumb"); ?>"<?php checked( (bool) $instance["thumb"], true ); ?> />
885 <?php _e( 'Show post thumbnail' ); ?>
886 </label>
887 </p>
888
889 <div class="scpwp-show-post-thumbnail-panel" style="border-left:5px solid #F1F1F1;padding-left:10px;display:<?php echo (isset($thumb) && $thumb) ? 'block' : 'none'?>">
890 <p>
891 <label for="<?php echo $this->get_field_id("thumbTop"); ?>">
892 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("thumbTop"); ?>" name="<?php echo $this->get_field_name("thumbTop"); ?>"<?php checked( (bool) $instance["thumbTop"], true ); ?> />
893 <?php _e( 'Thumbnail to top' ); ?>
894 </label>
895 </p>
896
897 <p>
898 <label>
899 <?php _e('Thumbnail dimensions (in pixels)'); ?>:<br />
900 <label for="<?php echo $this->get_field_id("thumb_w"); ?>">
901 Width: <input class="widefat" style="width:30%;" type="number" min="1" id="<?php echo $this->get_field_id("thumb_w"); ?>" name="<?php echo $this->get_field_name("thumb_w"); ?>" value="<?php echo $instance["thumb_w"]; ?>" />
902 </label>
903
904 <label for="<?php echo $this->get_field_id("thumb_h"); ?>">
905 Height: <input class="widefat" style="width:30%;" type="number" min="1" id="<?php echo $this->get_field_id("thumb_h"); ?>" name="<?php echo $this->get_field_name("thumb_h"); ?>" value="<?php echo $instance["thumb_h"]; ?>" />
906 </label>
907 </label>
908 </p>
909
910 <p>
911 <label for="<?php echo $this->get_field_id("use_css_cropping"); ?>">
912 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("use_css_cropping"); ?>" name="<?php echo $this->get_field_name("use_css_cropping"); ?>"<?php checked( (bool) $instance["use_css_cropping"], true ); ?> />
913 <?php _e( 'CSS crop to requested size' ); ?>
914 </label>
915 </p>
916 </div>
917 <?php
918 endif;
919 ?>
920 </div>
921 <h4 data-panel="details"><?php _e('Post details')?></h4>
922 <div>
923 <p>
924 <label for="<?php echo $this->get_field_id("excerpt"); ?>">
925 <input onchange="javascript:scpwp_namespace.toggleShowPostExcerptPanel(this)" type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("excerpt"); ?>" name="<?php echo $this->get_field_name("excerpt"); ?>"<?php checked( (bool) $instance["excerpt"], true ); ?> />
926 <?php _e( 'Show post excerpt' ); ?>
927 </label>
928 </p>
929
930 <div class="scpwp-show-post-excerpt-panel" style="border-left:5px solid #F1F1F1;padding-left:10px;display:<?php echo (isset($excerpt) && $excerpt) ? 'block' : 'none'?>">
931 <p>
932 <label for="<?php echo $this->get_field_id("excerpt_length"); ?>">
933 <?php _e( 'Excerpt length (in words):' ); ?>
934 </label>
935 <input style="width:30%; text-align: center;" placeholder="<?php _e('55')?>" type="number" min="0" id="<?php echo $this->get_field_id("excerpt_length"); ?>" name="<?php echo $this->get_field_name("excerpt_length"); ?>" value="<?php echo $instance["excerpt_length"]; ?>" size="3" />
936 </p>
937
938 <p>
939 <label for="<?php echo $this->get_field_id("excerpt_more_text"); ?>">
940 <?php _e( 'Excerpt \'more\' text:' ); ?>
941 </label>
942 <input class="widefat" style="width:50%;" placeholder="<?php _e('... more')?>" id="<?php echo $this->get_field_id("excerpt_more_text"); ?>" name="<?php echo $this->get_field_name("excerpt_more_text"); ?>" type="text" value="<?php echo esc_attr($instance["excerpt_more_text"]); ?>" />
943 </p>
944 </div>
945
946 <p>
947 <label for="<?php echo $this->get_field_id("comment_num"); ?>">
948 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("comment_num"); ?>" name="<?php echo $this->get_field_name("comment_num"); ?>"<?php checked( (bool) $instance["comment_num"], true ); ?> />
949 <?php _e( 'Show number of comments' ); ?>
950 </label>
951 </p>
952
953 <p>
954 <label for="<?php echo $this->get_field_id("date"); ?>" onchange="javascript:scpwp_namespace.toggleDatePanel(this)">
955 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("date"); ?>" name="<?php echo $this->get_field_name("date"); ?>"<?php checked( (bool) $instance["date"], true ); ?> />
956 <?php _e( 'Show post date' ); ?>
957 </label>
958 </p>
959 <div class="cpwp_ident scpwp-data-panel-date" style="display:<?php echo ((bool) $date) ? 'block' : 'none'?>">
960 <p>
961 <label for="<?php echo $this->get_field_id("use_wp_date_format"); ?>" onchange="javascript:scpwp_namespace.toggleUseWPDateFormatPanel(this)">
962 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("use_wp_date_format"); ?>" name="<?php echo $this->get_field_name("use_wp_date_format"); ?>"<?php checked( (bool) $instance["use_wp_date_format"], true ); ?> />
963 <?php _e( 'Use the WordPress Settings > General for the date format','category-posts' ); ?>
964 </label>
965 </p>
966 <div class="scpwp-data-panel-date-format" style="display:<?php echo ((bool) $use_wp_date_format) ? 'none' : 'block'?>">
967 <p>
968 <label for="<?php echo $this->get_field_id("date_format"); ?>">
969 <?php _e( 'Date format:','category-posts' ); ?>
970 </label>
971 <input class="text" placeholder="j M Y" id="<?php echo $this->get_field_id("date_format"); ?>" name="<?php echo $this->get_field_name("date_format"); ?>" type="text" value="<?php echo esc_attr($instance["date_format"]); ?>" size="8" />
972 </p>
973 </div>
974 <p>
975 <label for="<?php echo $this->get_field_id("date_link"); ?>">
976 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("date_link"); ?>" name="<?php echo $this->get_field_name("date_link"); ?>"<?php checked( (bool) $instance["date_link"], true ); ?> />
977 <?php _e( 'Make widget date link','category-posts' ); ?>
978 </label>
979 </p>
980 </div>
981
982 <p>
983 <label for="<?php echo $this->get_field_id("author"); ?>">
984 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id("author"); ?>" name="<?php echo $this->get_field_name("author"); ?>"<?php checked( (bool) $instance["author"], true ); ?> />
985 <?php _e( 'Show post author' ); ?>
986 </label>
987 </p>
988 </div>
989 <hr>
990
991 <p style="text-align:right;">
992 Follow us on <a target="_blank" href="https://www.facebook.com/TipTopPress">Facebook</a> and
993 <a target="_blank" href="https://twitter.com/TipTopPress">Twitter</a></br></br>
994 </p>
995 </div>
996 <?php
997
998 }
999
1000 }
1001
1002 function register_widget() {
1003 return \register_widget(__NAMESPACE__.'\Widget');
1004 }
1005
1006 add_action( 'widgets_init', __NAMESPACE__.'\register_widget' );
1007