* @link https://TheTempusProject.com * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Controllers; use TheTempusProject\Bedrock\Functions\Check; use TheTempusProject\Bedrock\Functions\Input; use TheTempusProject\Bedrock\Functions\Session; use TheTempusProject\Bedrock\Functions\Date; use TheTempusProject\Classes\Controller; use TheTempusProject\Houdini\Classes\Forms as HoudiniForms; use TheTempusProject\Classes\Forms; use TheTempusProject\Houdini\Classes\Issues; use TheTempusProject\Houdini\Classes\Views; use TheTempusProject\Houdini\Classes\Template; use TheTempusProject\Houdini\Classes\Components; use TheTempusProject\Hermes\Functions\Redirect; use TheTempusProject\TheTempusProject as App; use TheTempusProject\Models\Events; use TheTempusProject\Models\Calendars; use TheTempusProject\Houdini\Classes\Navigation; class Calendar extends Controller { protected static $events; protected static $calendars; protected static $defaultView; protected static $defaultCalendar; protected static $selectedDate; public function __construct() { if ( !App::$isLoggedIn ) { Session::flash( 'notice', 'You must be logged in to create or manage calendars.' ); return Redirect::home(); } parent::__construct(); self::$title = 'Calendar - {SITENAME}'; self::$pageDescription = 'The {SITENAME} calendar is where you can find various features for creating and managing events and schedules.'; self::$events = new Events; self::$calendars = new Calendars; $prefs = App::$activePrefs; if ( ! empty( $prefs['calendarPreference'] ) ) { $view = $prefs['calendarPreference']; } else { Session::flash( 'info', 'You can select a default view for this page in your user settings in the top right.' ); $view = 'byMonth'; } self::$defaultView = $view; self::$selectedDate = intval( strtotime( Date::determineDateInput() ) ); Template::setTemplate( 'calendar' ); // Date Dropdown $dateDropdownView = Views::simpleView('calendar.nav.dateDropdown', Date::getDateBreakdown( self::$selectedDate ) ); Components::set( 'dateDropdown', $dateDropdownView ); // Calendar Top Tabs $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, Input::get( 'url' ), false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); // must be done after dropdown gets added Components::set( 'CalendarNav', Template::parse( $calendarTabs ) ); } public function index() { if ( method_exists( $this, self::$defaultView ) ) { Redirect::to( 'calendar/'.self::$defaultView.'/' ); } else { Redirect::to( 'calendar/byMonth/' ); } } /** * Events */ public function event( $id = null ) { $event = $this->findEventOrFail( $id ); Views::view( 'calendar.events.view', $event ); } public function createEvent() { // get the url calendar input $newCalendar = Input::get('calendar_id') ? Input::get('calendar_id') : '';// for loading the form $calendarSelect = HoudiniForms::getFormFieldHtml( 'calendar_id', 'Calendar', 'select', $newCalendar, self::$calendars->simpleByUser() ); Components::set( 'calendarSelect', $calendarSelect ); $repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', 'none', self::$events->repeatOptions ); Components::set( 'repeatSelect', $repeatSelect ); $dateSelect = Views::simpleView( 'calendar.dateSelect', $this->getEventBreakdown( self::$selectedDate ) ); Components::set( 'dateSelect', $dateSelect ); if ( ! Input::exists() ) { return Views::view( 'calendar.events.create' ); } /** Attempt to save the form data somewhat */ // get the form calendar input $calendarID = Input::post('calendar_id') ? Input::post('calendar_id') : ''; // for submitting the form $calendarSelect = HoudiniForms::getFormFieldHtml( 'calendar_id', 'Calendar', 'select', $calendarID, self::$calendars->simpleByUser() ); Components::set( 'calendarSelect', $calendarSelect ); $repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', Input::post('repeats'), self::$events->repeatOptions ); Components::set( 'repeatSelect', $repeatSelect ); if ( ! Forms::check( 'createEvent' ) ) { Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] ); return Views::view( 'calendar.events.create' ); } $event_id = self::$events->create( $calendarID, Input::post('title'), Date::applyUtcToDate( Date::determineDateInput() ), Input::post('description'), Input::post('location'), Input::post('repeats'), Input::post('color'), 0, ); if ( ! $event_id ) { Issues::add( 'error', [ 'There was an error creating your event.' => Check::userErrors() ] ); return Views::view( 'calendar.events.create' ); } if ( Input::post('repeats') != 'none' ) { $childrens = self::$events->generateChildEvents( $event_id, true, true ); } Session::flash( 'success', 'Your Event has been created.' ); Redirect::to( 'calendar/'.self::$defaultView.'/'. $calendarID ); } public function editEvent( $id = null ) { $calendar = Input::exists('calendar_id') ? Input::post('calendar_id') : ''; $event = self::$events->findById( $id ); $readableDate = date('Y-m-d H:i:s', $event->event_time); if ( $event == false ) { Session::flash( 'error', 'Event not found.' ); return Redirect::to( 'calendar/'.self::$defaultView.'/' ); } if ( $event->createdBy != App::$activeUser->ID ) { Session::flash( 'error', 'You do not have permission to modify this event.' ); return Redirect::to( 'calendar/'.self::$defaultView.'/' ); } $repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', $event->repeats, self::$events->repeatOptions ); Components::set( 'repeatSelect', $repeatSelect ); // there should be a way to do this natively $event_at = Date::getDateBreakdown( $event->event_time, true ); // $readableDate = date('Y-m-d H:i:s', $readableDate); $dateSelect = Views::simpleView( 'calendar.dateSelect', $event_at ); Components::set( 'dateSelect', $dateSelect ); Components::set( 'color', $event->color ); if ( ! Input::exists( 'submit' ) ) { return Views::view( 'calendar.events.edit', $event ); } if ( ! Forms::check( 'editEvent' ) ) { Issues::add( 'error', [ 'There was an error updating your event.' => Check::userErrors() ] ); return Views::view( 'calendar.events.edit', $event ); } $result = self::$events->update( $id, Input::post('title'), Date::applyUtcToDate( Date::determineDateInput() ), Input::post('description'), Input::post('location'), Input::post('repeats'), Input::post('color'), ); if ( Input::post('repeats') != 'none' && $event->parent_id == 0 ) { $childrens = self::$events->generateChildEvents( $event->ID, true, true ); } if ( ! $result ) { Issues::add( 'error', [ 'There was an error updating your event.' => Check::userErrors() ] ); return Views::view( 'calendar.events.edit', $event->ID ); } Session::flash( 'success', 'Your Event has been updated.' ); Redirect::to( 'calendar/'.self::$defaultView.'/'. $event->calendar_id ); } public function deleteEvent( $id = null ) { $event = self::$events->findById( $id ); if ( $event == false ) { Issues::add( 'error', 'Event not found.' ); return $this->index(); } if ( $event->createdBy != App::$activeUser->ID ) { Issues::add( 'error', 'You do not have permission to modify this event.' ); return $this->index(); } $result = self::$events->delete( $id ); if ( !$result ) { Session::flash( 'error', 'There was an error deleting the event(s)' ); } else { Session::flash( 'success', 'Event deleted' ); } return $this->index(); } /** * Calendars */ public function calendar( $id = null ) { $calendar = $this->findCalendarOrFail( $id ); Views::view( 'calendar.calendar.view', $calendar ); } public function createCalendar() { $timezoneSelect = HoudiniForms::getTimezoneHtml( Date::getTimezone() ); Components::set( 'timezoneSelect', $timezoneSelect ); if ( ! Input::exists() ) { return Views::view( 'calendar.calendar.create' ); } if ( ! Forms::check( 'createCalendar' ) ) { Issues::add( 'error', [ 'There was an error creating your calendar111.' => Check::userErrors() ] ); return Views::view( 'calendar.calendar.create' ); } $calendar = self::$calendars->create( Input::post('title'), Input::post('description'), Input::post('timezone'), Input::post('color') ); if ( ! $calendar ) { return Views::view( 'calendar.calendar.create' ); } Session::flash( 'success', 'Your Calendar has been created.' ); Redirect::to( 'calendar/'.self::$defaultView.'/'); } public function editCalendar( $id = null ) { $calendar = $this->findCalendarOrFail( $id ); $timezoneSelect = HoudiniForms::getTimezoneHtml( Date::getTimezone() ); Components::set( 'timezoneSelect', $timezoneSelect ); Components::set( 'color', $calendar->color ); if ( ! Input::exists( 'submit' ) ) { return Views::view( 'calendar.calendar.edit', $calendar ); } if ( !Forms::check( 'editCalendar' ) ) { Issues::add( 'error', [ 'There was an error editing your calendar.' => Check::userErrors() ] ); return Views::view( 'calendar.calendar.edit', $calendar ); } $result = self::$calendars->update( $id, Input::post('title'), Input::post('description'), Input::post('timezone'), Input::post('color') ); if ( !$result ) { Issues::add( 'error', [ 'There was an error updating your calendar.' => Check::userErrors() ] ); return Views::view( 'calendar.calendar.edit', $calendar ); } Session::flash( 'success', 'Your Calendar has been updated.' ); Redirect::to( 'calendar/'.self::$defaultView.'/'. $calendar->ID ); } public function deleteCalendar( $id = null ) { $calendar = self::$calendars->findById( $id ); if ( $calendar == false ) { Issues::add( 'error', 'Calendar not found.' ); return $this->index(); } if ( $calendar->createdBy != App::$activeUser->ID ) { Issues::add( 'error', 'You do not have permission to modify this calendar.' ); return $this->index(); } $results = self::$events->deleteByCalendar( $id ); $result = self::$calendars->delete( $id ); if ( !$result ) { Session::flash( 'error', 'There was an error deleting the calendar(s)' ); } else { Session::flash( 'success', 'Calendar deleted' ); } Redirect::to( 'calendar/'.self::$defaultView.'/' ); } /** * Views */ public function byDay( $id = 0 ) { // Set base components Components::set( 'currentView', __FUNCTION__ ); Components::set( 'calendarID', $id ); // Set components for next / back arrows $nextDayMonth = date( 'M', strtotime( 'tomorrow', self::$selectedDate ) ); $nextDay = date( 'd', strtotime( 'tomorrow', self::$selectedDate ) ); $lastDayMonth = date( 'M', strtotime( 'yesterday', self::$selectedDate ) ); $lastDay = date( 'd', strtotime( 'yesterday', self::$selectedDate ) ); Components::set( 'nextDayMonth', $nextDayMonth ); Components::set( 'nextDay', $nextDay ); Components::set( 'lastDayMonth', $lastDayMonth ); Components::set( 'lastDay', $lastDay ); // Get the data $dayArray = self::$events->dayArray( $id, self::$selectedDate ); // build the results $selectedHour = Date::getCurrentHour(); $day = date( 'd', self::$selectedDate ); $month = date( 'M', self::$selectedDate ); $year = date( 'Y', self::$selectedDate ); $fullDay = []; foreach ( $dayArray as $hour => $events ) { Components::set( 'hour', $hour ); $hourCell = new \stdClass(); $hourCell->hour = $hour; if ( $hour == $selectedHour ) { $hourCell->hourSelected = ' hour-active'; } else { $hourCell->hourSelected = ''; } $hourCell->day = $day; $hourCell->month = $month; $hourCell->year = $year; $hourCell->EventCells = Views::simpleView( 'calendar.nav.row', $events ); $fullDay[] = $hourCell; } // Calendar Top Tabs Components::unset( 'calendarDropdown'); $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byDay/', false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); Components::set( 'CalendarNav', Template::parse( $tabsView ) ); Components::set( 'activeDate', date( 'F d, Y', self::$selectedDate ) ); Views::view( 'calendar.byDay', $fullDay ); } public function byWeek( $id = 0 ) { // Set base components Components::set( 'currentView', __FUNCTION__ ); Components::set( 'calendarID', $id ); // Set components for next / back arrows $lastWeekMonth = date( 'M', strtotime( '-7 days', self::$selectedDate) ); $lastWeekDay = date( 'd', strtotime( '-7 days', self::$selectedDate) ); $lastWeekYear = date( 'Y', strtotime( '-7 days', self::$selectedDate) ); $nextWeekMonth = date( 'M', strtotime( '+7 days', self::$selectedDate) ); $nextWeekDay = date( 'd', strtotime( '+7 days', self::$selectedDate) ); $nextWeekYear = date( 'Y', strtotime( '+7 days', self::$selectedDate) ); Components::set( 'lastWeekMonth', $lastWeekMonth ); Components::set( 'lastWeek', $lastWeekDay ); Components::set( 'lastYear', $lastWeekYear ); Components::set( 'nextWeekMonth', $nextWeekMonth ); Components::set( 'nextWeek', $nextWeekDay ); Components::set( 'nextYear', $nextWeekYear ); // Get the data $weekArray = self::$events->weekArray( $id, self::$selectedDate ); // build the results $presentMonth = date( 'F', self::$selectedDate ); $presentDay = date( 'd', self::$selectedDate ); foreach ( $weekArray as $week => $days ) { $weekFormat = []; foreach ( $days as $day => $events ) { if ( empty( $first ) ) { $first = true; if ( intval( $presentDay ) >= $day ) { $month = date( 'F', self::$selectedDate ); } else { $month = date( 'F', strtotime( '-7 days', self::$selectedDate ) ); } } if ( $day == '01' ) { $month = date( 'F', strtotime( '+7 days', self::$selectedDate ) ); } Components::set( 'currentMonth', $month ); Components::set( 'currentDay', $day ); $dayCell = new \stdClass(); if ( $presentDay == $day && $presentMonth == $month ) { $dayCell->highlightedDate = ' today'; } else { $dayCell->highlightedDate = ''; } $dayCell->day = $day; $dayCell->dayEventList = Views::simpleView( 'calendar.nav.cell', $events ); $weekFormat[] = $dayCell; } $weekView = Views::simpleView( 'calendar.nav.week', $weekFormat ); Components::set( $week . 'Element', $weekView ); } // Calendar Top Tabs Components::unset( 'calendarDropdown'); $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byWeek/', false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); Components::set( 'CalendarNav', Template::parse( $tabsView ) ); Components::set( 'dateWeek', 'Week of ' . date( 'F d, Y', self::$selectedDate ) ); Views::view( 'calendar.byWeek' ); } public function byMonth( $id = 0 ) { // Set base components Components::set( 'currentView', __FUNCTION__ ); Components::set( 'calendarID', $id ); // Set components for next / back arrows $month = date( 'F', strtotime( 'first day of last month', self::$selectedDate ) ); $lastMonthYear = date( 'Y', strtotime( 'first day of last month', self::$selectedDate ) ); $nextMonth = date( 'F', strtotime( 'first day of next month', self::$selectedDate ) ); $nextMonthYear = date( 'Y', strtotime( 'first day of next month', self::$selectedDate ) ); Components::set( 'lastMonth', $month ); Components::set( 'lastMonthYear', $lastMonthYear ); Components::set( 'nextMonth', $nextMonth ); Components::set( 'nextMonthYear', $nextMonthYear ); // Get the data $monthArray = self::$events->monthArray( $id, self::$selectedDate ); // build the results $lastMonth = strtotime( 'last month', self::$selectedDate ); $presentMonth = date( 'F', self::$selectedDate ); $presentDay = date( 'd', self::$selectedDate ); foreach ( $monthArray as $week => $days ) { $weekFormat = []; foreach ( $days as $day => $events ) { if ( $day == '01' ) { $month = date( 'F', strtotime( '+1 month', $lastMonth ) ); $lastMonth = strtotime( '+1 month', $lastMonth) ; } Components::set( 'currentMonth', $month ); Components::set( 'currentDay', $day ); $dayCell = new \stdClass(); if ( $presentDay == $day && $presentMonth == $month ) { $dayCell->highlightedDate = ' today'; } else { $dayCell->highlightedDate = ''; } $dayCell->day = $day; // prevent duplicated entries for previous/next month if ( $lastMonth < strtotime( 'this month',self::$selectedDate ) || $lastMonth == strtotime( 'next month',self::$selectedDate )) { $events = []; } $dayCell->dayEventList = Views::simpleView( 'calendar.nav.cell', $events ); $weekFormat[] = $dayCell; } $weekView = Views::simpleView( 'calendar.nav.week', $weekFormat ); Components::set( $week . 'Element', $weekView ); } // Calendar Top Tabs Components::unset( 'calendarDropdown'); $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byMonth/', false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); Components::set( 'CalendarNav', Template::parse( $tabsView ) ); Components::set( 'dateMonth', date( 'F Y', self::$selectedDate ) ); Views::view( 'calendar.byMonth' ); } public function byYear( $id = 0 ) { // Set base components Components::set( 'calendarID', $id ); Components::set( 'currentView', __FUNCTION__ ); // Set components for next / back arrows $nextYear = date( 'Y', strtotime( 'next year', self::$selectedDate ) ); $lastYear = date( 'Y', strtotime( 'last year', self::$selectedDate ) ); Components::set( 'lastYear', $lastYear ); Components::set( 'nextYear', $nextYear ); // Get the data $eventList = self::$events->yearArray( $id, self::$selectedDate ); // Calendar Top Tabs Components::unset( 'calendarDropdown'); $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byYear/', false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); Components::set( 'CalendarNav', Template::parse( $tabsView ) ); Components::set( 'dateYear', date( 'Y', self::$selectedDate ) ); Views::view( 'calendar.byYear', $eventList ); } public function events( $id = 0 ) { Components::set( 'currentView', __FUNCTION__ ); Components::set( 'calendarID', $id ); if ( ! empty( $id ) ) { $calendar = self::$calendars->findById( $id ); if ( $calendar == false ) { Issues::add( 'error', 'Calendar not found.' ); return $this->index(); } if ( $calendar->createdBy != App::$activeUser->ID ) { Issues::add( 'error', 'You do not have permission to view this calendar.' ); return $this->index(); } Components::set( 'calendarName', $calendar->title ); $eventList = self::$events->findByCalendar( $id ); } else { $eventList = self::$events->userEvents( 5 ); } // Calendar Top Tabs Components::unset( 'calendarDropdown'); $calendarTabs = Views::simpleView('calendar.nav.topTabs'); $tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/events/', false, true ); // must be done after top-nav gets selected $calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() ); $calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param Components::set( 'calendarDropdown', $calendarDropdownView); Components::set( 'CalendarNav', Template::parse( $tabsView ) ); Views::view( 'calendar.events.list', $eventList ); } /** * Support Functions */ private function findCalendarOrFail( $id = null ) { $calendar = self::$calendars->findById( $id ); if ( $calendar == false ) { Session::flash( 'error', 'Calendar not found.' ); Redirect::to( 'calendar/'.self::$defaultView.'/' ); } if ( $calendar->createdBy != App::$activeUser->ID ) { Session::flash( 'error', 'Permissions Error.' ); Redirect::to( 'calendar/'.self::$defaultView.'/' ); } return $calendar; } private function findEventOrFail( $id = null ) { $event = self::$events->findById( $id ); if ( $event == false ) { Session::flash( 'error', 'Event not found.' ); Redirect::to( 'calendar/'.self::$defaultView.'/' ); } if ( $event->createdBy != App::$activeUser->ID ) { Session::flash( 'error', 'Permissions Error.' ); Redirect::to( 'calendar/'.self::$defaultView.'/' ); } return $event; } private function getEventBreakdown( $start_timestamp = 0, $end_timestamp = 0, $with_timezone = false ) { $out = new \stdClass(); if ( empty( $end_timestamp ) ) { $out->allDay = 'true'; // $out->date = ; // $out->time = ; $out->endDate = $out->date; $out->endTime = $out->time; } else { $out->allDay = 'false'; // $out->date = ; // $out->time = ; $out->endDate = $out->date; $out->endTime = $out->time; } $timestamp = intval( $timestamp ); $init = date('Y-m-d H:i:s', $timestamp); if ( true === $with_timezone ) { $readableDate = self::applyTimezoneToTimestamp( $timestamp ); } else { $readableDate = date('Y-m-d H:i:s', $timestamp); } $date = date( 'Y-m-d', strtotime( $readableDate ) ); $time = date( 'H:i', strtotime( $readableDate ) ); return [ 'time' => $time, 'date' => $date, ]; } }