PHP code block – bringing order to chaos

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 …

  1. Select distinct years from all published content by converting unix timestamp to readable year value, then iterate on them
  2. Do a for loop from 12 (december) to 1 (january) to generate a unix timestamp for use in the next query
  3. 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
  4. 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’ :D , 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!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>