<?php
class calendar {
 private $nday,$nmon,$nyear; //Текущие день, месяц и год - менять извне нельзя!
 public $dayslinecolor='#333333', //Цвет названия дней
  $holidaycolor='red', //Цвет выходных и названий выходных
  $weekdaycolor='#000066', //Цвет обычных дней
  $todaycolor='green', //Цвет сегодняшнего дня
  $maintabcolumns=4, //Сколько столбцов в таблице месяцев (1-12)
  $weekhorizontalorientation=false, //Горизонтальное положение недель (true-вкл.)
  $showform=false, //Показывать ли форму выбора года (true-вкл.)
  $year1=1970, //Год начала списка лет в форме
  $year2=2035, //Год окончания списка лет в форме
  $selectedyear, //Год, выбранный в форме как текущий
  $month1=1, //Первый месяц календаря
  $month2=12, //Последний месяц календаря
  $text = ''; //Будем код календаря писать в эту переменную, так легче потом интегрировать
 public $months=array("Январь","Февраль","Март","Апрель","Май","Июнь",
  "Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"); //Названия месяцев
 public $days=array("Пн","Вт","Ср","Чт","Пт","Сб","Вс"); //Названия дней недели
 public $dayscount=array("31","28","31","30","31","30", 
  "31","31","30","31","30","31"); //Число дней в месяцах
 public $maincellspacing=5, //Расстояние между ячейками месяцев в главной таблице
  $maincellpadding=5, //Отступ от края ячейки месяца в главной таблице
  $monthsize=2, //Размер названий месяцев $months (1-7)
  $daysize=1; //Размер чисел в таблице месяца (1-7)
 public $links=array(); //Список ссылок для вывода в календаре
 public $defaultlinktarget='_self'; //Целевое окно ссылок календаря по умолчанию
  // '_self' - текущее окно, '_blank' - новое окно

 function __construct () { //Конструктор
  list($this->nyear,$this->nmon,$this->nday) = explode(".",date('Y.m.d')); 
  $this->selectedyear=$this->nyear;
 }

 function leapyear ($y) { //true, если год високосный
  return ($y%4==0) and ($y%100!=0) or ($y%400==0); 
 }

 function putform ($y1=1970,$y2=2135) { //Вывод формы выбора года
  $text='';
  if (empty($_REQUEST['selectedyear'])) $this->selectedyear = $this->nyear; 
  else $this->selectedyear = intval(strip_tags(trim($_REQUEST['selectedyear'])));
  $text.='<div align="center"><form action="'.$_SERVER['PHP_SELF'].
   '" method="POST"><select name="selectedyear" size="1">';
  for ($year=$y1;$year<=$y2;$year++) {
   if ($this->selectedyear == $year) $sel = ' selected'; else $sel = '';
   $text.="<option value=$year $sel>$year";
  }
  $text.='</select> <input type="submit" value="OK"></center></form></div>';
  return $text;
 }

 function drawhorizontalmonth ($firstday,$mon,$year,$daysamount) {
  //Рисует горизонтальный календарь на месяц
  $text= "\n".'<table border="0" align="center"><caption><font size="'.$this->monthsize.'">'.
   $this->months[$mon-1].'</font></caption><tr>';
  for ($i=0;$i<7;$i++) {
   $day=$this->days[$i];
   $text.= '<td align="center"><font size="'.$this->daysize.'" color="'.
    ($i>4?$this->holidaycolor:$this->dayslinecolor).'">'.ucfirst($day).'</font></td>'; 
  }
  $text.= '</tr><tr>';
  for($i=0; $i<$firstday; $i++) $text.= '<td><font size="'.$this->daysize.'">&nbsp;</font></td>';
  for ($q=1; $q<$daysamount; $q++) {
   if ($q==$this->nday and $mon==$this->nmon and $year==$this->nyear) $color=$this->todaycolor;
   else if ($firstday<5) $color=$this->weekdaycolor; 
   else $color=$this->holidaycolor;
   $firstday++;
  if ($firstday==7) $firstday=0;
   $text.= '<td align="right"><font size="'.$this->daysize.'" color="'.$color.'">'.
    $this->getdaylink($q,$mon,$year).'</font></td>'; 
   if(!strstr(''.($i+$q)/7,'.')) $text.= '</tr><tr>';
  }
  return $text.'</tr></table>';
 }

 function drawverticalmonth ($firstday,$mon,$year,$daysamount) {
  //Рисует вертикальный календарь на месяц
  $wd1=$firstday+1;
  $pn1=($wd1==1? 1 : 0);
  $wd=$wd1;
  $cols=1;
  $maxDay=$daysamount-1;
  $m=$mon;
  for ($i=1; $i<=$maxDay; $i++) {
   $wd++;
   if ($wd>7) {
    if ($pn1==0) $pn1=$i+1;
    $wd=1;
    if ($i<$maxDay) $cols++;
   }
  }
  $text = "\n".'<table border="0" align="center"><caption><font size="'.$this->monthsize.'">'.
   $this->months[$mon-1].'</font></caption>';
  for ($r=1; $r<8; $r++) {
   $wd=($pn1>1 ? $pn1+$r-1 : 7+$r );
   $text.='<tr><td align="center"><font size="'.$this->daysize.'" color="'.
    ($r>5?$this->holidaycolor:$this->dayslinecolor).'">'.ucfirst($this->days[$r-1]).'</font></td>';
   $rr=$r-($wd1-1);
   if ($rr==$this->nday and $m==$this->nmon and $year==$this->nyear) $color=$this->todaycolor;
   else if ($r>5) $color=$this->holidaycolor;
   else $color=$this->weekdaycolor;
   $text.='<td><font size="'.$this->daysize.'" color="'.$color.'">'.
    ($r<$wd1 ? '&nbsp;' : $this->getdaylink($rr,$mon,$year) ).'</font></td>';
   for ($c=1; $c<$cols; $c++) { 
    if ($wd==$this->nday and $m==$this->nmon and $year==$this->nyear) 
     $color=$this->todaycolor;
    else if ($r>5) $color=$this->holidaycolor;
    else $color=$this->weekdaycolor;
    $text.='<td align="right"><font size="'.$this->daysize.'" color="'.$color.'">'.
     ($wd>$maxDay ? '&nbsp;' : $this->getdaylink($wd,$mon,$year)).'</font></td>';
    $wd+=7;
   }
   $text.='</tr>';
  }
  return $text.'</table>';
 }

 function putcalendar ($m1=0,$m2=0) {
  //Возвращает календарь на месяцы [$m1,$m2] года $selectedyear
  if ($m1==0) $m1=$this->nmon;
  if ($m2==0) $m2=$this->nmon;
  if ($m1>$m2) { $a=$m1; $m1=$m2; $m2=$a; }
  $tabcol=$this->maintabcolumns;
  if ($m1==$m2) $tabcol=1;
  $text="\n".'<div align="center"><table border="0" cellspacing="'.$this->maincellspacing.
   '" cellpadding="'.$this->maincellpadding.'"><tr>';
  $rows=0; $cols=0; 
  for ($z=$m1;$z<=$m2;$z++) {
   $mon = $z;
   //Если форма не выводилась - selectedyear ставили в конструкторе
   $year = $this->selectedyear;
   $daysamount=($this->dayscount[$z-1])+1;
   if ($this->leapyear($year) and $z==2) $daysamount++;
   $firstday=date('w',mktime(0,0,0,$mon,0,(int)$year)); //0-6
   if ($mon>$m1 and $cols%$tabcol==0) { 
    $text.= '</tr><tr>'."\n"; 
    $rows++; $cols=0; 
   }
   $text.= '<td align="center" valign="top">';
   $cols++;
   if ($this->weekhorizontalorientation) { 
    //Рисуем месяц, когда недели по горизонтали
    $text.=$this->drawhorizontalmonth ($firstday,$mon,$year,$daysamount);
   }
   else {  //Рисуем месяц, когда недели по вертикали
    $text.=$this->drawverticalmonth ($firstday,$mon,$year,$daysamount);
   }
   $text.= '</td>';
  }
  if ($rows>0 and $cols<$tabcol) { //Дорисовать недостающие ячейки строки
   $voids = $tabcol - $cols;
   for ($i=0; $i<$voids; $i++) 
    $text.='<td><font size="'.$this->daysize.'">&nbsp;</font></td>';
  }
  return $text.'</tr></table></div>';  
 }

 function getdaylink ($day,$mon,$year,$target=0) {
  //Получить ранее сохранённую ссылку дня. $target может задавать имя окна (HTML).
  $t = mktime (0,0,0,$mon,$day,(int)$year);
  $tt=' target="';
  if ($target) $tt.=$target;
  else $tt.=$this->defaultlinktarget;
  $tt.='"';
  if (array_key_exists((int)$t,$this->links)) return '<a href="'.$this->links[$t].'"'.$tt.'>'.$day.'</a>';
  else return ''.$day;
 }

 function addlink ($day,$mon,$year,$url) {
  //Сохранить ссылку $url для указанной даты
  $t = mktime (0,0,0,$mon,$day,(int)$year);
  $this->links[(int)$t] = $url;
 }

 function show ($show=true) { //Показать форму и календарь
  //Если нужно только вернуть всё строкой - вызвать метод с параметром false
  if ($this->showform) {
   $this->text.=$this->putform ($this->year1,$this->year2);
  }
  $this->text.=$this->putcalendar ($this->month1,$this->month2);
  if ($show) echo $this->text;
  return $this->text;
 }
}
?>