Hello Forum!

I'm in the process of modifying the code for the open source Ajax Availability Calendar (http://www.ajaxavailabilitycalendar.com/) and I'm so close but I need help.

I've installed the code on my test server here: http://www.mindypostoff.com/wordpress/calendar/

If you select "Surin Project" as the Project, you'll see a new drop-down appears for "# of Weeks". The availability calendar displays the current weeks that are fully booked (Dec 2 and Jan 27) from values stored in the database.

Ideally, if you change the # of weeks value to "2", the Mondays prior to the booked weeks should also display as booked, but since those dates are available for single week bookings, I can't update the database with a "booked" status.

I have PHP code running that is properly updating the monthly calendars and closing out weeks as necessary, but ONLY if those dates are in the same month. So, in the example, both Nov 25 and Jan 20 should automatically show as booked when you change # of Weeks to "2". Unfortunately, since the month of Nov has already been "printed", I can't seem to modify the dates.

Below is the code generating the months:

function draw_cal($id_item,$month,$year,$manage_type="avail"){
	global $lang;

$month=sprintf("%02s",$month);
//	define vars
$today_timestamp	=   mktime(0,0,0,date('m'),date('d'),date('Y'));
$next_days		=   mktime(0,0,0,date('m'),date('d')+5,date('Y'));
$this_month 		= 	getDate(mktime(0, 0, 0, $month, 1, $year));
$first_week_day 	= $this_month["wday"];
$days_in_this_month = cal_days_in_month(CAL_GREGORIAN,$month,$year);	
$day_counter_tot	=	0; 

//	get num days in previous month - used to add dates to "empty" cells
$month_last	= $month-1;
$year_last	= $year;
if($month_last<1){
	$month_last=12;
	$year_last=$year-1;	
}
$days_in_last_month = cal_days_in_month(CAL_GREGORIAN,$month_last,$year_last);

//	day column titles - using first letter of each day
if($show_week_num)	$list_day_titles='<li class="weeknum_spacer"></li>';

if(AC_START_DAY=="sun"){
	for($k=0; $k<7; $k++){
		$weekday = mb_substr($lang["day_".$k.""],0,1,'UTF-8');
		$list_day_titles.='<li class="cal_weekday"> '.$weekday.'</li>';
	}
}else{
	if ($first_week_day == 0)	$first_week_day =7;
	for($k=1; $k<=7; $k++){
		if($k==7) 	$weekday = mb_substr($lang["day_0"][0],0,1,'UTF-8');
		else		$weekday = mb_substr($lang["day_".$k.""],0,1,'UTF-8');
		$list_day_titles.='<li title="'.$lang["day_".$k.""].'"> '.$weekday.'</li>';
	}
}

//	Fill the first week of the month with the appropriate number of blanks.       
$j=1;
if(AC_START_DAY=="sun")	$first_week_day_start	= $first_week_day;
else					$first_week_day	= $first_week_day-1;

$row_counter=0;

if($first_week_day!=7){
	if($show_week_num)	$list_days.='<li class="weeknum">-</li>';
	$last_month_start_num=$days_in_last_month-$first_week_day+1;
	for($week_day = 0; $week_day < $first_week_day; $week_day++){
		$list_days.='<li class="cal_empty">'.$last_month_start_num.'</li>';   
		++$last_month_start_num;
		++$j;
		++$day_counter_tot;

		if($day_counter_tot % 7==1) ++$row_counter;
	}
}
$week_day=$j;

//	get bookings for this month and item from database
	$booked_days=array();
	$sql = "
	SELECT 
		t1.the_date,
		t2.class,
		t2.desc_".AC_LANG." AS the_state
	FROM 
		".T_BOOKINGS." AS t1
		LEFT JOIN ".T_BOOKING_STATES." AS t2 ON t2.id=t1.id_state
	WHERE 
		t1.id_item=".$id_item." 
		AND MONTH(t1.the_date)=".$month." 
		AND YEAR(t1.the_date)=".$year."
	";
	if(!$res=mysql_query($sql))	die("ERROR checking id item availability dates<br>".mysql_error());
	while($row=mysql_fetch_assoc($res)){
		$booked_days[$row["the_date"]]=array("class"=>$row["class"],"state"=>$row["the_state"]);
	}


//	loop thorugh days (til max in month) to draw calendar
for($day_counter = 1; $day_counter <= $days_in_this_month; $day_counter++){
	//	reset xtra classes for each day
	//	note - these classes acumulate for each day according to state, current and clickable
	$day_classes 	=	"";
	$day_title_state=	" - ".$lang["available"];

	//	set all dates to clickable for now		
	$day_classes.=' clickable';


	//	turn date into timestamp for comparison with current timestamp (defined above)
	$date_timestamp =   mktime(0,0,0, $month,($day_counter),$year);


	//	get week number
	$week_num=date("W",$date_timestamp);
	if($week_num!=$last_week_num){
		//	new week
		//$list_days .= '<li>-</li>';
	}
	//	highlight current day
	if($date_timestamp==$today_timestamp)  $day_classes.=' today';

	//	format date for db modifying - the date is passed via ajax
	$date_db		=	$year."-".sprintf("%02s",$month)."-".sprintf("%02s",$day_counter);

	$one_wk			=	mktime(0,0,0,$month,($day_counter)+7,$year);
	$one_wk_year		=	date("Y",$one_wk);
	$one_wk_month		=	date("m",$one_wk);
	$one_wk_day		=	date("d",$one_wk);
	$one_wk_db		=	$one_wk_year."-".sprintf("%02s",$one_wk_month)."-".sprintf("%02s",$one_wk_day);


    //	format date for display only
    if(AC_DATE_DISPLAY_FORMAT=="us")	$date_format	=	$month."/".$day_counter."/".$year;
    else 			        			$date_format	=	$day_counter."/".$month."/".$year;

	//	check if day is available
	if(array_key_exists($date_db,$booked_days)) {
		$day_classes.=" ".$booked_days[$date_db]["class"];
		$day_title_state=" - ".$booked_days[$date_db]["state"];
	}

	$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
	$num_weeks = (int)(substr($url,-1));

	// if 2 weeks of volunteering is selected, must check if one week later is available	
	if ($num_weeks === 2) {

		if(array_key_exists($one_wk_db,$booked_days)) {
			$day_classes.=" ".$booked_days[$one_wk_db]["class"];
			$day_title_state=" - ".$booked_days[$one_wk_db]["state"];
		}

	}

	//	check if date is past			
	if ($date_timestamp<$next_days){
		$day_classes.=" past";	
		$day_classes=str_replace(' booked','',$day_classes);

		//	overwrite clickable state if CLICKABLE_PAST is off
		if(AC_ACTIVE_PAST_DATES=="off"){
			//	date is previous - strip out "clickable" from classes
			$day_classes=str_replace(' clickable','',$day_classes);
			$day_classes .= " empty";
		}
	}

	//	highlight current day
	if($date_timestamp==$today_timestamp){
		$day_classes.=' today';
		$day_classes=str_replace(' past','',$day_classes);
		$day_classes=str_replace(' empty','',$day_classes);
	}


	if (strpos($day_classes,'booked') !== false && strpos($day_classes, 'clickable')) {
		$day_classes=str_replace(' clickable','',$day_classes);
	}

	if (strpos($day_classes,'admin') !== false) {
		$day_classes .= ' clickable';
	}


	// make all days except Mondays unavailable for volunteer programs
	if (($id_item != 1) && ($id_item != 2) && ($id_item != 9)) {
		$day_of_week = date("N",$date_timestamp);
		if ($day_of_week != 1) {
			$day_classes = str_replace(' clickable','',$day_classes);
			$day_classes .= " past";
		}
	}

	//'.$lang["day_".$getdate["wday"].""].'
	$list_days .= '
	<li class="'.$day_classes.' "  id="date_'.$date_db.'" title="'.$date_format.$day_title_state.'" data-date="'.$date_format.'">'.$day_counter.'</li>';

	//	reset weekday counter if 7 (6)
	$week_day %= 7;		#	reset weekday to 0
	++$week_day;			#	increase weekday counter
	++$day_counter_tot;		#	add 1 to total days shown
	//echo "<br>".$week_day;
	if($show_week_num){
		if ($week_day==1) $list_days .= '<li class="weeknum">'.$week_num.'</li>';
	}
	$last_week_num=$week_num;
	if($day_counter_tot % 7==1) ++$row_counter;
}
//	add empty days till end of row
$next_month_day=1;

while($row_counter<6){
	//add days until it does :)
	for($till_day = $week_day; $till_day <=7; $till_day++){
		$list_days .= '<li class="cal_empty">'.$next_month_day.'</li>'; 
		++$next_month_day;  
		++$day_counter_tot;		#	add 1 to total days shown

	if($day_counter_tot % 7==1) ++$row_counter;
	}
	$week_day=1;

}
//	add empty dates (with next month numbers) until we get to 7
if($week_day > 1){
	for($till_day = $week_day; $till_day <=7; $till_day++){
		$list_days .= '<li class="cal_empty">'.$next_month_day.'</li>'; 
		++$next_month_day;  
		++$day_counter_tot;		#	add 1 to total days shown
	}
}


//	put it all together (parent div defined in parent file)
$the_cal='
<div id="'.$month.'_'.$year.'" class="cal_title">'.$lang["month_".$month.""].' '.$year.'</div>
<ul class="cal_weekday">
	'.$list_day_titles.'
</ul> 
<ul>
	'.$list_days.'
</ul>
<div class="clear"></div>
';

return $the_cal;

The open source project has numerous other files, and it makes my head spin. Please let me know if you have questions and I truly, truly appreciate your time and help with this!

Thank you,
Mindy : )

    The issue you are facing is that you have asked a question about the inner workings of a fairly obscure PHP project which might require some generous soul with time on their hands to dig in and understand it enough to answer your question -- and this is unlikely. If you could get closer to isolating the logic that needs to be changed and get more specific about general PHP questions, that would probably be a better path to success.

    In the meantime, there are lots of php functions related to time and date which are pretty flexible. [man]strtotime[/man], for instance, can take a wide variety of plain-english date expressions and convert them to a unix timestamp. The DateTime object also has functionality to add and subtract dates. These functions don't depend on any month boundaries or year boundaries generally speaking and might be quite useful.

      sneakyimp;11034881 wrote:

      The issue you are facing is that you have asked a question about the inner workings of a fairly obscure PHP project which might require some generous soul with time on their hands to dig in and understand it enough to answer your question -- and this is unlikely.

      Moreover, it seems to be a bad choice for a few noteable reasons listed below. I'd recommend finding something else if possible. If not, I'd urge you to fix this project before you even start using it, which may actually take more time than starting over from scratch.

      1. ext/mysql has been deprecated and is flagged for removal. Do not use it.

        mysql_query($sql)
        

        Both Oracle's and PHP's documentations tells you to stop using ext/mysql. Since I do not use it, I do not keep track of these things, but i believe it will be completely removed in php version, 5.6.

      2. Displaying internal error information to end users is bad

            if(!$res=mysql_query($sql))	die("ERROR checking id item availability dates<br>".mysql_error());
        
      3. Using die() generally leads to a crappy end user experience. We do not like blank pages.

            if(!$res=mysql_query($sql))	die("ERROR checking id item availability dates<br>".mysql_error());
        
      4. function draw_cal should be refactored
        It is 3 pages long and uses comments to describe functionality instead of breaking it down in smaller self-explanatory chunks.

      The first item on that list would be enough for me to stay far away from this project. ext/mysql was superceded by ext/mysqli several years ago. Any project still using mysql either lacks the ability to keep even remotely in line with the devlopment of php, or simply hasn't been developed at all for several years.

      Items 2, 3 and 4 are bad form and tell me the project is of poor quality. Should you still choose to use it, you will most likely have to spend a lot of time maintaining something which is flawed from the start.

        Write a Reply...