From 032957e0e2cf194f1736d8d9615bddd9bff77041 Mon Sep 17 00:00:00 2001 From: lsces Date: Wed, 27 Aug 2025 17:29:38 +0100 Subject: Code updated to PHP8.4 and namespace --- Calendar.php | 486 -------------------------------------- includes/bit_setup_inc.php | 29 ++- includes/classes/Calendar.php | 483 +++++++++++++++++++++++++++++++++++++ liberty_plugins/data.calendar.php | 42 ++-- 4 files changed, 521 insertions(+), 519 deletions(-) delete mode 100644 Calendar.php create mode 100644 includes/classes/Calendar.php diff --git a/Calendar.php b/Calendar.php deleted file mode 100644 index 146b42b..0000000 --- a/Calendar.php +++ /dev/null @@ -1,486 +0,0 @@ -mUserPrefs['calendar_week_offset'] ) ? $gBitUser->mUserPrefs['calendar_week_offset'] : $gBitSystem->getConfig( 'calendar_week_offset', 0 ) ); - -/** - * @package calendar - */ -class Calendar extends LibertyContent { - - public $display_offset; - - function Calendar() { - parent::__construct(); - global $gBitUser; - $this->mDate = new BitDate(0); - $this->display_offset = $this->mDate->get_display_offset(); - } - - /** - * get a full list of content for a given time period - * return array of items - * - * The output array will be a set of UTC tagged pages covering the period - * defined in the $pListHash. Items identified from the list will be tagged to - * the day identified in the selected timestamp from which the list was built. - * If the user has selected a local time display, then the day will be the actual - * UTC day that the item is in, rather than the UTC day of the item. In this way - * the display view provides a list of locally correct entries for each day. - **/ - function getList( $pListHash ) { - $ret = array(); - - $pListHash['include_data'] = TRUE; - if( !empty( $pListHash['focus_date'] ) ) { - $calDates = $this->doRangeCalculations( $pListHash ); - $pListHash['time_limit_start'] = $calDates['view_start'] - $this->display_offset; - $pListHash['time_limit_stop'] = $calDates['view_end'] - $this->display_offset; - } -// if ( empty( $pListHash['sort_mode'] ) ) { -// $pListHash['sort_mode'] = !empty( $_REQUEST['sort_mode'] ) ? $_REQUEST['sort_mode'] : 'event_time_asc'; -// } - $pListHash['sort_mode'] = 'event_time_asc'; - $pListHash['time_limit_column'] = preg_replace( "/(_asc$|_desc$)/i", "", $pListHash['sort_mode'] ); - - if ( empty( $pListHash['user_id'] ) ) { - $pListHash['user_id'] = !empty( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : NULL; - } - if ( !empty( $_REQUEST['order_table'] ) ) { - $pListHash['order_table'] = $_REQUEST['order_table']; - } - - // Don't think this is required. - $pListHash['offset'] = 0; - // There should at least be a preference for this. - $pListHash['max_records'] = 500; - - $res = $this->getContentList( $pListHash ); - - foreach( $res as $item ) { - // shift all time data by user timezone offset - // and then display as a simple UTC time - $item['timestamp'] = $item[$pListHash['time_limit_column']] + $this->display_offset; - $item['created'] = $item['created'] + $this->display_offset; - $item['last_modified'] = $item['last_modified'] + $this->display_offset; - $item['event_time'] = $item['event_time'] + $this->display_offset; - $item['parsed'] = self::parseDataHash( $item ); - $dstart = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( "m", $item['timestamp'], true ), $this->mDate->date( "d", $item['timestamp'], true ), $this->mDate->date( "Y", $item['timestamp'], true ) ); - $ret[$dstart][] = $item; - } - return $ret; - } - - /** - * calculate the start and stop time for the current display page - **/ - function doRangeCalculations( $pDateHash ) { - $focus = $this->mDate->_getdate( $pDateHash['focus_date'], false, true ); - - if( $pDateHash['view_mode'] == 'month' ) { - $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], 1, $focus['year'] ); - $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, 1, $focus['year'] ) - 1; - } elseif( $pDateHash['view_mode'] == 'week' or $pDateHash['view_mode'] == 'weeklist') { - if ( $focus['wday'] == 0 ) { - $wd = 7 + WEEK_OFFSET; - } else { - $wd = $focus['wday'] + WEEK_OFFSET; - } - // if we are moving out from the selected week, move us back in - if( $wd > 7 ) { - $wd -= 7; - } - - $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - $wd, $focus['year'] ); - $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - $wd + 7, $focus['year'] ) - 1; - } else { - $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] , $focus['year'] ); - $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ) - 1; - } - - $start_year = $this->mDate->date( 'Y', $view_start, true ); - if ( $start_year < 1902 ) { - $view_start_iso = $view_start = $this->mDate->date( 'Y-m-d', $view_start, true ); - $view_end_iso = $view_end = $this->mDate->date( 'Y-m-d', $view_start, true ); - $view_start = 0; - $view_end = 0; - } - - $ret = array( - 'view_start' => $view_start, - 'view_end' => $view_end, - ); - // Insert ISO dates if they are set - Used for dates pre 1902 - if ( !empty($view_start_iso) ) { - $ret['view_start_iso'] = $view_start_iso; - $ret['view_end_iso'] = $view_end_iso; - } - return $ret; - } - - /** - * prepare ListHash to ensure errorfree usage - **/ - public static function prepGetList( &$pListHash ) { - $pListHash['include_data'] = TRUE; - if( !empty( $pListHash['focus_date'] ) ) { - $calDates = $this->doRangeCalculations( $pListHash ); - $pListHash['time_limit_start'] = $calDates['view_start'] - $this->display_offset; - $pListHash['time_limit_stop'] = $calDates['view_end'] - $this->display_offset; - } - if ( empty( $pListHash['sort_mode'] ) ) { - $pListHash['sort_mode'] = !empty( $_REQUEST['sort_mode'] ) ? $_REQUEST['sort_mode'] : 'event_time_asc'; - } - $pListHash['time_limit_column'] = preg_replace( "/(_asc$|_desc$)/i", "", $pListHash['sort_mode'] ); - - if ( empty( $pListHash['user_id'] ) ) { - $pListHash['user_id'] = !empty( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : NULL; - } - if ( !empty( $_REQUEST['order_table'] ) ) { - $pListHash['order_table'] = $_REQUEST['order_table']; - } - - // Don't think this is required. - $pListHash['offset'] = 0; - // There should at least be a preference for this. - $pListHash['max_records'] = 500; - - LibertyContent::prepGetList( $pListHash ); - return TRUE; - } - - function buildDay( $pDateHash ) { - global $gBitSystem, $gBitUser; - $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); - - $ret = array(); - if( $pDateHash['view_mode'] == 'day' ) { - // calculare what the visible day view range is - $day_start = isset( $gBitUser->mUserPrefs['calendar_day_start'] ) ? $gBitUser->mUserPrefs['calendar_day_start'] : $gBitSystem->getConfig( 'calendar_day_start', 0 ); - $day_end = isset( $gBitUser->mUserPrefs['calendar_day_end'] ) ? $gBitUser->mUserPrefs['calendar_day_end'] : $gBitSystem->getConfig( 'calendar_day_end', 24 ); - $start_time = $this->mDate->mktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] ) + ( 60 * 60 * $day_start ); - $stop_time = $this->mDate->mktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ) - ( 60 * 60 * ( 24 - $day_end ) ); - $hours_count = ( $stop_time - $start_time ) / ( 60 * 60 ); - - // allow for custom time intervals - $hour_fraction = !empty( $gBitUser->mUserPrefs['calendar_hour_fraction'] ) ? $gBitUser->mUserPrefs['calendar_hour_fraction'] : $gBitSystem->getConfig( 'calendar_hour_fraction', 1 ); - $row_count = $hours_count * $hour_fraction; - $start_time_info = $this->mDate->getdate( $start_time, false, true ); - $hour = $start_time_info['hours'] - 1; - $mins = 0; - for( $i = 0; $i < $row_count; $i++ ) { - if( !( $i % $hour_fraction ) ) { - // set vars - $hour++; - $mins = 0; - } - $ret[$i]['time'] = $this->mDate->gmmktime( $hour, $mins, 0, $focus['mon'], $focus['mday'], $focus['year'] ); - $mins += 60 / $hour_fraction; - } - // calendar data is added below - } - return $ret; - } - - /** - * build an array of unix UTC timestamps relating to the current - * calendar focus. This provides a fixed basis from which to apply local - * offsets provided by tz_offset information. Daylight saving information - * is not available via this route! - **/ - function buildCalendarNavigation( $pDateHash ) { - global $gBitUser, $gBitSystem; - $today = $this->mDate->getdate( time(), false, true ); - $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); - - $ret = array( - 'before' => array( - 'day' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - 1, $focus['year'] ), - 'week' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - 7, $focus['year'] ), - 'month' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] - 1, $focus['mday'], $focus['year'] ), - 'year' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] - 1 ), - ), - 'after' => array( - 'day' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ), - 'week' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 7, $focus['year'] ), - 'month' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, $focus['mday'], $focus['year'] ), - 'year' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] + 1 ), - ), - 'focus_month' => $focus['mon'], - 'focus_year' => $focus['year'], - 'focus_date' => $focus[0], - 'today' => $this->mDate->gmmktime( 0, 0, 0, $today['mon'], $today['mday'], $today['year'] ), - 'tz_flag' => $gBitUser->getPreference('site_display_utc', "Local"), - 'display_focus_date' => $focus[0], - ); - - return $ret; - } - - /** - * build a two dimensional array of unix timestamps - * The timestamps are either UTC or display local time depending on the - * setting of the current users display time offset - * mktime SHOULD NOT BE USED since it offsets the times based on server - * timezone and daylight saving, but the USERS daylight saving information - * is not available, which will cause some problems! - **/ - function buildMonth( $pDateHash ) { - global $gBitSmarty; - - $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); - - $prev_month_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], 0, $focus['year'] ); - $next_month_begin = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, 1, $focus['year'] ); - - $prev_month_end_info = $this->mDate->getdate( $prev_month_end, false, true ); - $prev_month = $prev_month_end_info['mon']; - $prev_month_year = $prev_month_end_info['year']; - - // Build a two-dimensional array of UNIX timestamps. - $cal = array(); - - // Start the first row with the final day( s ) of the previous month. - $week = array(); - $month_begin = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], WEEK_OFFSET, $focus['year'] ); - $month_begin_day_of_week = $this->mDate->dayOfWeek( $focus['year'], $focus['mon'], WEEK_OFFSET ); - $days_in_prev_month = $this->mDate->daysInMonth( $prev_month, $prev_month_year ); - - // Fill out the first row with the last day( s ) of the previous month. - for( $day_of_week = 0; $day_of_week < $month_begin_day_of_week; $day_of_week++ ) { - $_day = $days_in_prev_month - $month_begin_day_of_week + $day_of_week + 1; - $week[]['day'] = $this->mDate->mktime( 0, 0, 0, $prev_month, $_day, $prev_month_year ); - } - - // Fill in the days of the selected month. - $days_in_month = $this->mDate->daysInMonth( $focus['mon'], $focus['year'] ); - for( $i = 1; $i <= $days_in_month; $i++ ) { - if( $day_of_week == 7 ) { - $calendar[$this->mDate->weekOfYear( $focus['year'], $focus['mon'], $i )] = $week; - - // re-initialize $day_of_week and $week - $day_of_week = 0; - $week = array(); - } - $week[]['day'] = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $i, $focus['year'] ); - $day_of_week++; - } - - // Fill out the last row with the first day( s ) of the next month. - for( $j = 1; $day_of_week < 7; $j++, $day_of_week++ ) { - $week[]['day'] = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, $j, $focus['year'] ); - } - $week_num = $this->mDate->weekOfYear( $focus['year'], $focus['mon'], $days_in_month + $j ); - $calendar[$week_num] = $week; - - // Modify offset to fix roll over on week numbers - // This is required because the week numbers are calculated for Sunday - // Offseting the result in BitDate is the real solution - if ( WEEK_OFFSET == 7 ) $offset = $focus['mday'] + 1; - else $offset = $focus['mday'] + 1 + WEEK_OFFSET; - // this week number has to be calculated, since the cal start can be configured - $week_num = $this->mDate->weekOfYear( $focus['year'], $focus['mon'], $offset ); - - // if we only want to see a weeks / days worth of data, nuke all xs data - if( $pDateHash['view_mode'] == 'week' or $pDateHash['view_mode'] == 'weeklist' ) { - $cal = $calendar[$week_num]; - $calendar = array(); - $calendar[$week_num] = $cal; - } elseif( $pDateHash['view_mode'] == 'day' ) { - $calendar = array(); - $calendar[$week_num][]['day'] = $pDateHash['focus_date']; - } - - return $calendar; - } - - // Setup the content types for use in the calendar. - function setupContentTypes() { - global $gLibertySystem, $gBitSmarty, $gBitSystem; - foreach( $gLibertySystem->mContentTypes as $cName => $cType ) { - if ( $gBitSystem->isPackageActive( $cType['handler_package'] ) ) { - $contentTypes[$cType['content_type_guid']] = $gLibertySystem->getContentTypeName( $cType['content_type_guid'] ); - } - } - asort($contentTypes); - $gBitSmarty->assign( 'calContentTypes', $contentTypes ); - } - - // Setup the day names for use in the calendar - function setupDayNames() { - global $gBitSmarty; - - // set up daynames for the calendar - $dayNames = array( - tra( "Monday" ), - tra( "Tuesday" ), - tra( "Wednesday" ), - tra( "Thursday" ), - tra( "Friday" ), - tra( "Saturday" ), - tra( "Sunday" ), - ); - - // depending on what day we want to view first, we need to adjust the dayNames array - for( $i = 0; $i < WEEK_OFFSET; $i++ ) { - $pop = array_pop( $dayNames ); - array_unshift( $dayNames, $pop ); - } - $gBitSmarty->assign( 'dayNames', $dayNames ); - } - - function processRequestHash(&$pRequest, &$pStore) { - global $gBitUser; - if( !empty( $pRequest["content_type_guid"] ) ) { - if( $gBitUser->isRegistered() ) { - $gBitUser->storePreference( 'calendar_default_guids', serialize( $pRequest['content_type_guid'] ) ); - } - $pStore['content_type_guid'] = $pRequest["content_type_guid"]; - } elseif( !isset( $pStore['content_type_guid'] ) && $gBitUser->getPreference( 'calendar_default_guids' ) && $gBitUser->isRegistered() ) { - $pStore['content_type_guid'] = unserialize( $gBitUser->getPreference( 'calendar_default_guids' ) ); - } elseif( !isset( $pStore['content_type_guid'] ) ) { - $pStore['content_type_guid'] = array(); - } elseif( isset( $pRequest["refresh"] ) && !isset( $pRequest["content_type_guid"] ) ) { - $pStore['content_type_guid'] = array(); - } - - // set up the todate - if( !empty( $pRequest["todate"] ) ) { - // clean up todate. who knows where this has come from - if ( is_numeric( $pRequest['todate'] ) ) { - $pStore['focus_date'] = $pRequest['todate'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( 'm', $pRequest['todate'], true ), $this->mDate->date( 'd', $pRequest['todate'], true ), $this->mDate->date( 'Y', $pRequest['todate'], true ) ); - } else { - $pStore['focus_date'] = $pRequest['todate'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date2( 'm', $pRequest['todate'], true ), $this->mDate->date2( 'd', $pRequest['todate'], true ), $this->mDate->date2( 'Y', $pRequest['todate'], true ) ); - } - } elseif( !empty( $pStore['focus_date'] ) ) { - $pRequest["todate"] = $pStore['focus_date']; - } else { - $pStore['focus_date'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( 'm' ), $this->mDate->date( 'd' ), $this->mDate->date( 'Y' ) ); - $pRequest["todate"] = $pStore['focus_date']; - } - - $focus = $pRequest['todate']; - if( !empty( $pRequest["view_mode"] ) ) { - $pStore['view_mode'] = $pRequest["view_mode"]; - } elseif( empty( $pStore['view_mode'] ) ) { - $pStore['view_mode'] = 'month'; - } - } - - function getEvents(&$pListHash) { - global $gBitSystem, $gLibertySystem; - - $bitEvents = array(); - if ( !empty( $pListHash['content_type_guid'] ) ) { - // Verify that the type is still active - foreach ( $pListHash['content_type_guid'] as $index => $type ) { - if ( !$gBitSystem->isPackageActive( $gLibertySystem->mContentTypes[$type]['handler_package'] ) ) { - unset( $pListHash['content_type_guid'][$index] ); - } - if ( !empty( $pListHash['content_type_guid'] ) ) { - $bitEvents = $this->getList( $pListHash ); - } - } - } - - return $bitEvents; - } - - function buildCalendar(&$pListHash, &$pDateHash) { - global $gBitSmarty, $gBitSystem; - - if( isset($pDateHash['focus_date']) && !isset($pListHash['focus_date']) ) { - $pListHash['focus_date'] = $pDateHash['focus_date']; - } - if( isset($pDateHash['view_mode']) && !isset($pListHash['view_mode']) ) { - $pListHash['view_mode'] = $pDateHash['view_mode']; - } - $bitEvents = $this->getEvents($pListHash); - - $gBitSmarty->assign( 'navigation', $this->buildCalendarNavigation( $pDateHash ) ); - $calMonth = $this->buildMonth( $pDateHash ); - $calDay = $this->buildDay( $pDateHash ); - - foreach( $calMonth as $w => $week ) { - foreach( $week as $d => $day ) { - $dayEvents = array(); - if( !empty( $bitEvents[$day['day']] ) ) { - $i = 0; - foreach( $bitEvents[$day['day']] as $bitEvent ) { - $bitEvent['parsed_data'] = self::parseDataHash($bitEvent); - $dayEvents[$i] = $bitEvent; - if (!$gBitSystem->isFeatureActive('calendar_ajax_popups')) { - $gBitSmarty->assign( 'cellHash', $bitEvent ); - $dayEvents[$i]["over"] = $gBitSmarty->fetch( "bitpackage:calendar/calendar_box.tpl" ); - } - - // populate $calDay array with events - if( !empty ( $bitEvent ) && $pDateHash['view_mode'] == 'day' ) { - foreach( $calDay as $key => $t ) { - // special case - last item entry in array - check this first - - if( $bitEvent['timestamp'] >= $calDay[$key]['time'] && empty( $calDay[$key + 1]['time'] ) ) { - $calDay[$key]['items'][] = $dayEvents[$i]; - } elseif( $bitEvent['timestamp'] >= $calDay[$key]['time'] && $bitEvent['timestamp'] < $calDay[$key + 1]['time'] ) { - $calDay[$key]['items'][] = $dayEvents[$i]; - } - } - } - - $i++; - } - } - if( !empty( $dayEvents ) ) { - $calMonth[$w][$d]['items'] = array_values( $dayEvents ); - } - } - } - $gBitSmarty->assignByRef( 'calDay', $calDay ); - $gBitSmarty->assignByRef( 'calMonth', $calMonth ); - } - - function setupCalendar($pShowContentOptions = TRUE) { - global $gBitThemes, $gBitSmarty, $gBitSystem; - if ( $pShowContentOptions ) { - $this->setupContentTypes(); - } - $this->setupDayNames(); - - if ($gBitSystem->isFeatureActive('calendar_ajax_popups')) { - $gBitThemes->loadAjax( 'mochikit' ); - } - - // TODO: make this a pref - $gBitSmarty->assign( 'trunc', $gBitSystem->getConfig( 'title_truncate', 32 ) ); - } - - // Display the actual calendar doing any other work required for the template - function display($pTitle, $pShowContentOptions = TRUE, $pBaseUrl=NULL) { - global $gBitSystem, $gBitSmarty; - - $this->setupCalendar($pShowContentOptions); - - // A default base for the calendar - if( empty($pBaseUrl) ){ - $pBaseUrl = CALENDAR_PKG_URL.'index.php'; - } - // Asssign it so templates see it. - $gBitSmarty->assign('baseCalendarUrl', $pBaseUrl); - - $gBitSystem->display( 'bitpackage:calendar/calendar.tpl', $pTitle , array( 'display_mode' => 'display' )); - - } -} -?> diff --git a/includes/bit_setup_inc.php b/includes/bit_setup_inc.php index 44444dd..85f47b7 100644 --- a/includes/bit_setup_inc.php +++ b/includes/bit_setup_inc.php @@ -1,21 +1,28 @@ 'calendar', - 'package_path' => dirname( dirname( __FILE__ ) ).'/', - 'homeable' => TRUE, -); -$gBitSystem->registerPackage( $registerHash ); + 'package_path' => dirname( dirname( __FILE__ ) ) . '/', + 'homeable' => true, +]; + +// fix to quieten down VS Code which can't see the dynamic creation of these ... +define( 'CALENDAR_PKG_NAME', $pRegisterHash['package_name'] ); +define( 'CALENDAR_PKG_URL', BIT_ROOT_URL . basename( $pRegisterHash['package_path'] ) . '/' ); +define( 'CALENDAR_PKG_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/' ); +define( 'CALENDAR_PKG_INCLUDE_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/includes/'); +define( 'CALENDAR_PKG_CLASS_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/includes/classes/'); +define( 'CALENDAR_PKG_ADMIN_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/admin/'); +$gBitSystem->registerPackage( $pRegisterHash ); if( $gBitSystem->isPackageActive( 'calendar' ) && $gBitUser->hasPermission( 'p_calendar_view' )) { - $menuHash = array( - 'package_name' => CALENDAR_PKG_NAME, - 'index_url' => CALENDAR_PKG_URL.'index.php', - 'menu_template' => 'bitpackage:calendar/menu_calendar.tpl', - ); + $menuHash = [ + 'package_name' => CALENDAR_PKG_NAME, + 'index_url' => CALENDAR_PKG_URL . 'index.php', + 'menu_template' => 'bitpackage:calendar/menu_calendar.tpl', + ]; $gBitSystem->registerAppMenu( $menuHash ); } -?> diff --git a/includes/classes/Calendar.php b/includes/classes/Calendar.php new file mode 100644 index 0000000..f62f907 --- /dev/null +++ b/includes/classes/Calendar.php @@ -0,0 +1,483 @@ +mUserPrefs['calendar_week_offset'] ) ? $gBitUser->mUserPrefs['calendar_week_offset'] : $gBitSystem->getConfig( 'calendar_week_offset', 0 ) ); + +/** + * @package calendar + */ +class Calendar extends LibertyContent { + + public $display_offset; + public $mDate; + + public function Calendar() { + parent::__construct(); + global $gBitUser; + $this->mDate = new BitDate(0); + $this->display_offset = $this->mDate->get_display_offset(); + } + + /** + * get a full list of content for a given time period + * return array of items + * + * The output array will be a set of UTC tagged pages covering the period + * defined in the $pListHash. Items identified from the list will be tagged to + * the day identified in the selected timestamp from which the list was built. + * If the user has selected a local time display, then the day will be the actual + * UTC day that the item is in, rather than the UTC day of the item. In this way + * the display view provides a list of locally correct entries for each day. + **/ + public function getList( $pListHash ) { + $ret = []; + + $pListHash['include_data'] = TRUE; + if( !empty( $pListHash['focus_date'] ) ) { + $calDates = $this->doRangeCalculations( $pListHash ); + $pListHash['time_limit_start'] = $calDates['view_start'] - $this->display_offset; + $pListHash['time_limit_stop'] = $calDates['view_end'] - $this->display_offset; + } +// if ( empty( $pListHash['sort_mode'] ) ) { +// $pListHash['sort_mode'] = !empty( $_REQUEST['sort_mode'] ) ? $_REQUEST['sort_mode'] : 'event_time_asc'; +// } + $pListHash['sort_mode'] = 'event_time_asc'; + $pListHash['time_limit_column'] = preg_replace( "/(_asc$|_desc$)/i", "", $pListHash['sort_mode'] ); + + if ( empty( $pListHash['user_id'] ) ) { + $pListHash['user_id'] = !empty( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : NULL; + } + if ( !empty( $_REQUEST['order_table'] ) ) { + $pListHash['order_table'] = $_REQUEST['order_table']; + } + + // Don't think this is required. + $pListHash['offset'] = 0; + // There should at least be a preference for this. + $pListHash['max_records'] = 500; + + $res = $this->getContentList( $pListHash ); + + foreach( $res as $item ) { + // shift all time data by user timezone offset + // and then display as a simple UTC time + $item['timestamp'] = $item[$pListHash['time_limit_column']] + $this->display_offset; + $item['created'] += $this->display_offset; + $item['last_modified'] += $this->display_offset; + $item['event_time'] += $this->display_offset; + $item['parsed'] = self::parseDataHash( $item ); + $dstart = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( "m", $item['timestamp'], true ), $this->mDate->date( "d", $item['timestamp'], true ), $this->mDate->date( "Y", $item['timestamp'], true ) ); + $ret[$dstart][] = $item; + } + return $ret; + } + + /** + * calculate the start and stop time for the current display page + **/ + public function doRangeCalculations( $pDateHash ) { + $focus = $this->mDate->_getdate( $pDateHash['focus_date'], false, true ); + + if( $pDateHash['view_mode'] == 'month' ) { + $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], 1, $focus['year'] ); + $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, 1, $focus['year'] ) - 1; + } elseif( $pDateHash['view_mode'] == 'week' or $pDateHash['view_mode'] == 'weeklist') { + $wd = $focus['wday'] == 0 ? 7 + WEEK_OFFSET : $focus['wday'] + WEEK_OFFSET; + // if we are moving out from the selected week, move us back in + if( $wd > 7 ) { + $wd -= 7; + } + + $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - $wd, $focus['year'] ); + $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - $wd + 7, $focus['year'] ) - 1; + } else { + $view_start = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] , $focus['year'] ); + $view_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ) - 1; + } + + $start_year = $this->mDate->date( 'Y', $view_start, true ); + if ( $start_year < 1902 ) { + $view_start_iso = $view_start = $this->mDate->date( 'Y-m-d', $view_start, true ); + $view_end_iso = $view_end = $this->mDate->date( 'Y-m-d', $view_start, true ); + $view_start = 0; + $view_end = 0; + } + + $ret = [ + 'view_start' => $view_start, + 'view_end' => $view_end, + ]; + // Insert ISO dates if they are set - Used for dates pre 1902 + if ( !empty($view_start_iso) ) { + $ret['view_start_iso'] = $view_start_iso; + $ret['view_end_iso'] = $view_end_iso; + } + return $ret; + } + + /** + * prepare ListHash to ensure errorfree usage + * @param array pListHash hash of parameters for any getList() function + * @return array the link to display the page. + **/ + public function prepGetList( &$pListHash ) { + $pListHash['include_data'] = TRUE; + if( !empty( $pListHash['focus_date'] ) ) { + $calDates = $this->doRangeCalculations( $pListHash ); + $pListHash['time_limit_start'] = $calDates['view_start'] - $this->display_offset; + $pListHash['time_limit_stop'] = $calDates['view_end'] - $this->display_offset; + } + if ( empty( $pListHash['sort_mode'] ) ) { + $pListHash['sort_mode'] = !empty( $_REQUEST['sort_mode'] ) ? $_REQUEST['sort_mode'] : 'event_time_asc'; + } + $pListHash['time_limit_column'] = preg_replace( "/(_asc$|_desc$)/i", "", $pListHash['sort_mode'] ); + + if ( empty( $pListHash['user_id'] ) ) { + $pListHash['user_id'] = !empty( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : NULL; + } + if ( !empty( $_REQUEST['order_table'] ) ) { + $pListHash['order_table'] = $_REQUEST['order_table']; + } + + // Don't think this is required. + $pListHash['offset'] = 0; + // There should at least be a preference for this. + $pListHash['max_records'] = 500; + + LibertyContent::prepGetList( $pListHash ); + return TRUE; + } + + public function buildDay( $pDateHash ) { + global $gBitSystem, $gBitUser; + $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); + + $ret = []; + if( $pDateHash['view_mode'] == 'day' ) { + // calculare what the visible day view range is + $day_start = $gBitUser->mUserPrefs['calendar_day_start'] ?? $gBitSystem->getConfig( 'calendar_day_start', 0 ); + $day_end = $gBitUser->mUserPrefs['calendar_day_end'] ?? $gBitSystem->getConfig( 'calendar_day_end', 24 ); + $start_time = $this->mDate->mktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] ) + ( 60 * 60 * $day_start ); + $stop_time = $this->mDate->mktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ) - ( 60 * 60 * ( 24 - $day_end ) ); + $hours_count = ( $stop_time - $start_time ) / ( 60 * 60 ); + + // allow for custom time intervals + $hour_fraction = !empty( $gBitUser->mUserPrefs['calendar_hour_fraction'] ) ? $gBitUser->mUserPrefs['calendar_hour_fraction'] : $gBitSystem->getConfig( 'calendar_hour_fraction', 1 ); + $row_count = $hours_count * $hour_fraction; + $start_time_info = $this->mDate->getdate( $start_time, false, true ); + $hour = $start_time_info['hours'] - 1; + $mins = 0; + for( $i = 0; $i < $row_count; $i++ ) { + if( !( $i % $hour_fraction ) ) { + // set vars + $hour++; + $mins = 0; + } + $ret[$i]['time'] = $this->mDate->gmmktime( $hour, $mins, 0, $focus['mon'], $focus['mday'], $focus['year'] ); + $mins += 60 / $hour_fraction; + } + // calendar data is added below + } + return $ret; + } + + /** + * build an array of unix UTC timestamps relating to the current + * calendar focus. This provides a fixed basis from which to apply local + * offsets provided by tz_offset information. Daylight saving information + * is not available via this route! + **/ + public function buildCalendarNavigation( $pDateHash ) { + global $gBitUser, $gBitSystem; + $today = $this->mDate->getdate( time(), false, true ); + $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); + + $ret = [ + 'before' => [ + 'day' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - 1, $focus['year'] ), + 'week' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] - 7, $focus['year'] ), + 'month' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] - 1, $focus['mday'], $focus['year'] ), + 'year' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] - 1 ), + ], + 'after' => [ + 'day' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 1, $focus['year'] ), + 'week' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'] + 7, $focus['year'] ), + 'month' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, $focus['mday'], $focus['year'] ), + 'year' => $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $focus['mday'], $focus['year'] + 1 ), + ], + 'focus_month' => $focus['mon'], + 'focus_year' => $focus['year'], + 'focus_date' => $focus[0], + 'today' => $this->mDate->gmmktime( 0, 0, 0, $today['mon'], $today['mday'], $today['year'] ), + 'tz_flag' => $gBitUser->getPreference( 'site_display_utc', "Local" ), + 'display_focus_date' => $focus[0], + ]; + + return $ret; + } + + /** + * build a two dimensional array of unix timestamps + * The timestamps are either UTC or display local time depending on the + * setting of the current users display time offset + * mktime SHOULD NOT BE USED since it offsets the times based on server + * timezone and daylight saving, but the USERS daylight saving information + * is not available, which will cause some problems! + **/ + public function buildMonth( $pDateHash ) { + global $gBitSmarty; + + $focus = $this->mDate->getdate( $pDateHash['focus_date'], false, true ); + + $prev_month_end = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], 0, $focus['year'] ); + $next_month_begin = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, 1, $focus['year'] ); + + $prev_month_end_info = $this->mDate->getdate( $prev_month_end, false, true ); + $prev_month = $prev_month_end_info['mon']; + $prev_month_year = $prev_month_end_info['year']; + + // Build a two-dimensional array of UNIX timestamps. + $cal = []; + + // Start the first row with the final day( s ) of the previous month. + $week = []; + $month_begin = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], WEEK_OFFSET, $focus['year'] ); + $month_begin_day_of_week = $this->mDate->dayOfWeek( $focus['year'], $focus['mon'], WEEK_OFFSET ); + $days_in_prev_month = $this->mDate->daysInMonth( $prev_month, $prev_month_year ); + + // Fill out the first row with the last day( s ) of the previous month. + for( $day_of_week = 0; $day_of_week < $month_begin_day_of_week; $day_of_week++ ) { + $_day = $days_in_prev_month - $month_begin_day_of_week + $day_of_week + 1; + $week[]['day'] = $this->mDate->mktime( 0, 0, 0, $prev_month, $_day, $prev_month_year ); + } + + // Fill in the days of the selected month. + $days_in_month = $this->mDate->daysInMonth( $focus['mon'], $focus['year'] ); + for( $i = 1; $i <= $days_in_month; $i++ ) { + if( $day_of_week == 7 ) { + $calendar[$this->mDate->weekOfYear( $focus['year'], $focus['mon'], $i )] = $week; + + // re-initialize $day_of_week and $week + $day_of_week = 0; + $week = []; + } + $week[]['day'] = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'], $i, $focus['year'] ); + $day_of_week++; + } + + // Fill out the last row with the first day( s ) of the next month. + for( $j = 1; $day_of_week < 7; $j++, $day_of_week++ ) { + $week[]['day'] = $this->mDate->gmmktime( 0, 0, 0, $focus['mon'] + 1, $j, $focus['year'] ); + } + $week_num = $this->mDate->weekOfYear( $focus['year'], $focus['mon'], $days_in_month + $j ); + $calendar[$week_num] = $week; + + // Modify offset to fix roll over on week numbers + // This is required because the week numbers are calculated for Sunday + // Offseting the result in BitDate is the real solution + $offset = WEEK_OFFSET == 7 ? $focus['mday'] + 1 : $focus['mday'] + 1 + WEEK_OFFSET; + // this week number has to be calculated, since the cal start can be configured + $week_num = $this->mDate->weekOfYear( $focus['year'], $focus['mon'], $offset ); + + // if we only want to see a weeks / days worth of data, nuke all xs data + if( $pDateHash['view_mode'] == 'week' or $pDateHash['view_mode'] == 'weeklist' ) { + $cal = $calendar[$week_num]; + $calendar = []; + $calendar[$week_num] = $cal; + } elseif( $pDateHash['view_mode'] == 'day' ) { + $calendar = []; + $calendar[$week_num][]['day'] = $pDateHash['focus_date']; + } + + return $calendar; + } + + // Setup the content types for use in the calendar. + public function setupContentTypes() { + global $gLibertySystem, $gBitSmarty, $gBitSystem; + foreach( $gLibertySystem->mContentTypes as $cName => $cType ) { + if ( $gBitSystem->isPackageActive( $cType['handler_package'] ) ) { + $contentTypes[$cType['content_type_guid']] = $gLibertySystem->getContentTypeName( $cType['content_type_guid'] ); + } + } + asort($contentTypes); + $gBitSmarty->assign( 'calContentTypes', $contentTypes ); + } + + // Setup the day names for use in the calendar + public function setupDayNames() { + global $gBitSmarty; + + // set up daynames for the calendar + $dayNames = [ + KernelTools::tra( "Monday" ), + KernelTools::tra( "Tuesday" ), + KernelTools::tra( "Wednesday" ), + KernelTools::tra( "Thursday" ), + KernelTools::tra( "Friday" ), + KernelTools::tra( "Saturday" ), + KernelTools::tra( "Sunday" ), + ]; + + // depending on what day we want to view first, we need to adjust the dayNames array + for( $i = 0; $i < WEEK_OFFSET; $i++ ) { + $pop = array_pop( $dayNames ); + array_unshift( $dayNames, $pop ); + } + $gBitSmarty->assign( 'dayNames', $dayNames ); + } + + function processRequestHash(&$pRequest, &$pStore) { + global $gBitUser; + if( !empty( $pRequest["content_type_guid"] ) ) { + if( $gBitUser->isRegistered() ) { + $gBitUser->storePreference( 'calendar_default_guids', serialize( $pRequest['content_type_guid'] ) ); + } + $pStore['content_type_guid'] = $pRequest["content_type_guid"]; + } elseif( !isset( $pStore['content_type_guid'] ) && $gBitUser->getPreference( 'calendar_default_guids' ) && $gBitUser->isRegistered() ) { + $pStore['content_type_guid'] = unserialize( $gBitUser->getPreference( 'calendar_default_guids' ) ); + } elseif( !isset( $pStore['content_type_guid'] ) ) { + $pStore['content_type_guid'] = []; + } elseif( isset( $pRequest["refresh"] ) && !isset( $pRequest["content_type_guid"] ) ) { + $pStore['content_type_guid'] = []; + } + + // set up the todate + if( !empty( $pRequest["todate"] ) ) { + // clean up todate. who knows where this has come from + $pStore['focus_date'] = is_numeric( $pRequest['todate'] ) ? $pRequest['todate'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( 'm', $pRequest['todate'], true ), $this->mDate->date( 'd', $pRequest['todate'], true ), $this->mDate->date( 'Y', $pRequest['todate'], true ) ) : $pRequest['todate'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date2( 'm', $pRequest['todate'], true ), $this->mDate->date2( 'd', $pRequest['todate'], true ), $this->mDate->date2( 'Y', $pRequest['todate'], true ) ); + } elseif( !empty( $pStore['focus_date'] ) ) { + $pRequest["todate"] = $pStore['focus_date']; + } else { + $pStore['focus_date'] = $this->mDate->gmmktime( 0, 0, 0, $this->mDate->date( 'm' ), $this->mDate->date( 'd' ), $this->mDate->date( 'Y' ) ); + $pRequest["todate"] = $pStore['focus_date']; + } + + $focus = $pRequest['todate']; + if( !empty( $pRequest["view_mode"] ) ) { + $pStore['view_mode'] = $pRequest["view_mode"]; + } elseif( empty( $pStore['view_mode'] ) ) { + $pStore['view_mode'] = 'month'; + } + } + + public function getEvents(&$pListHash) { + global $gBitSystem, $gLibertySystem; + + $bitEvents = []; + if ( !empty( $pListHash['content_type_guid'] ) ) { + // Verify that the type is still active + foreach ( $pListHash['content_type_guid'] as $index => $type ) { + if ( !$gBitSystem->isPackageActive( $gLibertySystem->mContentTypes[$type]['handler_package'] ) ) { + unset( $pListHash['content_type_guid'][$index] ); + } + if ( !empty( $pListHash['content_type_guid'] ) ) { + $bitEvents = $this->getList( $pListHash ); + } + } + } + + return $bitEvents; + } + + public function buildCalendar(&$pListHash, &$pDateHash) { + global $gBitSmarty, $gBitSystem; + + if( isset($pDateHash['focus_date']) && !isset($pListHash['focus_date']) ) { + $pListHash['focus_date'] = $pDateHash['focus_date']; + } + if( isset($pDateHash['view_mode']) && !isset($pListHash['view_mode']) ) { + $pListHash['view_mode'] = $pDateHash['view_mode']; + } + $bitEvents = $this->getEvents($pListHash); + + $gBitSmarty->assign( 'navigation', $this->buildCalendarNavigation( $pDateHash ) ); + $calMonth = $this->buildMonth( $pDateHash ); + $calDay = $this->buildDay( $pDateHash ); + + foreach( $calMonth as $w => $week ) { + foreach( $week as $d => $day ) { + $dayEvents = []; + if( !empty( $bitEvents[$day['day']] ) ) { + $i = 0; + foreach( $bitEvents[$day['day']] as $bitEvent ) { + $bitEvent['parsed_data'] = self::parseDataHash($bitEvent); + $dayEvents[$i] = $bitEvent; + if (!$gBitSystem->isFeatureActive('calendar_ajax_popups')) { + $gBitSmarty->assign( 'cellHash', $bitEvent ); + $dayEvents[$i]["over"] = $gBitSmarty->fetch( "bitpackage:calendar/calendar_box.tpl" ); + } + + // populate $calDay array with events + if( !empty ( $bitEvent ) && $pDateHash['view_mode'] == 'day' ) { + foreach( $calDay as $key => $t ) { + // special case - last item entry in array - check this first + + if( $bitEvent['timestamp'] >= $calDay[$key]['time'] && empty( $calDay[$key + 1]['time'] ) ) { + $calDay[$key]['items'][] = $dayEvents[$i]; + } elseif( $bitEvent['timestamp'] >= $calDay[$key]['time'] && $bitEvent['timestamp'] < $calDay[$key + 1]['time'] ) { + $calDay[$key]['items'][] = $dayEvents[$i]; + } + } + } + + $i++; + } + } + if( !empty( $dayEvents ) ) { + $calMonth[$w][$d]['items'] = array_values( $dayEvents ); + } + } + } + $gBitSmarty->assign( 'calDay', $calDay ); + $gBitSmarty->assign( 'calMonth', $calMonth ); + } + + function setupCalendar($pShowContentOptions = TRUE) { + global $gBitThemes, $gBitSmarty, $gBitSystem; + if ( $pShowContentOptions ) { + $this->setupContentTypes(); + } + $this->setupDayNames(); + + if ($gBitSystem->isFeatureActive('calendar_ajax_popups')) { + $gBitThemes->loadAjax( 'mochikit' ); + } + + // TODO: make this a pref + $gBitSmarty->assign( 'trunc', $gBitSystem->getConfig( 'title_truncate', 32 ) ); + } + + // Display the actual calendar doing any other work required for the template + function display($pTitle, $pShowContentOptions = TRUE, $pBaseUrl=NULL) { + global $gBitSystem, $gBitSmarty; + + $this->setupCalendar($pShowContentOptions); + + // A default base for the calendar + if( empty($pBaseUrl) ){ + $pBaseUrl = CALENDAR_PKG_URL.'index.php'; + } + // Asssign it so templates see it. + $gBitSmarty->assign('baseCalendarUrl', $pBaseUrl); + + $gBitSystem->display( 'bitpackage:calendar/calendar.tpl', $pTitle , [ 'display_mode' => 'display' ]); + + } +} diff --git a/liberty_plugins/data.calendar.php b/liberty_plugins/data.calendar.php index 7851a6e..cc7861a 100644 --- a/liberty_plugins/data.calendar.php +++ b/liberty_plugins/data.calendar.php @@ -1,4 +1,8 @@ 'CALENDAR', - 'auto_activate' => TRUE, - 'requires_pair' => FALSE, +$pluginParams = [ + 'tag' => 'CALENDAR', + 'auto_activate' => true, + 'requires_pair' => false, 'load_function' => 'data_calendar', - 'title' => 'Calendar', - 'help_page' => 'DataPluginCalendar', - 'description' => tra("Displays a mini calendar that links to the calendar package."), - 'syntax' => " {CALENDAR} ", - 'plugin_type' => DATA_PLUGIN -); + 'title' => 'Calendar', + 'help_page' => 'DataPluginCalendar', + 'description' => KernelTools::tra( "Displays a mini calendar that links to the calendar package." ), + 'syntax' => " {CALENDAR} ", + 'plugin_type' => DATA_PLUGIN, +]; $gLibertySystem->registerPlugin( PLUGIN_GUID_DATACALENDAR, $pluginParams ); $gLibertySystem->registerDataTag( $pluginParams['tag'], PLUGIN_GUID_DATACALENDAR ); @@ -61,7 +65,7 @@ function data_calendar( $data, $params ) { $last = $bitDate->getDate($last_time); $next = $bitDate->getDate($next_time); - $days = array(); + $days = []; for ($i = 2; $i < 9; $i++) { // Start from known sunday. $timestamp = $bitDate->mktime(0, 0, 0, 1, $i, 2000); @@ -69,10 +73,10 @@ function data_calendar( $data, $params ) { } // Build a two-dimensional array of UNIX timestamps. - $calendar = array(); + $calendar = []; // Start with last days of previous month. - $week = array(); + $week = []; $month_begin = $bitDate->mktime(0, 0, 0, $month, 1, $year); $month_begin_dow = strftime('%w', $month_begin); @@ -95,7 +99,7 @@ function data_calendar( $data, $params ) { // Done with row $dow = 0; unset($week); - $week = array(); + $week = []; } $d['time'] = $bitDate->mktime(0, 0, 0, $month, $i, $year); $d['dim'] = false; @@ -127,17 +131,11 @@ function data_calendar( $data, $params ) { $gBitSmarty->assign('today', $time); // Assign a base url - if (empty($params['events'])) { - $pBaseUrl = CALENDAR_PKG_URL.'index.php'; - } - else { - $pBaseUrl = EVENTS_PKG_URL.'calendar.php'; - } + $pBaseUrl = ( empty( $params['events'] ) ) ? CALENDAR_PKG_URL . 'index.php' : CALENDAR_PKG_URL . 'calendar.php'; $gBitSmarty->assign('baseCalendarUrl', $pBaseUrl); return $gBitSmarty->fetch('bitpackage:calendar/minical.tpl'); } return '
Calendar Package Not Active
'; -} -?> +} \ No newline at end of file -- cgit v1.3