PluginProbe
Same Category Posts / 1.1.3
Same Category Posts v1.1.3
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.3, at same-category-posts.php

1,006 lines 41.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.3
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 $post;
367 $current_post_id = get_the_ID();
368 $post_old = $post; // Save the post object.
369
370 extract( $args );
371 $this->instance = $instance;
372
373 $this->initPostTypesAndTaxes($instance);
374
375 // Get taxonomies
376 $taxonomies = null;
377 $taxes = get_object_taxonomies( $post );
378 $categories = null;
379 foreach ($taxes as $tax) {
380 $post_type = $instance['post_types'][$tax]['post_type'];
381 if ($tax == $instance['include_tax'][$post_type]) {
382 $terms = get_the_terms($post->ID, $tax);
383 if ($terms) {
384 foreach ($terms as $term) {
385 $taxonomies[$tax][] = $term->term_id;
386 }
387 }
388 $categories = get_the_terms($post->ID,$tax);
389 }
390 }
391
392 // Excerpt length filter
393 if ( isset($instance["excerpt_length"]) && $instance["excerpt_length"] > 0 ) {
394 $new_excerpt_length = create_function('$length', "return " . $instance["excerpt_length"] . ";");
395 add_filter('excerpt_length', $new_excerpt_length);
396 }
397
398 $valid_sort_orders = array('date', 'title', 'comment_count', 'rand');
399 if ( isset($instance['sort_by']) && in_array($instance['sort_by'], $valid_sort_orders) ) {
400 $sort_by = $instance['sort_by'];
401 $sort_order = (bool) isset( $instance['asc_sort_order'] ) ? 'ASC' : 'DESC';
402 } else {
403 // by default, display latest first
404 $sort_by = 'date';
405 $sort_order = 'DESC';
406 }
407
408 // Excerpt more_text
409 if( isset($instance["excerpt_more_text"]) && ltrim($instance["excerpt_more_text"]) != '' )
410 {
411 add_filter('excerpt_more', array($this,'excerpt_more_filter'));
412 }
413
414 // deprecate >= 1.0.12: 'exclude_categories' get 'exclude_terms'
415 // Exclude categories
416 if (!isset($instance['exclude_terms']['category']) && isset($instance['exclude_categories']) && $instance['exclude_categories'])
417 $instance['exclude_terms'] = array( 'category' => $instance['exclude_categories']);
418
419 // Query args
420 $args = array(
421 'orderby' => $sort_by,
422 'order' => $sort_order
423 );
424
425 $args['post_type'] = array( get_post_type( $post ) );
426
427 if ($taxonomies) {
428 $term_query_in = array('relation' => 'OR');
429 foreach ( $taxonomies as $tax=>$terms) {
430 if ( isset($instance['exclude_terms']) && $instance['exclude_terms'] && array_key_exists($tax, $instance['exclude_terms']) )
431 $terms = array_diff($terms, $instance['exclude_terms'][$tax]);
432 if ($terms) {
433 $term_query_in[] = array(
434 'taxonomy' => $tax,
435 'field' => 'term_id',
436 'terms' => $terms,
437 'include_children' => isset($instance['exclude_children']) && $instance['exclude_children'] ? false : true,
438 'operator' => 'IN',
439 );
440 }
441 }
442 }
443
444 $term_query_not_in = null;
445 if ( isset($instance['exclude_terms']) && $instance['exclude_terms'] ) {
446 foreach ( $instance['exclude_terms'] as $tax=>$terms) {
447 $post_type = $instance['post_types'][$tax]['post_type'];
448 if ($tax == $instance['include_tax'][$post_type]) {
449 $term_query_not_in[] = array(
450 'taxonomy' => $tax,
451 'field' => 'term_id',
452 'terms' => $instance['exclude_terms'][$tax],
453 'include_children' => isset($instance['exclude_no_children']) && $instance['exclude_no_children'] ? false : true,
454 'operator' => 'NOT IN',
455 );
456 }
457 }
458 }
459
460 $term_query[] = array('relation' => 'AND');
461 $term_query[] = $term_query_in;
462 $term_query[] = $term_query_not_in;
463
464 if (is_array($term_query))
465 $args['tax_query'] = $term_query;
466
467 $args['post__not_in'] = array();
468 if (isset( $instance['exclude_current_post'] ) && $instance['exclude_current_post']) {
469 $args['post__not_in'] = array( get_the_ID() );
470 }
471
472 if(isset( $instance['exclude_sticky_posts'] ) && $instance['exclude_sticky_posts']) {
473 foreach (get_option( 'sticky_posts' ) as $value) {
474 $args['post__not_in'][] = $value;
475 }
476 }
477
478 $args['posts_per_page'] = (isset($instance['num']) && $instance['num']) ? $instance['num'] : -1;
479
480 $my_query = new \WP_Query($args);
481
482 if( $my_query->have_posts() )
483 {
484 echo $before_widget;
485
486 // Widget title
487 if( !isset ( $instance["hide_title"] ) ) {
488 if( isset( $instance["separate_categories"] ) && $instance["separate_categories"] ) {
489 // Separate categories: title to array
490 foreach($categories as $cat) {
491 $widgetHTML[$cat->name]['ID'] = $cat->term_id;
492 if( isset ( $instance["title_link"] ) ) {
493 $title = '<a href="' . get_category_link( $cat ) . '">'. $cat->name . '</a>';
494 if(isset($instance['title']) && strpos($instance['title'], '%cat-all%') !== false)
495 $title = str_replace( "%cat-all%", $title, $instance['title']);
496 else if(isset($instance['title']) && strpos($instance['title'], '%cat%') !== false)
497 $title = str_replace( "%cat%", $title, $instance['title']);
498 $widgetHTML[$cat->name]['title'] = $title;
499 } else {
500 $title = $cat->name;
501 if(isset($instance['title']) && strpos($instance['title'], '%cat-all%') !== false)
502 $title = str_replace( "%cat-all%", $title, $instance['title']);
503 else if(isset($instance['title']) && strpos($instance['title'], '%cat%') !== false)
504 $title = str_replace( "%cat%", $title, $instance['title']);
505 $widgetHTML[$cat->name]['title'] = $title;
506 }
507 }
508 } else {
509 // ! Separate categories: echo
510 echo $before_title;
511 if( isset ( $instance["title_link"] ) ) {
512 $linkList = "";
513 foreach($categories as $cat) {
514 if(isset($instance['exclude_terms']) && $instance['exclude_terms'] && in_array($cat->term_id,$instance['exclude_terms']))
515 continue;
516 $linkList .= '<a href="' . get_category_link( $cat ) . '">'. $cat->name . '</a>, ';
517 }
518 $linkList = trim($linkList, ", ");
519 if( isset($instance['title']) && $instance['title'] ) { // use placeholders if title is not empty
520 if(strpos($instance['title'], '%cat-all%') !== false ||
521 strpos($instance['title'], '%cat%') !== false) { // all-category placeholder is used
522 if(strpos($instance['title'], '%cat-all%') !== false)
523 $linkList = str_replace( "%cat-all%", $linkList, $instance['title']);
524 else if(strpos($instance['title'], '%cat%') !== false)
525 $linkList = str_replace( "%cat%", '<a href="' . get_category_link( $categories[0] ) . '">'. $categories[0]->name . '</a>', $instance['title']);
526 } else // no category placeholder is used
527 $linkList = '<a href="' . get_category_link( $categories[0] ) . '">'. $instance['title'] . '</a>';
528 }
529 echo htmlspecialchars_decode(apply_filters('widget_title',$linkList));
530 } else {
531 $categoryNames = "";
532 if ($categories) {
533 foreach ($categories as $key => $val) {
534 if(isset($instance['exclude_terms']) && $instance['exclude_terms'] && in_array($val->term_id,$instance['exclude_terms'][$val->taxonomy]))
535 continue;
536 $categoryNames .= $val->name . ", ";
537 }
538 $categoryNames = trim($categoryNames, ", ");
539 }
540
541 if( isset($instance['title']) && $instance['title'] ) { // use placeholders if title is not empty
542 if(strpos($instance['title'], '%cat-all%') !== false) // all-category placeholder is used
543 $categoryNames = str_replace( "%cat-all%", $categoryNames, $instance['title']);
544 else if(strpos($instance['title'], '%cat%') !== false) // one-category placeholder is used
545 $categoryNames = str_replace( "%cat%", $categories[0]->name, $instance['title']);
546 else
547 $categoryNames = $instance['title'];
548 }
549 echo htmlspecialchars_decode(apply_filters('widget_title',$categoryNames));
550 }
551 echo $after_title;
552 }
553 }
554 // /Widget title
555
556 // Post list
557 echo "<ul>\n";
558 while ($my_query->have_posts())
559 {
560 $my_query->the_post();
561
562 if( isset( $instance["separate_categories"] ) && $instance["separate_categories"] ) {
563 // Separate categories: get itemHTML to array
564 $object_taxes = get_object_taxonomies( $post, 'objects' );
565 $post_categories = null;
566 foreach ( $object_taxes as $tax ) {
567 $post_type = $instance['post_types'][$tax->name]['post_type'];
568 if ($tax->name == $instance['include_tax'][$post_type]) {
569 $post_categories = get_the_terms($post->ID,$tax->name);
570 break;
571 }
572 }
573 foreach ($post_categories as $val) {
574 $widgetHTML[$val->name][$post->ID]['itemHTML'] = $this->itemHTML($instance,$current_post_id);
575 $widgetHTML[$val->name][$post->ID]['ID'] = $post->ID;
576 }
577 } else {
578 // ! Separate categories: get itemHTML and echo
579 echo $this->itemHTML($instance,$current_post_id);
580 }
581 } // end while
582
583 if (isset( $instance["separate_categories"] ) && $instance["separate_categories"]) {
584 // Separate categories: echo
585 $isOnPage = array();
586 foreach($widgetHTML as $val) {
587 // widget title
588 $haveItemHTML = false;
589 $ret = $before_title . htmlspecialchars_decode(apply_filters('widget_title',isset($val['title'])?$val['title']:"")) . $after_title;
590 $count = 1;
591 $num_per_cat = (isset($instance['num_per_cate'])&&$instance['num_per_cate']!=0?($instance['num_per_cate']):99999);
592 foreach($val as $key) {
593 if(is_array($key) && array_key_exists('itemHTML', $key)) {
594 if( !in_array($key['ID'], $isOnPage) ) {
595 if($count <= $num_per_cat) {
596 $ret .= $key['itemHTML'];
597 $haveItemHTML = true;
598 $isOnPage[] = $key['ID'];
599 } else
600 break;
601 $count++;
602 }
603 }
604 }
605 if ($haveItemHTML)
606 echo $ret;
607 }
608 }
609
610 echo "</ul>\n";
611 // end Post list
612
613 echo $after_widget;
614 }
615
616 if(isset($new_excerpt_length))
617 remove_filter('excerpt_length', $new_excerpt_length);
618 remove_filter('excerpt_more', array($this,'excerpt_more_filter'));
619
620 $post = $post_old; // Restore the post object.
621 }
622
623 /**
624 * Update the options
625 *
626 * @param array $new_instance
627 * @param array $old_instance
628 * @return array
629 */
630 function update($new_instance, $old_instance) {
631
632 return $new_instance;
633 }
634
635 /**
636 * The widget configuration form back end.
637 *
638 * @param array $instance
639 * @return void
640 */
641 function form($instance) {
642
643 // ToDo seperate_cat get seperate_tax (if update, settings)
644
645 $this->initPostTypesAndTaxes($instance);
646
647 $instance = wp_parse_args( ( array ) $instance, array(
648 'title' => '',
649 'hide_title' => '',
650 'separate_categories' => '',
651 'num_per_cate' => '',
652 'num' => '',
653 'exclude_no_children' => '',
654 'exclude_children' => '',
655 'sort_by' => '',
656 'asc_sort_order' => '',
657 'title_link' => '',
658 'exclude_categories' => '',
659 'exclude_terms' => array(),
660 'include_tax' => array(),
661 'post_types' => array(),
662 'exclude_current_post' => '',
663 'exclude_sticky_posts' => '',
664 'author' => '',
665 'date_format' => '',
666 'use_wp_date_format' => '',
667 'date_link' => '',
668 'excerpt' => '',
669 'excerpt_length' => '',
670 'excerpt_more_text' => '',
671 'comment_num' => '',
672 'date' => '',
673 'thumb' => '',
674 'thumbTop' => '',
675 'thumb_w' => '',
676 'thumb_h' => '',
677 'use_css_cropping' => ''
678 ) );
679
680 $title = $instance['title'];
681 $hide_title = $instance['hide_title'];
682 $separate_categories = $instance['separate_categories'];
683 $num_per_cate = $instance['num_per_cate'];
684 $num = $instance['num'];
685 $exclude_no_children = $instance['exclude_no_children'];
686 $exclude_children = $instance['exclude_children'];
687 $sort_by = $instance['sort_by'];
688 $asc_sort_order = $instance['asc_sort_order'];
689 $title_link = $instance['title_link'];
690 $exclude_categories = $instance['exclude_categories'];
691 $exclude_terms = $instance['exclude_terms'];
692 $include_tax = $instance['include_tax'];
693 $post_types = $instance['post_types'];
694 $exclude_current_post = $instance['exclude_current_post'];
695 $exclude_sticky_posts = $instance['exclude_sticky_posts'];
696 $author = $instance['author'];
697 $date_format = $instance['date_format'];
698 $use_wp_date_format = $instance['use_wp_date_format'];
699 $date_link = $instance['date_link'];
700 $excerpt = $instance['excerpt'];
701 $excerpt_length = $instance['excerpt_length'];
702 $excerpt_more_text = $instance['excerpt_more_text'];
703 $comment_num = $instance['comment_num'];
704 $date = $instance['date'];
705 $thumb = $instance['thumb'];
706 $thumbTop = $instance['thumbTop'];
707 $thumb_w = $instance['thumb_w'];
708 $thumb_h = $instance['thumb_h'];
709 $use_css_cropping = $instance['use_css_cropping'];
710
711 ?>
712 <div class="same-category-widget-cont">
713 <h4 data-panel="title"><?php _e('Title')?></h4>
714 <div>
715 <p>
716 <label for="<?php echo $this->get_field_id("title_link"); ?>">
717 <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 ); ?> />
718 <?php _e( 'Make widget title link' ); ?>
719 </label>
720 </p>
721
722 <p>
723 <label for="<?php echo $this->get_field_id("hide_title"); ?>">
724 <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 ); ?> />
725 <?php _e( 'Hide title' ); ?>
726 </label>
727 </p>
728
729 <p>
730 <label for="<?php echo $this->get_field_id("title"); ?>">
731 <?php _e( 'Title *' ); ?>:
732 <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']); ?>" />
733 <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>
734 </label>
735 </p>
736 </div>
737 <h4 data-panel="filter"><?php _e('Filter')?></h4>
738 <div>
739 <?php
740 // get taxonomies except for the built-in
741 $args = array(
742 'public' => true
743 );
744 $taxs = get_taxonomies( $args, 'objects' );
745
746 // now get all tags
747 $args = array(
748 'hide_empty' => false, // we want to show not yet populated terms as well
749 'fields' => 'id=>name' // return array of names matched to ids
750 );
751 $collect_post_types = "";
752 foreach ($taxs as $key=>$tax) {
753 $taxname = $tax->name;
754 $terms = get_terms($taxname,$args);
755 $post_type = $post_types[$taxname]['post_type'];
756
757 if ($terms) {
758 if ($collect_post_types != $post_type) {
759 echo ($collect_post_types == "")?'':'</div>';
760 echo 'Show <b>'.$post_type.'</b> with:<br>';
761 echo '<div style="border-left:5px solid #F1F1F1;padding-left:10px;">';
762 $collect_post_types = $post_type;
763 }
764 ?>
765 <p>
766 <label>
767 <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 ); ?> />
768 <?php printf( __( 'Same "%s" and exclude:' ), esc_html($tax->labels->name)); ?>
769 </label>
770 </p>
771 <?php
772
773 $selected = array();
774 if (isset($instance['exclude_terms'][$taxname]))
775 $selected = $instance['exclude_terms'][$taxname];
776 else if (isset($instance["exclude_categories"]) && $instance["exclude_categories"] && $taxname == 'category') // deprecate >= 1.0.12: 'exclude_categories' get 'exclude_terms'
777 $selected = $instance["exclude_categories"];
778
779 $style_display_attr = ($instance['include_tax'][$post_type] == $taxname)?'block':'none';
780
781 echo '<div data-post-type='.$post_type.' class=\'scpwp-exclude-taxterms-'.$taxname.'-panel\' style="display:'.$style_display_attr.'">';
782 echo '<select multiple="multiple" name="'.$this->get_field_name('exclude_terms').'['.$taxname.'][]" id="'.$this->get_field_id('exclude_terms['.$taxname.']').'">';
783 foreach ($terms as $id => $name) {
784 $sel = '';
785 if (in_array($id,$selected))
786 $sel = ' selected="selected"';
787 echo '<option value="'.$id.'"'.$sel.'>'.esc_html($name).'</option>';
788 }
789 echo '</select>';
790 echo '<p>(CTRL+Click: Multiselection and clear)</p>';
791 echo '</div>';
792 }
793 }
794 ?>
795
796 <p>
797 <label for="<?php echo $this->get_field_id("exclude_no_children"); ?>">
798 <input type="checkbox" class="checkbox"
799 id="<?php echo $this->get_field_id("exclude_no_children"); ?>"
800 name="<?php echo $this->get_field_name("exclude_no_children"); ?>"
801 <?php checked( (bool) $instance["exclude_no_children"], true ); ?> />
802 <?php _e( 'Perform the exclusion without children' ); ?>
803 </label>
804 </p>
805
806 </div>
807
808 <p>
809 <label for="<?php echo $this->get_field_id("sort_by"); ?>">
810 <?php _e('Sort by'); ?>:
811 <select id="<?php echo $this->get_field_id("sort_by"); ?>" name="<?php echo $this->get_field_name("sort_by"); ?>">
812 <option value="date"<?php selected( $instance["sort_by"], "date" ); ?>>Date</option>
813 <option value="title"<?php selected( $instance["sort_by"], "title" ); ?>>Title</option>
814 <option value="comment_count"<?php selected( $instance["sort_by"], "comment_count" ); ?>>Number of comments</option>
815 <option value="rand"<?php selected( $instance["sort_by"], "rand" ); ?>>Random</option>
816 </select>
817 </label>
818 </p>
819
820 <p>
821 <label for="<?php echo $this->get_field_id("asc_sort_order"); ?>">
822 <input type="checkbox" class="checkbox"
823 id="<?php echo $this->get_field_id("asc_sort_order"); ?>"
824 name="<?php echo $this->get_field_name("asc_sort_order"); ?>"
825 <?php checked( (bool) $instance["asc_sort_order"], true ); ?> />
826 <?php _e( 'Reverse sort order (ascending)' ); ?>
827 </label>
828 </p>
829
830 <p>
831 <label for="<?php echo $this->get_field_id("separate_categories"); ?>">
832 <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 ); ?> />
833 <?php _e( 'Separate terms (If more than one assigned)' ); ?>
834 </label>
835 </p>
836
837 <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'?>">
838 <label for="<?php echo $this->get_field_id("num_per_cate"); ?>">
839 <?php _e('Max. number of posts per separated categories'); ?>:
840 <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' />
841 </label>
842 </p>
843
844 <p>
845 <label for="<?php echo $this->get_field_id("num"); ?>">
846 <?php _e('Number of posts to show (overall)'); ?>:
847 <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' />
848 </label>
849 </p>
850
851 <p>
852 <label for="<?php echo $this->get_field_id("exclude_current_post"); ?>">
853 <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 ); ?> />
854 <?php _e( 'Exclude current post' ); ?>
855 </label>
856 </p>
857
858 <p>
859 <label for="<?php echo $this->get_field_id("exclude_sticky_posts"); ?>">
860 <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 ); ?> />
861 <?php _e( 'Exclude sticky posts' ); ?>
862 </label>
863 </p>
864
865 <p>
866 <label for="<?php echo $this->get_field_id("exclude_children"); ?>">
867 <input type="checkbox" class="checkbox"
868 id="<?php echo $this->get_field_id("exclude_children"); ?>"
869 name="<?php echo $this->get_field_name("exclude_children"); ?>"
870 <?php checked( (bool) $instance["exclude_children"], true ); ?> />
871 <?php _e( 'Exclude children' ); ?>
872 </label>
873 </p>
874
875 </div>
876 <h4 data-panel="thumbnails"><?php _e('Thumbnails')?></h4>
877 <div>
878 <?php
879 if ( function_exists('the_post_thumbnail') && current_theme_supports("post-thumbnails") ) :
880 ?>
881 <p>
882 <label for="<?php echo $this->get_field_id("thumb"); ?>">
883 <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 ); ?> />
884 <?php _e( 'Show post thumbnail' ); ?>
885 </label>
886 </p>
887
888 <div class="scpwp-show-post-thumbnail-panel" style="border-left:5px solid #F1F1F1;padding-left:10px;display:<?php echo (isset($thumb) && $thumb) ? 'block' : 'none'?>">
889 <p>
890 <label for="<?php echo $this->get_field_id("thumbTop"); ?>">
891 <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 ); ?> />
892 <?php _e( 'Thumbnail to top' ); ?>
893 </label>
894 </p>
895
896 <p>
897 <label>
898 <?php _e('Thumbnail dimensions (in pixels)'); ?>:<br />
899 <label for="<?php echo $this->get_field_id("thumb_w"); ?>">
900 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"]; ?>" />
901 </label>
902
903 <label for="<?php echo $this->get_field_id("thumb_h"); ?>">
904 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"]; ?>" />
905 </label>
906 </label>
907 </p>
908
909 <p>
910 <label for="<?php echo $this->get_field_id("use_css_cropping"); ?>">
911 <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 ); ?> />
912 <?php _e( 'CSS crop to requested size' ); ?>
913 </label>
914 </p>
915 </div>
916 <?php
917 endif;
918 ?>
919 </div>
920 <h4 data-panel="details"><?php _e('Post details')?></h4>
921 <div>
922 <p>
923 <label for="<?php echo $this->get_field_id("excerpt"); ?>">
924 <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 ); ?> />
925 <?php _e( 'Show post excerpt' ); ?>
926 </label>
927 </p>
928
929 <div class="scpwp-show-post-excerpt-panel" style="border-left:5px solid #F1F1F1;padding-left:10px;display:<?php echo (isset($excerpt) && $excerpt) ? 'block' : 'none'?>">
930 <p>
931 <label for="<?php echo $this->get_field_id("excerpt_length"); ?>">
932 <?php _e( 'Excerpt length (in words):' ); ?>
933 </label>
934 <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" />
935 </p>
936
937 <p>
938 <label for="<?php echo $this->get_field_id("excerpt_more_text"); ?>">
939 <?php _e( 'Excerpt \'more\' text:' ); ?>
940 </label>
941 <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"]); ?>" />
942 </p>
943 </div>
944
945 <p>
946 <label for="<?php echo $this->get_field_id("comment_num"); ?>">
947 <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 ); ?> />
948 <?php _e( 'Show number of comments' ); ?>
949 </label>
950 </p>
951
952 <p>
953 <label for="<?php echo $this->get_field_id("date"); ?>" onchange="javascript:scpwp_namespace.toggleDatePanel(this)">
954 <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 ); ?> />
955 <?php _e( 'Show post date' ); ?>
956 </label>
957 </p>
958 <div class="cpwp_ident scpwp-data-panel-date" style="display:<?php echo ((bool) $date) ? 'block' : 'none'?>">
959 <p>
960 <label for="<?php echo $this->get_field_id("use_wp_date_format"); ?>" onchange="javascript:scpwp_namespace.toggleUseWPDateFormatPanel(this)">
961 <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 ); ?> />
962 <?php _e( 'Use the WordPress Settings > General for the date format','category-posts' ); ?>
963 </label>
964 </p>
965 <div class="scpwp-data-panel-date-format" style="display:<?php echo ((bool) $use_wp_date_format) ? 'none' : 'block'?>">
966 <p>
967 <label for="<?php echo $this->get_field_id("date_format"); ?>">
968 <?php _e( 'Date format:','category-posts' ); ?>
969 </label>
970 <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" />
971 </p>
972 </div>
973 <p>
974 <label for="<?php echo $this->get_field_id("date_link"); ?>">
975 <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 ); ?> />
976 <?php _e( 'Make widget date link','category-posts' ); ?>
977 </label>
978 </p>
979 </div>
980
981 <p>
982 <label for="<?php echo $this->get_field_id("author"); ?>">
983 <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 ); ?> />
984 <?php _e( 'Show post author' ); ?>
985 </label>
986 </p>
987 </div>
988 <hr>
989
990 <p style="text-align:right;">
991 Follow us on <a target="_blank" href="https://www.facebook.com/TipTopPress">Facebook</a> and
992 <a target="_blank" href="https://twitter.com/TipTopPress">Twitter</a></br></br>
993 </p>
994 </div>
995 <?php
996
997 }
998
999 }
1000
1001 function register_widget() {
1002 return \register_widget(__NAMESPACE__.'\Widget');
1003 }
1004
1005 add_action( 'widgets_init', __NAMESPACE__.'\register_widget' );
1006