I had to come up with this post because I’ve been working on an old CMS about 3 years old (or even more) and I had been wondering why the calendar links cuts off from 2001 to 2003.
Task: List a year/month links from the present to the oldest published image sets.
Sounds easy, and I believe it is.
But when I checked on the existing script, this is what I got.
$month_array = array("1"=>'January',"2"=>'February',"3"=>'March',"4"=>'April',"5"=>'May',"6"=>'June',"7"=>'July',"8"=>'August',"9"=>'September',"10"=>'October',"11"=>'November',"12"=>'December');
$smarty->assign('y2day',$y2day); $y=0;
for ($q=12; $q >= 1; $q--){
$month = $month_array[$q];
if( ($_GET[year] < '2000') && ($m2day ==$q ) ) $w_string = $week_string; else $w_string ='';
if( ($_GET[year] == '2007') && ($_GET[month] == $q) ) $w_string = $week_string;
if($m2day >= $q){
$tmp_cal_month_now_array = array(
'month' => $month,
'string' => $w_string,
'link' => $q
); $date_month_now_array[$y++] = $tmp_cal_month_now_array; }
} //for
$smarty->assign('calendar_now_month',$date_month_now_array);
$y=0; $c_yeartoday = date("Y") -1; //echo $c_yeartoday;
for($q=0; $q < = 5; $q++){
$tmp =$c_yeartoday - $q; //echo $tmp;
$tmp_cal_date_array = array(
'year' => $tmp
); $date_year_array[$y++] = $tmp_cal_date_array;
} //for
$smarty->assign('calendar_year',$date_year_array);
$y=0;
for($q=12; $q >= 1; $q--)
{
$month = $month_array[$q];
if( $_GET[month] == $q ) $w_string = $week_string; else $w_string='';
$tmp_cal_month_array = array(
'month' => $month,
'string' => $w_string,
'link' => $q
); $date_month_array[$y++] = $tmp_cal_month_array;
}//for
$smarty->assign('calendar_month',$date_month_array);
$y=0;
for($q=12; $q >= 10; $q--)
{
$month = $month_array[$q];
if( ($_GET[year] == '2000') && ($_GET[month] == $q) ) $w_string = $week_string; else $w_string='';
$tmp_cal_month_old_array = array(
'month' => $month,
'string' => $w_string,
'link' => $q
); $date_month_old_array[$y++] = $tmp_cal_month_old_array;
}//for
$smarty->assign('calendar_month_old',$date_month_old_array);
Looking at the above script, it looks like they were grouped in to 4 sections, deriving the values of $date_month_now_array, $date_year_array, $date_month_array and $date_month_old_array. And the hardcoded values ’2000′ and ’2007′ will definitely set limit and obviously introduce bug, and so it did. Honestly, I would have coded it this way when I was moving into PHP 3 years ago, and perhaps even now if I’d have been coding for a whole day confronted with bugs.
Anyway, the main problem with the above code is, there was always a reference for dates and the original programmer didn’t use it, the date column in the content’s table. Instead, I’m guessing, he setup a start ‘year’ which is probably he asked someone about the oldest possible year a content was published – there he arrived at using ’2000′ in the code. And if I’m not mistaken, this code was written in 2007, LOL, so there was a condition on year set to 2007.
Here’s how I modified it, optimized it as much (well I hope). The date column had a unix timestamp values, so it’s not in typical date format.
/**
* Calendar modification
* @author marvin marcelo
* @uses ez_sql
* @link http://www.phpclasses.org/browse/package/790.html
*/
/* present */
list($y, $m, $d) = explode(" ", date("Y n j"));
$sql = "select distinct(from_unixtime(updateStartDate, '%Y')) year
from series_table where updateStartDate > 0 order by updateStartDate desc";
/* ezSql stuff */
$years = $db->get_results($sql, ARRAY_A);
for ($i = 0; $i < count($years); ++$i)
{
$months = array();
for ($j = 12; $j > 0; --$j)
{
$endofmonth = date("t", strtotime("{$years[$i]["year"]}-$j-1"));
if ($years[$i]["year"] == $y && $j > $m)
{
continue; /* future year-month */
}
if ($years[$i]["year"] == $y && $j == $m)
{
/* this day in this month of this year is also future, use current date instead */
$endofmonth = $d;
}
$ts0 = strtotime("{$years[$i]["year"]}-$j-1"); /* unix timestamp start of month */
$ts1 = strtotime("{$years[$i]["year"]}-$j-$endofmonth"); /* unix timestamp last day or today of month */
if ($db->get_row("select * from series_table where updateStartDate > $ts0 and updateStartDate < = $ts1"))
{
if ($year == $years[$i]["year"] && $j == $month)
{
$months[] = array("active" => "1", "j" => $j, "F" => date("F", $ts0));
}
else
{
$months[] = array("j" => $j, "F" => date("F", $ts0));
}
}
}
if (count($months))
{
$years[$i]["months"] = $months;
}
}
/* template */
$smarty->assign('calendar', $years);
/**
* Calendar modification end block
*/
The process I did …
- Select distinct years from all published content by converting unix timestamp to readable year value, then iterate on them
- Do a for loop from 12 (december) to 1 (january) to generate a unix timestamp for use in the next query
- Query the table for a matching timestamp of the first day and the last day of month-year pair; Use current day of month if iterating year and month matches the present
- Show the month link for the year in iteration if a match is found
Couple of notes though, I didn’t name the table as ‘series_table’
, it’s been there years since. I also named my variables when referring to start and end as $x0 and $x1, $ts0 and $ts1. I got used to this when college years in physics – the start and end of a distance, I don’t know, I just like the thought
.
Hope it didn’t went order to chaos at all!