├── .gitignore ├── .project ├── .travis.yml ├── README.md ├── composer.json ├── phpunit.xml ├── src ├── Calendar.php ├── CalendarServiceProvider.php ├── Facades │ └── Calendar.php └── config │ └── calendar.php └── tests └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | .idea -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | calendar 4 | 5 | 6 | 7 | 8 | 9 | 10 | com.aptana.projects.webnature 11 | com.aptana.editor.php.phpNature 12 | 13 | 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - hhvm 9 | 10 | before_script: 11 | - composer self-update 12 | - composer install --prefer-source --no-interaction --dev 13 | 14 | script: phpunit 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel 5 Calendar 2 | 3 | Flexible Calendar for Laravel 5, supports Month, Week and Day Views and multiple events per date. 4 | 5 | To change the view type dynamically, pass in a GET variable called 'cv' (calendar view) with either a 'week' or 'day' value. Day and Week views are split into 30 minute interval rows. 6 | 7 | **For Laravel 4 use [makzumi/laravel-calendar](https://github.com/makzumi/laravel-calendar)** 8 | 9 | ## Installation instructions for Laravel 5: 10 | 11 | Add this to "require" section in composer.json: 12 | 13 | "skecskes/calendar": "0.2.*" 14 | 15 | After that run a `composer update`, and then in /config/app.php add this line to providers array: 16 | 17 | 18 | 'providers' => array( 19 | ..., 20 | Skecskes\Calendar\CalendarServiceProvider::class, 21 | ), 22 | 23 | If you want to change some of the default values of calendar, first publish the configuration with 24 | 25 | php artisan vendor:publish 26 | 27 | This will create new configuration file in your app `config/calendar.php` where you can overwrite default values. 28 | 29 | ## Usage 30 | 31 | To use, create a new Calender instance and generate it, below you'll find several options to customize it as well: 32 | 33 | $events = array( 34 | "2014-04-09 10:30:00" => array( 35 | "Event 1", 36 | "Event 2 with html", 37 | ), 38 | "2014-04-12 14:12:23" => array( 39 | "Event 3", 40 | ), 41 | "2014-05-14 08:00:00" => array( 42 | "Event 4", 43 | ), 44 | ); 45 | 46 | $cal = Skecskes\Calendar\Facades\Calendar::make(); // create instance 47 | 48 | /**** OPTIONAL METHODS ****/ 49 | $cal->setDate(Input::get('cdate')); //Set starting date 50 | $cal->setBasePath('/dashboard'); // Base path for navigation URLs 51 | $cal->showNav(true); // Show or hide navigation 52 | $cal->setView(Input::get('cv')); //'day' or 'week' or null 53 | $cal->setStartEndHours(8,20); // Set the hour range for day and week view 54 | $cal->setTimeClass('ctime'); //Class Name for times column on day and week views 55 | $cal->setEventsWrap(array('

', '

')); // Set the event's content wrapper 56 | $cal->setDayWrap(array('
','
')); //Set the day's number wrapper 57 | $cal->setNextIcon('>>'); //Can also be html: 58 | $cal->setPrevIcon('<<'); // Same as above 59 | $cal->setDayLabels(array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')); //Label names for week days 60 | $cal->setMonthLabels(array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')); //Month names 61 | $cal->setDateWrap(array('
','
')); //Set cell inner content wrapper 62 | $cal->setTableClass('table'); //Set the table's class name 63 | $cal->setHeadClass('table-header'); //Set top header's class name 64 | $cal->setNextClass('btn'); // Set next btn class name 65 | $cal->setPrevClass('btn'); // Set Prev btn class name 66 | $cal->setEvents($events); // Receives the events array 67 | /**** END OPTIONAL METHODS ****/ 68 | 69 | echo $cal->generate() // Return the calendar's html; 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skecskes/calendar", 3 | "type": "library", 4 | "description": "Laravel 5 Flexible Calendar", 5 | "keywords": ["laravel", "calendar", "events"], 6 | "authors": [ 7 | { 8 | "name": "Stefan Kecskes", 9 | "email": "info@skey.uk" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.3.0", 14 | "illuminate/support": "~5" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Skecskes\\Calendar\\": "src/" 19 | } 20 | }, 21 | "minimum-stability": "stable" 22 | } 23 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Calendar.php: -------------------------------------------------------------------------------- 1 | '; 30 | private $prevClass = 'cal_prev'; 31 | private $nextClass = 'cal_next'; 32 | private $basePath = "/"; 33 | 34 | private $timeClass = 'ctime'; 35 | private $dayWrap = array('
', '
'); 36 | private $dateWrap = array('
', '
'); 37 | private $labelsClass = 'cal_labels'; 38 | private $eventWrap = array('

', '

'); 39 | 40 | private $today; 41 | 42 | public function __construct() { 43 | $this->setConfiguration(config('calendar')); 44 | } 45 | 46 | public function make() { 47 | return new static(); 48 | } 49 | 50 | public function setConfiguration(array $config) 51 | { 52 | $this->day = date('d'); 53 | $this->month = date('n'); 54 | $this->year = date('Y'); 55 | $this->today = date('Y-m-d'); 56 | $this->day_lbls = isset($config['day_labels']) ? $config['day_labels'] : $this->day_lbls; 57 | $this->month_lbls = isset($config['month_labels']) ? $config['month_labels'] : $this->month_lbls; 58 | $this->days_month = isset($config['days_month']) ? $config['days_month'] : $this->days_month; 59 | } 60 | 61 | public function showNav($show) { 62 | $this->nav = $show; 63 | return $this; 64 | } 65 | 66 | public function setView($view) { 67 | $this->view = $view; 68 | return $this; 69 | } 70 | 71 | public function setTimeClass($class) { 72 | $this->timeClass = $class; 73 | return $this; 74 | } 75 | 76 | public function setStartEndHours($s, $e) { 77 | $this->start_hour = $s; 78 | $this->end_hour = $e; 79 | return $this; 80 | } 81 | 82 | public function setDate($date = FALSE) { 83 | 84 | $date = explode('-', $date); 85 | $day = @$date[2] ? : date('d'); 86 | $month = @$date[1] ? : date('m'); 87 | 88 | $year = @$date[0] ? : date('Y'); 89 | 90 | $this->day = @$day; 91 | $this->month = @$month; 92 | $this->year = @$year; 93 | return $this; 94 | 95 | } 96 | 97 | public function generate() { 98 | $this->buildHeader(); 99 | switch ($this->view) { 100 | case 'day' : 101 | $this->buildBodyDay(); 102 | break; 103 | case 'week' : 104 | $this->buildBodyWeek(); 105 | break; 106 | default : 107 | $this->buildBody(); 108 | break; 109 | } 110 | return $this->html; 111 | } 112 | 113 | public function setBasePath($path) { 114 | $this->basePath = $path; 115 | return $this; 116 | } 117 | 118 | public function setDayLabels($array) { 119 | if (count($array) != 7) 120 | return; 121 | $this->day_lbls = $array; 122 | return $this; 123 | } 124 | 125 | public function setMonthLabels($array) { 126 | if (count($array) != 12) 127 | return; 128 | $this->month_lbls = $array; 129 | return $this; 130 | } 131 | 132 | public function setEvents($events) { 133 | if (!is_array($events)) 134 | return; 135 | $this->events = $events; 136 | return $this; 137 | } 138 | 139 | public function setEventsWrap($wrap) { 140 | $this->eventWrap = $wrap; 141 | return $this; 142 | } 143 | 144 | public function setDayWrap($wrap) { 145 | $this->dayWrap = $wrap; 146 | return $this; 147 | } 148 | 149 | public function setNextIcon($html) { 150 | $this->nextIco = $html; 151 | return $this; 152 | } 153 | 154 | public function setPrevIcon($html) { 155 | $this->prevIco = $html; 156 | return $this; 157 | } 158 | 159 | public function setDateWrap($wrap) { 160 | $this->dateWrap = $wrap; 161 | return $this; 162 | } 163 | 164 | public function setTableClass($class) { 165 | $this->tableClass = $class; 166 | return $this; 167 | } 168 | 169 | public function setHeadClass($class) { 170 | $this->headClass = $class; 171 | return $this; 172 | } 173 | 174 | public function setNextClass($class) { 175 | $this->nextClass = $class; 176 | return $this; 177 | } 178 | 179 | public function setPrevClass($class) { 180 | $this->prevClass = $class; 181 | return $this; 182 | } 183 | 184 | public function setLabelsClass($class) { 185 | $this->labelsClass = $class; 186 | return $this; 187 | } 188 | 189 | private function buildHeader() { 190 | $month_name = $this->month_lbls[$this->month - 1] . ' ' . $this->year; 191 | $vclass = strtolower($this->view); 192 | $h = ""; 193 | $h .= ""; 194 | $h .= ""; 195 | $cs = 5; 196 | if ($this->view == 'week' || $this->view == 'day') 197 | $h .= ""; 198 | if ($this->view == 'day') 199 | $cs = 1; 200 | 201 | if ($this->nav) { 202 | $h .= ""; 205 | $h .= ""; 208 | $h .= ""; 211 | } else { 212 | $h .= ""; 215 | } 216 | $h .= ""; 217 | $h .= ""; 218 | 219 | $h .= ""; 220 | if ($this->view != 'day' && $this->view != 'week') { 221 | $h .= ""; 222 | 223 | for ($i = 0; $i <= 6; $i++) { 224 | $h .= ""; 227 | } 228 | 229 | $h .= ""; 230 | } 231 | if ($this->view == 'day' || $this->view == 'week') 232 | $h .= self::getWeekDays(); 233 | 234 | $this->html .= $h; 235 | } 236 | 237 | private function getWeekDays() { 238 | $time = date('Y-m-d', strtotime($this->year . '-' . $this->month . '-' . $this->day)); 239 | if ($this->view == 'week') { 240 | $sunday = strtotime('last sunday', strtotime($time . ' +1day')); 241 | $day = date('j', $sunday); 242 | $startingDay = date('N', $sunday); 243 | $cnt = 6; 244 | } 245 | if ($this->view == 'day') { 246 | $day = $this->day; 247 | $cnt = 0; 248 | } 249 | 250 | $this->week_days = array(); 251 | $mlen = $this->days_month[intval($this->month) - 1]; 252 | if ($this->month == 2 && ((($this->year % 4) == 0) && ((($this->year % 100) != 0) || (($this->year % 400) == 0)))) { 253 | $mlen = $mlen + 1; 254 | } 255 | $h = ""; 256 | $h .= ""; 257 | for ($j = 0; $j <= $cnt; $j++) { 258 | $cs = $cnt == 0 ? 3 : 1; 259 | $h .= ""; 274 | } 275 | 276 | $h .= ""; 277 | return $h; 278 | } 279 | 280 | private function buildBody() { 281 | $day = 1; 282 | $now_date = $this->year . '-' . $this->month . '-01'; 283 | $startingDay = date('N', strtotime('first day of this month', strtotime($now_date))); 284 | //Add the following line if you want to start the week with monday instead of sunday. Or change the number to suit your needs. 285 | //$startingDay = $startingDay - 1; 286 | $monthLength = $this->days_month[$this->month - 1]; 287 | if ($this->month == 2 && ((($this->year % 4) == 0) && ((($this->year % 100) != 0) || (($this->year % 400) == 0)))) { 288 | $monthLength = $monthLength + 1; 289 | } 290 | $h = ""; 291 | for ($i = $startingDay == 7 ? 1 : 0; $i < 9; $i++) { 292 | for ($j = 0; $j <= 6; $j++) { 293 | $curr_date = $this->getDayDate($day); 294 | $is_today = ""; 295 | if ($curr_date == $this->today) 296 | $is_today = "class='today'"; 297 | $h .= ""; 310 | } 311 | // stop making rows if we've run out of days 312 | if ($day > $monthLength) { 313 | break; 314 | } else { 315 | $h .= ""; 316 | $h .= ""; 317 | } 318 | } 319 | $h .= ""; 320 | $h .= ""; 321 | $h .= "
 "; 203 | $h .= "" . $this->prevIco . ""; 204 | $h .= ""; 206 | $h .= $month_name; 207 | $h .= ""; 209 | $h .= "" . $this->nextIco . ""; 210 | $h .= ""; 213 | $h .= $month_name; 214 | $h .= "
"; 225 | $h .= $this->day_lbls[$i]; 226 | $h .= "
 "; 260 | if ($this->view == 'day') 261 | $getDayNumber = date('w', strtotime($time)); 262 | else 263 | $getDayNumber = $j; 264 | if ($day <= $mlen) { 265 | 266 | } else { 267 | $day = 1; 268 | } 269 | $h .= $this->day_lbls[$getDayNumber] . ' '; 270 | $h .= intval($day); 271 | $this->week_days[] = $day; 272 | $day++; 273 | $h .= "
"; 298 | $h .= $this->dateWrap[0]; 299 | if ($day <= $monthLength && ($i > 0 || $j >= $startingDay)) { 300 | $h .= $this->dayWrap[0]; 301 | $h .= $day; 302 | $h .= $this->dayWrap[1]; 303 | $h .= $this->buildEvents($curr_date); 304 | $day++; 305 | } else { 306 | $h .= " "; 307 | } 308 | $h .= $this->dateWrap[1]; 309 | $h .= "
"; 322 | $this->html .= $h; 323 | } 324 | 325 | private function buildBodyDay() { 326 | 327 | $events = $this->events; 328 | $h = ""; 329 | for ($i = $this->start_hour; $i < $this->end_hour; $i++) { 330 | for ($t = 0; $t < 2; $t++) { 331 | $h .= ""; 332 | $min = $t == 0 ? ":00" : ":30"; 333 | $h .= "" . date('g:ia', strtotime($i . $min)) . ""; 334 | for ($k = 0; $k < 1; $k++) { 335 | $wd = $this->week_days[$k]; 336 | $time_r = $this->year . '-' . $this->month . '-' . $wd . ' ' . $i . ':00:00'; 337 | $min = $t == 0 ? '' : '+30 minute'; 338 | $time_1 = strtotime($time_r . $min); 339 | $time_2 = strtotime(date('Y-m-d H:i:s', $time_1) . '+30 minute'); 340 | $dt = date('Y-m-d H:i:s', $time_1); 341 | $h .= ""; 342 | $h .= $this->dateWrap[0]; 343 | 344 | $hasEvent = FALSE; 345 | foreach ($events as $key=>$event) { 346 | //EVENT TIME AND DATE 347 | $time_e = strtotime($key); 348 | if ($time_e >= $time_1 && $time_e < $time_2) { 349 | $hasEvent = TRUE; 350 | $h .= $this->buildEvents(FALSE, $event); 351 | } 352 | } 353 | $h .= !$hasEvent ? ' ' : ''; 354 | $h .= $this->dateWrap[1]; 355 | $h .= ""; 356 | } 357 | $h .= ""; 358 | } 359 | } 360 | $h .= ""; 361 | $h .= ""; 362 | 363 | $this->html .= $h; 364 | } 365 | 366 | private function buildBodyWeek() { 367 | 368 | $events = $this->events; 369 | $h = ""; 370 | for ($i = $this->start_hour; $i < $this->end_hour; $i++) { 371 | for ($t = 0; $t < 2; $t++) { 372 | $h .= ""; 373 | $min = $t == 0 ? ":00" : ":30"; 374 | $h .= "" . date('g:ia', strtotime($i . $min)) . ""; 375 | 376 | for ($k = 0; $k < count($this->week_days); $k++) { 377 | 378 | $wd = $this->week_days[$k]; 379 | $time_r = $this->year . '-' . $this->month . '-' . $wd . ' ' . $i . ':00:00'; 380 | //we also need next month string 381 | $time_r_next_month = $this->year . '-' . (string)($this->month + 1) . '-' . $wd . ' ' . $i . ':00:00'; 382 | $min = $t == 0 ? '' : '+30 minute'; 383 | $time_1 = strtotime($time_r . $min); 384 | $time_2 = strtotime(date('Y-m-d H:i:s', $time_1) . '+30 minute'); 385 | //events need additional checking, if they are in same week but next month they will not show up 386 | //so we need somt additional time rules to check 387 | $time_3 = strtotime($time_r_next_month . $min); 388 | $time_4 = strtotime(date('Y-m-d H:i:s', $time_3) . '+60 minute'); 389 | $dt = date('Y-m-d H:i:s', $time_1); 390 | $h .= ""; 391 | $h .= $this->dateWrap[0]; 392 | 393 | $hasEvent = FALSE; 394 | foreach ($events as $key=>$event) { 395 | //EVENT TIME AND DATE 396 | $time_e = strtotime($key); 397 | //and the additional check should be done in the below conditional 398 | if (($time_e >= $time_1 && $time_e < $time_2) || ($time_e >= $time_3 && $time_e < $time_4)) { 399 | $hasEvent = TRUE; 400 | $h .= $this->buildEvents(FALSE, $event); 401 | } 402 | } 403 | $h .= !$hasEvent ? ' ' : ''; 404 | $h .= $this->dateWrap[1]; 405 | $h .= ""; 406 | } 407 | $h .= ""; 408 | } 409 | } 410 | $h .= ""; 411 | $h .= ""; 412 | 413 | $this->html .= $h; 414 | } 415 | 416 | private function buildEvents($date, $event = FALSE) { 417 | if (!$this->events) 418 | return ""; 419 | $events = $this->events; 420 | $h = ""; 421 | //IF DAY CALC MINS 422 | $date = date('Y-m-d', strtotime($date)); 423 | if ($event) { 424 | return $this->processEvent($event); 425 | } 426 | foreach ($events as $key=>$event) { 427 | $edate = date('Y-m-d', strtotime($key)); 428 | if (is_array($event)) { 429 | if ($date == $edate) { 430 | $h .= $this->processEvent($event); 431 | } 432 | } else { 433 | if ($date == $key) { 434 | $h .= $this->eventWrap[0]; 435 | $h .= $event; 436 | $h .= $this->eventWrap[1]; 437 | } 438 | } 439 | } 440 | return $h; 441 | } 442 | 443 | private function processEvent($event) { 444 | $h = ""; 445 | foreach ($event as $e) { 446 | $h .= $this->eventWrap[0]; 447 | $h .= $e; 448 | $h .= $this->eventWrap[1]; 449 | } 450 | return $h; 451 | } 452 | 453 | private function prevLink() { 454 | $y = $this->year; 455 | $d = intval($this->day); 456 | $d = $d < 10 ? '0' . $d : $d; 457 | $m = intval($this->month); 458 | $m = $m < 10 ? '0' . $m : $m; 459 | 460 | $time = $y . '-' . $m . '-' . $d; 461 | 462 | if ($this->view == "week") { 463 | $time = strtotime('last sunday', strtotime($time . ' +1 day')); 464 | $time = date('Y-m-d', $time); 465 | $time = date('Y-m-d', strtotime($time . ' -1 week')); 466 | } else if ($this->view == "day") { 467 | $time = date('Y-m-d', strtotime($time . '-1day')); 468 | } else { 469 | $time = date('Y-m', strtotime($y . '-' . $m . '-01 -1month')); 470 | } 471 | $url = $this->basePath . '?cdate=' . $time; 472 | return $url . $this->getOldGET(); 473 | } 474 | 475 | private function nextLink() { 476 | $y = $this->year; 477 | $d = intval($this->day); 478 | $d = $d < 10 ? '0' . $d : $d; 479 | $m = intval($this->month); 480 | $m = $m < 10 ? '0' . $m : $m; 481 | 482 | $time = $y . '-' . $m . '-' . $d; 483 | 484 | if ($this->view == "week") { 485 | $time = strtotime('next sunday', strtotime($time . ' -1 day')); 486 | $time = date('Y-m-d', $time); 487 | $time = date('Y-m-d', strtotime($time . '+1week')); 488 | } else if ($this->view == "day") { 489 | $time = date('Y-m-d', strtotime($time . '+1day')); 490 | } else { 491 | $time = date('Y-m', strtotime($y . '-' . $m . '-01 +1month')); 492 | } 493 | 494 | $url = $this->basePath . '?cdate=' . $time; 495 | return $url . $this->getOldGET(); 496 | } 497 | 498 | private function getDayDate($day) { 499 | $day = intval($day); 500 | $y = $this->year; 501 | $m = intval($this->month); 502 | $m = $m < 10 ? '0' . $m : $m; 503 | $d = intval($day); 504 | $d = $d < 10 ? '0' . $d : $d; 505 | $date = $y . '-' . $m . '-' . $d; 506 | return $date; 507 | } 508 | 509 | private function getOldGET() { 510 | $get = $_GET; 511 | $vars = ''; 512 | foreach ($get as $key=>$value) 513 | if ($key != 'cdate') 514 | $vars .= '&' . $key . '=' . $value; 515 | return $vars; 516 | } 517 | 518 | } 519 | -------------------------------------------------------------------------------- /src/CalendarServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton('Skecskes\Calendar\Calendar', function($app) { 22 | return new Calendar(); 23 | }); 24 | } 25 | 26 | /** 27 | * Bootstrap the configuration 28 | * 29 | * @return void 30 | */ 31 | public function boot() 32 | { 33 | $config = __DIR__ . '/config/calendar.php'; 34 | //$this->mergeConfigFrom($config, 'calendar'); 35 | $this->publishes([$config => config_path('calendar.php')]); 36 | } 37 | 38 | /** 39 | * Get the services provided by the provider. 40 | * 41 | * @return array 42 | */ 43 | public function provides() { 44 | return ['Skecskes\Calendar\Calendar']; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/Facades/Calendar.php: -------------------------------------------------------------------------------- 1 | array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), 13 | 'month_labels' => array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'), 14 | 'days_month' => array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 15 | 16 | ); -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skecskes/laravel-calendar/65c4ade0af263fa1f2d15ae127552e332cb3b061/tests/.gitkeep --------------------------------------------------------------------------------