title = $title; $this->date = $date; $this->author = $author; $this->description = $description; } } /** * Calendar exception */ class CalendarException extends Exception {} /** * Wrong month */ class NoSuchMonthException extends CalendarException { public function __construct($message) { parrent::__construct($message); } public function __toString() { return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; } } /** * Wrong day in month */ class NoSuchDayException extends CalendarException { public function __construct($message) { parent::__construct($message); } public function __toString() { return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; } } /** * Represents each day of month */ class Day { /** number of day in calendar */ public $number; /** day date in database date format */ public $date; /** is action today? */ public $isAction = false; /** an action held this day */ public $action = null; /** * creates new instance of Day * @param $number number of day in month * @param $action Action which is held this day * @throw NoSuchDayException when bad $number specified */ public function __construct($number, $date, Action $action = null) { //if ($number <= 0 || $number > 31) // throw new NoSuchDayException("Bad day number: '$number'!"); $this->number = $number; $this->date = $date; if (isset($action) && $action != null) { $this->isAction = true; $this->action = $action; } } /** * Tels if this day is some action set or not * @return true if this day is some action, false if not */ public function isAction() { return $this->isAction; } } /** * IView shows data to user */ interface IView { function show(); } /** * Handles main component logic. Is able to get or modify data from DB */ interface IModel { function getDays(); //returns Day[] function setDay(Action $a); function getMonth(); //returns int function setMonth($month); function getYear(); //returns int function setYear($year); } /* ============================= Controler ================================== */ /** * Controls interaction between Modes and View */ class Controler { /** instance of IModel to be controled */ private /*final*/ $model; /** instance of IView to be controled */ private /*final*/ $view; /* instance of IDatabase handling database acces */ //private IDatabase $db; //not here, but in Model (probably...) /** * creates new instance of Controler * @param $model instance of IModel, which operates raw data * @param $view instance if IView, which shows data */ public function __construct(IModel $model, IView $view/*, IDatabase $db*/) { $this->model = $model; $this->view = $view; //$this->view = new CalViewer($model); //$this->db = $db; } /** * When calendar location changed (it means month and year is changed) * need to get new data, and reshow calendar * @param $month current month * @param $year current year */ public function calLocationChanged($month, $year) { // year can be very big number and also very small or negative number // if not alow this, if ($month <= 0 || $month > 12) throw new NoSuchMonthException("No such mont can exists '$month'!"); $this->model->setMonth($month); $this->model->setYear($year); $this->view->show(); } } /* ================================ View ==================================== */ define('N', "\n"); //new line define('NL', "
".N); //"GUI" new line define('T', " "); //tabulator /** * Viewer */ class CalViewer implements IView { /** instance of IModel to be shown */ private /*final*/ $model; /** language used for localization texts */ private $lang = 'cs_CZ'; /** localization of calendar months */ private $i18n_months = array( 'cs_CZ' => array( 1 => 'Leden', 'Únor', 'Březen', 'Duben', 'Květen','Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad','Prosinec') ); /** localization of calendar days */ private $i18n_days = array( 'cs_CZ' => array( 'Po', 'Út', 'St', 'Čt', 'Pá', 'So', 'Ne') ); /** localization of calendar action headers */ private $i18n_action = array( 'cs_CZ' => array( /* 'title' => */ 'Titulek', /* 'date' => */ 'Datum', /* 'descr' => */ 'Popis', /* 'author' => */ 'Vložil') ); /** * creates new instance of IView * @param $model istance of IModel which will be shown */ public function __construct($model) { $this->model = $model; } /** * Shows calendar */ public function show() { $numOfColumns = $this->numberOfColumns(); print "".N; print T.''.N; print T.T.''.N; print T.''.N; $days = $this->model->getDays(); for ($r = 0; $r < 7; $r++) { //7 days in week = 7 rows print T.''.N.T.T; for($c = 0; $c < $numOfColumns; $c++) { $month = $this->model->getMonth(); $year = $this->model->getYear(); $day = $this->celContent($r, $c); //is today? if ($day->date == $this->today()) print ''; } print N.T.''.N; } print '
'. $this->i18n_months[$this->lang][$this->model->getMonth()].' '. $this->model->getYear().'
'.$day->number; else if ($c == 0) print ''.$day->number; else print ''.$day->number; //is an action this day? if ($day->isAction()) { print $this->actionToHTML($day->action); } print '
'.N; } /** * Sets language to be used. Also * @param $lang language abbreviation specifying used language */ public function setLang($lang) { $this->lang = $lang; } /** * Sets localization for month names in calendar * @param $lang language of localization * @param $months array of month titles */ public function addI18nMonths($lang, array $months) { // need to start array from 1 not from 0 for ($i = 0; $i < count($months); $i++) $this->i18n_months[$lang][$i + 1] = $months[$i]; } /** * Sets localization for day names in calendar * @param $lang language of localization * @param $days array of day titles */ public function addI18nDays($lang, array $days) { $this->i18n_days[$lang] = $days; } /** * Sets localization for action names in calendar * @param $lang language of localization * @param $action array of action titles */ public function addI18nAction($lang, array $action) { $this->i18n_action[$lang] = $action; } /** * Gets controls to enable browsing calendar months, years, etc. */ private function getControls() { return ''; } /** * Gets number of columns required to draw calendar * @return number of columns of calendar * in czech ------ * funkce zjisti pocet sloupcu kalendare = pocet tydnu (s tim, ze prvniho * muze byt treba v sobotu a 31. v pondeli). * Vyuziva se f-ce date: "W" je cislo tydne v roce. Protoze prelom dvou * mesicu je problematicky, pocita se od druheho tydne mesice do * predposledniho, pak se prictou tyto dva mesice + 2 sloupce navic * (jeden pro zapis dne druhy kvuli matematice operaci odcitani: * 23 - 20 = 3, ale jsou to 4 sloupce ) */ private function numberOfColumns() { $month = $this->model->getMonth(); $year = $this->model->getYear(); $days = cal_days_in_month(CAL_GREGORIAN, $month, $year); $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); return (date("W", mktime(0, 0, 0, $month, $days - 7, $year) ) - date("W", mktime(0, 0, 0, $month,1 +7, $year) ) + 2 + 2 ); } /** * Gets today date in database format * @return today date in database format */ private function today() { return date("Y-m-j"); } /** * Gets content of current callendar cel * @param * @param * @return * in czech ----- * funkce zjisti obsah bunky tabuky kalendare. * Obsah je zavisly na aktualnim radku, sloupci, jaky je prvni den a * celkovem poctu dnu mesice */ private function celContent($row, $col) { if ($col == 0) return new Day($this->i18n_days[$this->lang][$row], ''); $firstDay = date("w", mktime(0, 0, 0, $this->model->getMonth(), 1, $this->model->getYear()) ); $firstDay = ($firstDay == 0) ? 7 : $firstDay; //ternarni operator $totalDays = cal_days_in_month(CAL_GREGORIAN, $this->model->getMonth(), $this->model->getYear()); $numberOfDay = ($col - 1) * 7 + $row - $firstDay + 2 ; if($numberOfDay <= 0 || $numberOfDay > $totalDays) return new Day(' ', ''); else foreach ($this->model->getDays() as $day) if ($day->number == $numberOfDay) return $day; } /** * Exports action data into HTML code to be shown * @param $action action to be exported * @return action exported into HTML */ private function actionToHTML(Action $action) { $ret = ''; $ret .= ''.$this->i18n_action[$this->lang][1].': '; $ret .= $action->title; $ret .= ''.$this->i18n_action[$this->lang][2].': '; $ret .= $action->date; $ret .= ''.$this->i18n_action[$this->lang][3].': '; $ret .= $action->description; $ret .= ''.$this->i18n_action[$this->lang][4].': '; $ret .= $action->author; $ret .= ''; } } /* ================================ Model =================================== */ /** * */ class CalendarData implements IModel { private $month; private $year; /** * */ public function getDays() { $days = array(); for ($i = 1; $i <= cal_days_in_month(CAL_GREGORIAN, $this->month, $this->year); $i++) { $days[] = new Day($i, '2009-01-'.$i, null); } return $days; } public function setDay(Action $a) {} public function getMonth() { return $this->month; } public function setMonth($month) { $this->month = $month; } public function getYear() { return $this->year; } public function setYear($year) { $this->year = $year; } } /* =============================== main app ================================= */ $model = new CalendarData(); $view = new CalViewer($model); $controler = new Controler($model, $view); ?> '; $controler->calLocationChanged(1, 2009); print '--------------------'; $view->addI18nMonths('en_US', array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')); $view->addI18nDays('en_US', array('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')); $view->addI18nAction('en_US', array('Title', 'Date', 'Description', 'Author')); $view->setLang('en_US'); $controler->calLocationChanged(2, 2009); print '--------------------'; $controler->calLocationChanged(3, 2009); print '--------------------'; $view->setLang('cs_CZ'); $controler->calLocationChanged(4, 2009); print ''; ?>