<?php
/*
Plugin Name: Category Filtered Widgets
Plugin URI: http://www.qogo.com/wpplugins/
Description: Filter the categories that appear in the archive list and calendar. Adds <code>wp_get_cats_archives()</code>, <code>get_cats_archives()</code> and <code>get_cats_calender()</code> functions.
Version: 0.1
Author: Burt Heymanson
Author URI: mailto:wpplugins@qogo.com

<strong>get_cats_archives()</strong> - Creates archive lists in exactly the same way as the WordPress standard get_archives() function with an additional argument, category. Multiple categories can be listed in comma delimited form. Categories may also be negated to create an archive list of posts that are not in the given categories. 

<strong>wp_get_cats_archives()</strong> - A wrapper function around <code>get_cats_archives()</code> that allows for arguments to be passed in query string style, like the standard wp_get_archives() function.

<strong>get_cats_calendar()</strong> - Creates a calendar in exactly the same way as the WordPress standard get_calendar() function with an additional argument, category. Multiple categories can be listed in comma delimited form. Categories may also be negated to create a calendar of posts that are not in the given categories. 

<strong>get_cats_archives()</strong>

To show an archive list only for category 1 use:

<code><?php get_cats_archives( 'monthly','','html','','',true,'1' ); ?></code>

or for multiple categories 1, 2 and 4 use:

<code><?php get_cats_archives( 'monthly','','html','','',true,'1,2,4' ); ?></code>

Negation may also be used. For example, to show an archive list for all posts not in category 1, use:

<code><?php get_cats_archives( 'monthly','','html','','',true,'-1' ); ?></code>

If you use multiple negated categories, they will be ANDed. Thus, the following will list archives that contain posts that are not in category 1 AND not in category 3:

<code><?php get_cats_archives( 'monthly','','html','','',true,'-1,-3' ); ?></code>


<strong>wp_get_cats_archives()</strong>

To show an archive list only for category 1 use:

<code><?php wp_get_cats_archives( 'category=1' ); ?></code>

or for multiple categories 1, 2 and 4 use:

<code><?php wp_get_cats_archives( 'category=1,2,4' ); ?></code>

Negation may also be used. For example, to show an archive list for all posts not in category 1, use:

<code><?php wp_get_cats_archives( 'category=-1' ); ?></code>

If you use multiple negated categories, they will be ANDed. Thus, the following will list archives that contain posts that are not in category 1 AND not in category 3:

<code><?php wp_get_cats_archives( 'category=-1,-3' ); ?></code>


<strong>get_cats_calendar()</strong>

To show a calendar only for category 1 use:

<code><?php get_cats_calendar( '1','1' ); ?></code>

or for multiple categories 1, 2 and 4 use:

<code><?php get_cats_calendar( '1','1,2,4' ); ?></code>

Negation may also be used. For example, to show a calendar for all posts not in category 1, use:

<code><?php get_cats_calendar( '1','-1' ); ?></code>

The following will show a calendar that contains posts that are not in category 1 or category 3:

<code><?php get_cats_calendar( '1','-1,-3' ); ?></code>



*/ 

function wp_get_cats_archives($args '') {
        
parse_str($args$r);
        if (!isset(
$r['type'])) $r['type'] = '';
        if (!isset(
$r['limit'])) $r['limit'] = '';
        if (!isset(
$r['format'])) $r['format'] = 'html';
        if (!isset(
$r['before'])) $r['before'] = '';
        if (!isset(
$r['after'])) $r['after'] = '';
        if (!isset(
$r['show_post_count'])) $r['show_post_count'] = false;
        if (!isset(
$r['category'])) $r['category'] = '';
        
get_cats_archives($r['type'], $r['limit'], $r['format'], $r['before'], $r['after'], $r['show_post_count'], $r['category']);
}

function 
get_cats_archives($type=''$limit=''$format='html'$before ''$after ''$show_post_count false$category '') {
    global 
$tableposts$tablepost2cat;
    global 
$querystring_start$querystring_equal$querystring_separator$month$wpdb;

    if (
'' == $type) {
        
$type get_settings('archive_mode');
    }

    if (
'' != $limit) {
        
$limit = (int) $limit;
        
$limit ' LIMIT '.$limit;
    }

    if (
$category) {
        
$cat_array explode','$category ); // Make array of cats & nocats

        
for( $i=0$i count($cat_array); $i++ ) {
            if( 
$cat_array[$i] < ) {
                
$get_cats_exclude[] = abs("$cat_array[$i]");
            } else {
                
$get_cats_include[] = "$cat_array[$i]";
            }
        }
        if( 
count($get_cats_include) > ) {
            
$get_cats ' AND '.$tablepost2cat.'.category_id IN ( '.implode','$get_cats_include ).' ) ';
        }
        if( 
count($get_cats_exclude) > ) {
            
$get_cats .= 'AND '.$tablepost2cat.'.category_id NOT IN ( '.implode','$get_cats_exclude ).' ) ';
        }
    } else {
        
$get_cats '';
    }

    
// this is what will separate dates on weekly archive links
    
$archive_week_separator '&#8211;';

    
// archive link url
    
$archive_link_m get_settings('siteurl').'/'.get_settings('blogfilename').$querystring_start.'m'.$querystring_equal;    # monthly archive;
    
$archive_link_w get_settings('siteurl').'/'.get_settings('blogfilename').$querystring_start.'w'.$querystring_equal;    # weekly archive;
    
$archive_link_p get_settings('siteurl').'/'.get_settings('blogfilename').$querystring_start.'p'.$querystring_equal;    # post-by-post archive;

    // over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride
    
$archive_date_format_over_ride 0;

    
// options for daily archive (only if you over-ride the general date format)
    
$archive_day_date_format 'Y/m/d';

    
// options for weekly archive (only if you over-ride the general date format)
    
$archive_week_start_date_format 'Y/m/d';
    
$archive_week_end_date_format   'Y/m/d';

    if (!
$archive_date_format_over_ride) {
        
$archive_day_date_format get_settings('date_format');
        
$archive_week_start_date_format get_settings('date_format');
        
$archive_week_end_date_format get_settings('date_format');
    }

    
$add_hours intval(get_settings('gmt_offset'));
    
$add_minutes intval(60 * (get_settings('gmt_offset') - $add_hours));

    
$now current_time('mysql');

    if (
'monthly' == $type) {
        
$arcresults $wpdb->get_results("SELECT DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $tableposts LEFT JOIN $tablepost2cat ON (ID = post_ID) WHERE post_date < '$now' AND post_status = 'publish' $get_cats GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC" $limit);
        if (
$arcresults) {
            
$afterafter $after;
            foreach (
$arcresults as $arcresult) {
                
$url  get_month_link($arcresult->year,   $arcresult->month);
                if (
$show_post_count) {
                    
$text sprintf('%s %d'$month[zeroise($arcresult->month,2)], $arcresult->year);
                    
$after '&nbsp;('.$arcresult->posts.')' $afterafter;
                } else {
                    
$text sprintf('%s %d'$month[zeroise($arcresult->month,2)], $arcresult->year);
                }
                echo 
get_archives_link($url$text$format$before$after);
            }
        }
    } elseif (
'daily' == $type) {
        
$arcresults $wpdb->get_results("SELECT DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth` FROM $tableposts LEFT JOIN $tablepost2cat ON (ID = post_ID) WHERE post_date < '$now' AND post_status = 'publish' $get_cats ORDER BY post_date DESC" $limit);
        if (
$arcresults) {
            foreach (
$arcresults as $arcresult) {
                
$url  get_day_link($arcresult->year$arcresult->month$arcresult->dayofmonth);
                
$date sprintf("%d-%02d-%02d 00:00:00"$arcresult->year$arcresult->month$arcresult->dayofmonth);
                
$text mysql2date($archive_day_date_format$date);
                echo 
get_archives_link($url$text$format$before$after);
            }
        }
    } elseif (
'weekly' == $type) {
    
$start_of_week get_settings('start_of_week');
        
$arcresults $wpdb->get_results("SELECT DISTINCT WEEK(post_date, $start_of_week) AS `week`, YEAR(post_date) AS yr, DATE_FORMAT(post_date, '%Y-%m-%d') AS yyyymmdd FROM $tableposts LEFT JOIN $tablepost2cat ON (ID = post_ID) WHERE post_date < '$now' AND post_status = 'publish' $get_cats ORDER BY post_date DESC" $limit);
        
$arc_w_last '';
        if (
$arcresults) {
            foreach (
$arcresults as $arcresult) {
                if (
$arcresult->week != $arc_w_last) {
                    
$arc_year $arcresult->yr;
                    
$arc_w_last $arcresult->week;
                    
$arc_week get_weekstartend($arcresult->yyyymmddget_settings('start_of_week'));
                    
$arc_week_start date_i18n($archive_week_start_date_format$arc_week['start']);
                    
$arc_week_end date_i18n($archive_week_end_date_format$arc_week['end']);
                    
$url  sprintf('%s/%s%sm%s%s%sw%s%d'get_settings('home'), get_settings('blogfilename'), $querystring_start,
                                    
$querystring_equal$arc_year$querystring_separator,
                                    
$querystring_equal$arcresult->week);
                    
$text $arc_week_start $archive_week_separator $arc_week_end;
                    echo 
get_archives_link($url$text$format$before$after);
                }
            }
        }
    } elseif (
'postbypost' == $type) {
        
$arcresults $wpdb->get_results("SELECT ID, post_date, post_title FROM $tableposts LEFT JOIN $tablepost2cat ON (ID = post_ID) WHERE post_date < '$now' AND post_status = 'publish' $get_cats ORDER BY post_date DESC" $limit);
        if (
$arcresults) {
            foreach (
$arcresults as $arcresult) {
                if (
$arcresult->post_date != '0000-00-00 00:00:00') {
                    
$url  get_permalink($arcresult->ID);
                    
$arc_title stripslashes($arcresult->post_title);
                    if (
$arc_title) {
                        
$text strip_tags($arc_title);
                    } else {
                        
$text $arcresult->ID;
                    }
                    echo 
get_archives_link($url$text$format$before$after);
                }
            }
        }
    }
}



function 
get_cats_calendar($daylength 1$category '') {
    global 
$wpdb$m$monthnum$year$timedifference$month$month_abbrev$weekday$weekday_initial$weekday_abbrev$tableposts$tablepost2cat$posts;

    if (
$category) {
        
$cat_array explode','$category ); // Make array of cats & nocats

        
for( $i=0$i count($cat_array); $i++ ) {
            if( 
$cat_array[$i] < ) {
                
$get_cats_exclude[] = abs("$cat_array[$i]");
            } else {
                
$get_cats_include[] = "$cat_array[$i]";
            }
        }
        if( 
count($get_cats_include) > ) {
            
$get_cats ' AND '.$tablepost2cat.'.category_id IN ( '.implode','$get_cats_include ).' ) ';
        }
        if( 
count($get_cats_exclude) > ) {
            
$get_cats .= 'AND '.$tablepost2cat.'.category_id NOT IN ( '.implode','$get_cats_exclude ).' ) ';
        }
    } else {
        
$get_cats '';
    }

    
// Quick check. If we have no posts at all, abort!
    
if (!$posts) {
        
$gotsome $wpdb->get_var("SELECT ID from $tableposts LEFT JOIN $tablepost2cat ON (ID = post_ID) WHERE post_status = 'publish' $get_cats ORDER BY post_date DESC LIMIT 1");
        if (!
$gotsome)
            return;
    }

    if (isset(
$_GET['w'])) {
        
$w ''.intval($_GET['w']);
    }

    
$add_hours intval(get_settings('gmt_offset'));
    
$add_minutes intval(60 * (get_settings('gmt_offset') - $add_hours));

    
// Let's figure out when we are
    
if (!empty($monthnum) && !empty($year)) {
        
$thismonth ''.zeroise(intval($monthnum), 2);
        
$thisyear ''.intval($year);
    } elseif (!empty(
$w)) {
        
// We need to get the month from MySQL
        
$thisyear ''.intval(substr($m04));
        
$d = (($w 1) * 7) + 6//it seems MySQL's weeks disagree with PHP's
        
$thismonth $wpdb->get_var("SELECT DATE_FORMAT((DATE_ADD('${thisyear}0101', INTERVAL $d DAY) ), '%m')");
    } elseif (!empty(
$m)) {
        
$calendar substr($m06);
        
$thisyear ''.intval(substr($m04));
        if (
strlen($m) < 6) {
            
$thismonth '01';
        } else {
            
$thismonth ''.zeroise(intval(substr($m42)), 2);
        }
    } else {
        
$thisyear gmdate('Y'current_time('timestamp') + get_settings('gmt_offset') * 3600);
        
$thismonth gmdate('m'current_time('timestamp') + get_settings('gmt_offset') * 3600);
    }

    
$unixmonth mktime(00$thismonth1$thisyear);

    
// Get the next and previous month and year with at least one post
    
$previous $wpdb->get_row("SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year
            FROM $tableposts
            LEFT JOIN $tablepost2cat ON (ID = post_ID) 
            WHERE post_date < '$thisyear-$thismonth-01'
            AND post_status = 'publish'
            $get_cats
                              ORDER BY post_date DESC
                              LIMIT 1"
);
    
$next $wpdb->get_row("SELECT  DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year
            FROM $tableposts
            LEFT JOIN $tablepost2cat ON (ID = post_ID) 
            WHERE post_date >  '$thisyear-$thismonth-01'
            AND MONTH( post_date ) != MONTH( '$thisyear-$thismonth-01' )
            AND post_status = 'publish'
            $get_cats
                              ORDER  BY post_date ASC
                              LIMIT 1"
);

    echo 
'<table id="wp-calendar">
    <caption>' 
$month[zeroise($thismonth2)] . ' ' date('Y'$unixmonth) . '</caption>
    <thead>
    <tr>'
;

    
$day_abbrev $weekday_initial;
    if (
$daylength 1) {
        
$day_abbrev $weekday_abbrev;
    }

    foreach (
$weekday as $wd) {
        echo 
"\n\t\t<th abbr=\"$wd\" scope=\"col\" title=\"$wd\">" $day_abbrev[$wd] . '</th>';
    }

    echo 
'
    </tr>
    </thead>

    <tfoot>
    <tr>'
;

    if (
$previous) {
        echo 
"\n\t\t".'<td abbr="' $month[zeroise($previous->month2)] . '" colspan="3" id="prev"><a href="' .
            
get_month_link($previous->year$previous->month) . '" title="' sprintf(__('View posts for %1$s %2$s'), $month[zeroise($previous->month2)], date('Y'mktime(00$previous->month1$previous->year))) . '">&laquo; ' $month_abbrev[$month[zeroise($previous->month2)]] . '</a></td>';
    } else {
        echo 
"\n\t\t".'<td colspan="3" id="prev" class="pad">&nbsp;</td>';
    }

    echo 
"\n\t\t".'<td class="pad">&nbsp;</td>';

    if (
$next) {
        echo 
"\n\t\t".'<td abbr="' $month[zeroise($next->month2)] . '" colspan="3" id="next"><a href="' .
                
get_month_link($next->year$next->month) . '" title="View posts for ' $month[zeroise($next->month2)] . ' ' .
                
date('Y'mktime(00$next->month1$next->year)) . '">' substr($month[zeroise($next->month2)], 03) . ' &raquo;</a></td>';
    } else {
        echo 
"\n\t\t".'<td colspan="3" id="next" class="pad">&nbsp;</td>';
    }

    echo 
'
    </tr>
    </tfoot>

    <tbody>
    <tr>'
;

    
// Get days with posts
    
$dayswithposts $wpdb->get_results("SELECT DISTINCT DAYOFMONTH(post_date)
            FROM $tableposts
            LEFT JOIN $tablepost2cat ON (ID = post_ID) 
            WHERE MONTH(post_date) = $thismonth
            AND YEAR(post_date) = $thisyear
            AND post_status = 'publish'
            AND post_date < '" 
current_time('mysql') . '\''
            
"$get_cats"ARRAY_N);
    if (
$dayswithposts) {
        foreach (
$dayswithposts as $daywith) {
            
$daywithpost[] = $daywith[0];
        }
    } else {
        
$daywithpost = array();
    }



    if (
strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') ||
          
strstr(strtolower($_SERVER['HTTP_USER_AGENT']), 'camino') ||
          
strstr(strtolower($_SERVER['HTTP_USER_AGENT']), 'safari')) {
        
$ak_title_separator "\n";
    } else {
        
$ak_title_separator ', ';
    }

    
$ak_titles_for_day = array();
    
$ak_post_titles $wpdb->get_results("SELECT post_title, DAYOFMONTH(post_date) as dom
                                          FROM $tableposts
                                          LEFT JOIN $tablepost2cat ON (ID = post_ID)
                                          WHERE YEAR(post_date) = '$thisyear'
                                          AND MONTH(post_date) = '$thismonth'
                                          AND post_date < '"
.current_time('mysql')."'
                                          AND post_status = 'publish'
                                          $get_cats
                                        "
);
    if (
$ak_post_titles) {
        foreach (
$ak_post_titles as $ak_post_title) {
            if (empty(
$ak_titles_for_day['day_'.$ak_post_title->dom])) {
                
$ak_titles_for_day['day_'.$ak_post_title->dom] = '';
            }
            if (empty(
$ak_titles_for_day["$ak_post_title->dom"])) { // first one
                
$ak_titles_for_day["$ak_post_title->dom"] = htmlspecialchars(stripslashes($ak_post_title->post_title));
            } else {
                
$ak_titles_for_day["$ak_post_title->dom"] .= $ak_title_separator htmlspecialchars(stripslashes($ak_post_title->post_title));
            }
        }
    }


    
// See how much we should pad in the beginning
    
$pad intval(date('w'$unixmonth));
    if (
!= $pad) echo "\n\t\t".'<td colspan="'.$pad.'" class="pad">&nbsp;</td>';

    
$daysinmonth intval(date('t'$unixmonth));
    for (
$day 1$day <= $daysinmonth; ++$day) {
        if (isset(
$newrow) && $newrow)
            echo 
"\n\t</tr>\n\t<tr>\n\t\t";
        
$newrow false;

        if (
$day == gmdate('j', (time() + (get_settings('gmt_offset') * 3600))) && $thismonth == gmdate('m'time()+(get_settings('gmt_offset') * 3600)))
            echo 
'<td id="today">';
        else
            echo 
'<td>';

        if (
in_array($day$daywithpost)) { // any posts today?
            
echo '<a href="' get_day_link($thisyear$thismonth$day) . "\" title=\"$ak_titles_for_day[$day]\">$day</a>";
        } else {
            echo 
$day;
        }
        echo 
'</td>';

        if (
== date('w'mktime(00$thismonth$day$thisyear)))
            
$newrow true;
    }

    
$pad date('w'mktime(00$thismonth$day$thisyear));
    if (
$pad != && $pad != 7)
        echo 
"\n\t\t".'<td class="pad" colspan="'.$pad.'">&nbsp;</td>';

    echo 
"\n\t</tr>\n\t</tbody>\n\t</table>";
}


?>