<?php

/**
 *some useful calendar functions
 */
class Calendar {

    /**
     * month num
     * @var int
     */ 
    private $_month;
    
    /**
     * year
     * @var int
     */
    private $_year;

    /**
     * starting day
     * @var int
     */
    private $_startDay = 0;
    
    public function __construct($monthNum = null, $yearNum = null)
    {
        if (is_null($yearNum)) $this->_year = date('Y');
        if (is_null($monthNum)) $this->_month = date('n');
        $this->_startDay = 0;
    }

    public function getMonth()
    {
        return $this->_month;
    }
    

    public function getYear()
    {
        return $this->_year;
    }
    
    /**
     * Returns first day in the actual calendar month.
     * @return int unix timestamp
     */
    public function getFirstMonthDay()
    {
        return mktime(0, 0, 0, $this->_month, 1, $this->_year);
    }
   
    /**
     * Sets start day of the week
     * @param int $startDayNum
     * startDayNum can be
     * - 0 : Sunday
     * - 1 : Monday
     * - 2 : Tuesday
     *  ....
     * - 6 :
     * @throws OutOfRangeException when $startDayNum is out of range (0..6)
     */
    public function setStartDay($startDayNum)
    {
        if ($startDayNum < 0 || $startDayNum > 6) throw new OutOfRangeException("start day must be in a interval 0..6");
        $this->_startDay = $startDayNum;
    }
  
    public function getStartDay()
    {
        return $this->_startDay;
    }
 
    public function setYear($yearNum)
    {
        $this->_year = $yearNum;
    }
    
    public function setMonth($monthNum)
    {
        $this->_month = $monthNum;
    }
    
    public function getMonthArray()
    {
        //first day in a month
        $firstDay = $this->getFirstMonthDay();
        if ($firstDay === false) throw new InvalidArgumentException("cannot create
            timestamp for the first day in the month, a month or a year is invalid");
        $firtsDayDigit = date('w', $firstDay);
        $firstDayOffset = $firtsDayDigit - $this->_startDay;
        if ($firstDayOffset < 0) $firstDayOffset+= 7;
        //number of days in a month
        $days = date('t', $firstDay);
        $monthArray = array();
        $dayNum = 1;
        while ($dayNum <= $days) {
            $weekArray = array();
            for ($i = 0;$i < 7;$i++) {
                if (($dayNum == 1 && $firstDayOffset > $i) || $dayNum > $days) {
                    $weekArray[] = null;
                } else {
                    $weekArray[] = $dayNum++;
                }
            }
            $monthArray[] = $weekArray;
        }
        return $monthArray;
    }
    
    public static function shiftDayNames($startDay, &$dayNames)
    {
        while ($startDay-- > 0) {
            $day = array_shift($dayNames);
            array_push($dayNames, $day);
        }
    }
}
