Version 4.7.6

This commit is contained in:
Neo committed 2025-12-19 16:05:19 -08:00
1 parent 8ba7d43898
commit 7b7404e741
1085 files changed
+30590 -7837

No files matched your search

@@ -50,13 +50,12 @@ class _settings extends \IPS\Dispatcher\Controller
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Radio( 'calendar_default_view', \IPS\Settings::i()->calendar_default_view, TRUE, array( 'options' => array( 'month' => 'cal_df_month', 'week' => 'cal_df_week', 'day' => 'cal_df_day', 'stream' => 'cal_df_stream' ) ) ) );
$form->add( new \IPS\Helpers\Form\Radio( 'calendar_default_view', \IPS\Settings::i()->calendar_default_view, TRUE, array( 'options' => array( 'overview' => 'cal_df_overview', 'month' => 'cal_df_month', 'week' => 'cal_df_week', 'day' => 'cal_df_day' ) ) ) );
$options = array_combine( array_keys( \IPS\calendar\Date::$dateFormats ), array_map( function( $val ){ return "calendar_df_" . $val; }, array_keys( \IPS\calendar\Date::$dateFormats ) ) );
$form->add( new \IPS\Helpers\Form\Select( 'calendar_date_format', \IPS\Settings::i()->calendar_date_format, TRUE, array( 'options' => $options, 'unlimited' => '-1', 'unlimitedLang' => "calendar_custom_df", 'unlimitedToggles' => array( 'calendar_date_format_custom' ) ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'calendar_date_format_custom', \IPS\Settings::i()->calendar_date_format_custom, FALSE, array(), NULL, NULL, NULL, 'calendar_date_format_custom' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'show_bday_calendar', \IPS\Settings::i()->show_bday_calendar ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_calendar_mon', \IPS\Settings::i()->ipb_calendar_mon ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'calendar_rss_feed', \IPS\Settings::i()->calendar_rss_feed, FALSE, array( 'togglesOn' => array( 'calendar_rss_feed_days', 'calendar_rss_feed_order' ) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'calendar_rss_feed_days', \IPS\Settings::i()->calendar_rss_feed_days, FALSE, array( 'unlimited' => -1 ), NULL, NULL, NULL, 'calendar_rss_feed_days' ) );
@@ -68,7 +67,13 @@ class _settings extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\YesNo( 'calendar_venues_enabled', \IPS\Settings::i()->calendar_venues_enabled ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'calendar_block_past_changes', \IPS\Settings::i()->calendar_block_past_changes ) );
if( \IPS\GeoLocation::enabled() )
{
$form->add( new \IPS\Helpers\Form\Number( 'map_center_lat', \IPS\Settings::i()->map_center_lat, FALSE, array( 'decimals' => 8, 'min' => "-180", 'max' => "180" ), NULL, NULL, NULL, 'map_center_lat' ) );
$form->add( new \IPS\Helpers\Form\Number( 'map_center_lon', \IPS\Settings::i()->map_center_lon, FALSE, array( 'decimals' => 8, 'min' => "-180", 'max' => "180" ), NULL, NULL, NULL, 'map_center_lon' ) );
}
if ( $values = $form->values() )
{
if( $values['calendar_date_format'] == -1 AND !$values['calendar_date_format_custom'] )
@@ -53,7 +53,7 @@ class _rsvp extends \IPS\Dispatcher\Controller
foreach( array( 0,1,2 ) as $response )
{
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_response_' . $response ), 'number', 'COUNT(*)', FALSE );
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_response_' . $response ), 'number', 'COUNT(*)', FALSE, $response );
}
$chart->title = \IPS\Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_title');
@@ -272,8 +272,6 @@ class _event extends \IPS\Content\Controller
*/
protected function downloadRsvp()
{
\IPS\Session::i()->csrfCheck();
$output = \IPS\Theme::i()->getTemplate( 'view' )->attendees( $this->event );
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $output ) );
@@ -121,8 +121,9 @@ class _view extends \IPS\Dispatcher\Controller
/* Otherwise use ACP default preference */
else
{
\IPS\Request::i()->view = \IPS\Settings::i()->calendar_default_view;
$method = "_view" . ucwords( \IPS\Settings::i()->calendar_default_view );
$this->$method( $jump, iterator_to_array( \IPS\calendar\Event::featured( 4, '_rand' ) ) );
$this->$method( $jump );
}
/* Online User Location */
@@ -140,10 +141,9 @@ class _view extends \IPS\Dispatcher\Controller
* Show month view
*
* @param \IPS\Helpers\Form $jump Calendar jump
* @param array $featured Featured events (only populated for the ACP-specified default view)
* @return void
*/
protected function _viewMonth( $jump, $featured=array() )
protected function _viewMonth( $jump )
{
/* Get the month data */
$day = NULL;
@@ -156,20 +156,6 @@ class _view extends \IPS\Dispatcher\Controller
try
{
$date = \IPS\calendar\Date::getDate( \IPS\Request::i()->y ?: NULL, \IPS\Request::i()->m ?: NULL, $day );
$showBirthday = FALSE;
/* Show birthdays if we're on the calendar landing page */
if ( $this->_calendar === NULL OR \count( $this->roots ) == 0 )
{
$showBirthday = TRUE;
}
/* show birthdays if there's only one calendar */
if ( \IPS\Request::i()->id AND $this->_calendar !== NULL OR \count( $this->roots ) == 1 )
{
$showBirthday = TRUE;
}
/* Get birthdays */
$birthdays = $showBirthday ? $date->getBirthdays( FALSE, TRUE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
@@ -190,7 +176,7 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarMonth( $this->roots, $date, $featured, $birthdays, $events, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarMonth( $this->roots, $date, $events, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
@@ -206,7 +192,6 @@ class _view extends \IPS\Dispatcher\Controller
$this->_calendar,
$jump,
$date,
$featured,
$this->_downloadLinks()
);
}
@@ -216,10 +201,9 @@ class _view extends \IPS\Dispatcher\Controller
* Show week view
*
* @param \IPS\Helpers\Form $jump Calendar jump
* @param array $featured Featured events (only populated for the ACP-specified default view)
* @return void
*/
protected function _viewWeek( $jump, $featured=array() )
protected function _viewWeek( $jump )
{
/* Get the week data */
$week = \IPS\Request::i()->w ? explode( '-', \IPS\Request::i()->w ) : NULL;
@@ -245,9 +229,6 @@ class _view extends \IPS\Dispatcher\Controller
$days[] = \IPS\calendar\Date::getDate( $date->firstDayOfWeek('year'), $date->firstDayOfWeek('mon'), $date->firstDayOfWeek('mday') )->adjust( $i . ' days' );
}
/* Get birthdays */
$birthdays = ( $this->_calendar === NULL OR \count( $this->roots ) == 0 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfWeek('year'), $date->firstDayOfWeek('mon'), $date->firstDayOfWeek('mday') ),
@@ -267,7 +248,7 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWeek( $this->roots, $date, $featured, $birthdays, $events, $nextWeek, $lastWeek, $days, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWeek( $this->roots, $date, $events, $nextWeek, $lastWeek, $days, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
@@ -289,8 +270,7 @@ class _view extends \IPS\Dispatcher\Controller
$this->roots,
$this->_calendar,
$jump,
$date,
$featured,
$date,
$this->_downloadLinks()
);
}
@@ -300,10 +280,9 @@ class _view extends \IPS\Dispatcher\Controller
* Show day view
*
* @param \IPS\Helpers\Form $jump Calendar jump
* @param array $featured Featured events (only populated for the ACP-specified default view)
* @return void
*/
protected function _viewDay( $jump, $featured=array() )
protected function _viewDay( $jump )
{
/* Get the day data */
try
@@ -318,23 +297,6 @@ class _view extends \IPS\Dispatcher\Controller
$tomorrow = clone $date->adjust( '+1 day' );
$yesterday = clone $date->adjust( '-1 day' );
/* Get birthdays */
if( isset( \IPS\Request::i()->show ) AND \IPS\Request::i()->show == 'birthdays' AND \IPS\Settings::i()->show_bday_calendar )
{
$table = new \IPS\Helpers\Table\Db( 'core_members', \IPS\Request::i()->url()->setQueryString('show', 'birthdays'), $date->getBirthdaysWhere( TRUE ) );
$table->sortBy = 'name';
$table->sortDirection = 'asc';
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'browse', 'calendar', 'front' ), 'birthdaysTable' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'browse', 'calendar', 'front' ), 'birthday' );
\IPS\Output::i()->output = $table;
\IPS\Output::i()->metaTags['robots'] = 'noindex';
return;
}
$birthdayCount = \IPS\Settings::i()->show_bday_calendar ? $date->getBirthdays( TRUE, TRUE ) : [];
$birthdays = \IPS\Settings::i()->show_bday_calendar ? $date->getBirthdays( TRUE, FALSE ) : [];
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents( clone $date, clone $date, $this->_calendar );
@@ -356,7 +318,7 @@ class _view extends \IPS\Dispatcher\Controller
{
$dayEvents['count']++;
if( $_event->all_day AND (
if( $_event->all_day AND ( $_event->nextOccurrence( $date, 'startDate' ) AND
$_event->nextOccurrence( $date, 'startDate' )->strFormat('%d') == $date->mday OR
$_event->nextOccurrence( $date, 'endDate' ) AND $_event->nextOccurrence( $date, 'endDate' )->strFormat('%d') == $date->mday
) )
@@ -365,7 +327,7 @@ class _view extends \IPS\Dispatcher\Controller
}
else
{
if( $_event->nextOccurrence( $date, 'startDate' )->strFormat('%d') == $date->mday )
if( $_event->nextOccurrence( $date, 'startDate' ) AND $_event->nextOccurrence( $date, 'startDate' )->strFormat('%d') == $date->mday )
{
$dayEvents[ $_event->_start_date->hours ][ $_event->id ] = $_event;
}
@@ -385,7 +347,7 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarDay( $this->roots, $date, $featured, $birthdays, $birthdayCount, $dayEvents, $tomorrow, $yesterday, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarDay( $this->roots, $date, $dayEvents, $tomorrow, $yesterday, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
@@ -399,8 +361,7 @@ class _view extends \IPS\Dispatcher\Controller
$this->roots,
$this->_calendar,
$jump,
$date,
$featured,
$date,
$this->_downloadLinks()
);
}
@@ -411,116 +372,6 @@ class _view extends \IPS\Dispatcher\Controller
*/
public $streamPerPage = 50;
/**
* Show stream view
*
* @param \IPS\Helpers\Form $jump Calendar jump
* @param array $featured Featured events (only populated for the ACP-specified default view)
* @return void
*/
protected function _viewStream( $jump, $featured=array() )
{
/* Get the month data */
$day = NULL;
if( ( !\IPS\Request::i()->y OR \IPS\Request::i()->y == $this->_today->year ) AND ( !\IPS\Request::i()->m OR \IPS\Request::i()->m == $this->_today->mon ) )
{
$day = $this->_today->mday;
}
try
{
$date = \IPS\calendar\Date::getDate( \IPS\Request::i()->y ?: NULL, \IPS\Request::i()->m ?: NULL, $day );
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ),
\IPS\calendar\Date::getDate( $date->lastDayOfMonth('year'), $date->lastDayOfMonth('mon'), $date->lastDayOfMonth('mday'), 23, 59, 59 ),
$this->_calendar,
NULL,
FALSE
);
}
catch( \InvalidArgumentException $e )
{
\IPS\Output::i()->error( 'error_bad_date', '2L182/A', 403, '' );
}
/* Sort */
$startDate = \IPS\calendar\Date::getDate();
@usort( $events, function( $a, $b ) use ( $startDate )
{
if( $a->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return -1;
}
if( $b->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return 1;
}
if ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() == $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() )
{
return 0;
}
return ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() < $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() ) ? -1 : 1;
} );
/* Pagination */
$pagination = array(
'page' => ( isset( \IPS\Request::i()->page ) ) ? \IPS\Request::i()->page : 1,
'pages' => ( \count( $events ) > 0 ) ? ceil( \count( $events ) / $this->streamPerPage ) : 1,
'limit' => $this->streamPerPage
);
if( $pagination['page'] < 1 )
{
$pagination['page'] = 1;
}
/* If there are no events, tell search engines not to index the page but do NOT tell them not to follow links */
if( \count( $events ) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
else
{
$events = \array_slice( $events, ( $pagination['page'] - 1 ) * $this->streamPerPage, $this->streamPerPage );
}
/* Non-existent page */
if( $pagination['page'] > 1 AND !\count( $events ) )
{
\IPS\Output::i()->error( 'no_events_month', '2L182/B', 404, '' );
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarStream( $this->roots, $date, $featured, $events, $this->_calendar, $jump, $pagination );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
/* We can show the sidebar in stream view */
\IPS\Output::i()->sidebar['enabled'] = TRUE;
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'cal_month_stream_title', FALSE, array( 'sprintf' => array( $date->monthName, $date->year ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWrapper(
$output,
$this->roots,
$this->_calendar,
$jump,
$date,
$featured,
$this->_downloadLinks()
);
}
}
/**
* Generate keyed links for RSS/iCal download
*
@@ -586,4 +437,514 @@ class _view extends \IPS\Dispatcher\Controller
return $form;
}
/**
* Overview
*
* @return void
*/
protected function _viewOverview()
{
$this->_today = \IPS\calendar\Date::getDate();
/* Featured events */
$featured = iterator_to_array( \IPS\calendar\Event::featured( 13, '_rand' ) );
/* If there are no featured get upcoming */
if( \count( $featured ) === 0 )
{
$featured = \IPS\calendar\Event::retrieveEvents(
$this->_today,
\IPS\calendar\Date::getDate()->adjust( "next year" ),
NULL,
3,
FALSE,
NULL,
NULL,
FALSE,
NULL,
TRUE
);
}
/* Events near me */
$location = NULL;
if( isset( \IPS\Request::i()->lat ) and isset( \IPS\Request::i()->lon ) )
{
$location = array( 'lat' => \IPS\Request::i()->lat, 'lon' => \IPS\Request::i()->lon );
}
else
{
/* Do an IP lookup */
try
{
$geo = \IPS\GeoLocation::getByIp( \IPS\Request::i()->ipAddress() );
$location = array( 'lat' => $geo->lat, 'lon' => $geo->long );
}
catch ( \Exception $e )
{
$location = array( 'lat' => \IPS\Settings::i()->map_center_lat, 'lon' => \IPS\Settings::i()->map_center_lon );
}
}
/* Get the calendars we can view */
$calendars = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
$nearme = \IPS\calendar\Event::retrieveEvents(
$this->_today,
\IPS\calendar\Date::getDate()->adjust( "next year" ),
NULL,
6,
FALSE,
NULL,
NULL,
FALSE,
$location,
FALSE
);
/* Set map markers */
$mapMarkers = array();
foreach ( $nearme as $event )
{
$mapMarkers[ $event->id ] = array( 'lat' => (float) $event->latitude, 'long' => (float) $event->longitude , 'title' => $event->title );
}
/* Are we just returning nearby events? */
if( \IPS\Request::i()->isAjax() && \IPS\Request::i()->get == 'nearMe' )
{
$output = \IPS\Theme::i()->getTemplate( 'events', 'calendar' )->nearMeContent( $nearme, $mapMarkers );
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
$toReturn = array(
'content' => $output,
'lat' => (float) $location['lat'],
'long' => (float) $location['lon']
);
\IPS\Output::i()->sendOutput( json_encode($toReturn), 200, 'application/json' );
return;
}
/* By month */
$day = NULL;
if( ( !\IPS\Request::i()->y OR \IPS\Request::i()->y == $this->_today->year ) AND ( !\IPS\Request::i()->m OR \IPS\Request::i()->m == $this->_today->mon ) )
{
$day = $this->_today->mday;
}
try
{
$date = \IPS\calendar\Date::getDate( \IPS\Request::i()->y ?: NULL, \IPS\Request::i()->m ?: NULL, $day );
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ),
\IPS\calendar\Date::getDate( $date->lastDayOfMonth('year'), $date->lastDayOfMonth('mon'), $date->lastDayOfMonth('mday'), 23, 59, 59 ),
NULL,
NULL,
FALSE,
NULL,
NULL,
FALSE
);
}
catch( \InvalidArgumentException $e )
{
\IPS\Output::i()->error( 'error_bad_date', '', 403, '' ); //@todo
}
/* Sort */
$startDate = \IPS\calendar\Date::getDate();
@usort( $events, function( $a, $b ) use ( $startDate )
{
if( $a->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return -1;
}
if( $b->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return 1;
}
if ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() == $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() )
{
return 0;
}
return ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() < $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() ) ? -1 : 1;
} );
/* Pagination */
$offset = isset( \IPS\Request::i()->offset ) ? min( array( \IPS\Request::i()->offset, \count( $events ) ) ) : 0;
/* If there are no events, tell search engines not to index the page but do NOT tell them not to follow links */
if( \count( $events ) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
else
{
$events = \array_slice( $events, $offset, $this->streamPerPage );
}
/* Return events if we're after those specifically */
if( \IPS\Request::i()->isAjax() && \IPS\Request::i()->get == 'byMonth' )
{
$eventHtml = "";
if( \count( $events ) )
{
foreach( $events as $idx => $event )
{
$eventHtml .= \IPS\Theme::i()->getTemplate( 'events', 'calendar' )->event( $event );
}
}
else
{
$eventHtml = \IPS\Theme::i()->getTemplate( 'events', 'calendar' )->noEvents();
}
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $eventHtml );
$toReturn = array(
'count' => \count( $events ),
'html' => $eventHtml
);
\IPS\Output::i()->sendOutput( json_encode( $toReturn ), 200, 'application/json' );
return;
}
/* Non-existent page */
if( $offset > 0 && !\count( $events ) )
{
\IPS\Output::i()->error( 'no_events_month', '2L182/B', 404, '' );
}
/* Clone date so we can update time without affecting other areas on this page */
$startTime = clone $date;
$endTime = clone $date;
$startTime->setTime(0,0,0);
$endTime->setTime(23,59,59);
/* Online */
$online = \IPS\calendar\Event::retrieveEvents(
$startTime,
NULL,
NULL,
NULL,
FALSE,
NULL,
NULL,
FALSE,
NULL,
TRUE
);
/* Build an array of month objects for the nav */
$months = new \DatePeriod( (new \DateTime)->setDate( date('Y'), date('m'), 1 ), new \DateInterval( 'P1M' ), 11 );
$stream = \IPS\Theme::i()->getTemplate( 'overview', 'calendar' )->byMonth( $calendars, $date, $featured, $events, NULL, $months );
$form = $this->getForm();
$date = \IPS\calendar\Date::getDate();
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $stream, 200, 'text/html' );
}
else
{
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_overview.js', 'calendar', 'front' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( '__app_calendar' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'overview' )->wrapper( $featured, $nearme, $stream, $form, $mapMarkers, $online, $date );
}
}
/**
* Build search form
*
* @return \IPS\Helpers\Form
*/
public function getForm()
{
/* Search form */
$form = new \IPS\Helpers\Form('form', 'search', \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=view&do=search' ) );
if ( \IPS\GeoLocation::enabled() )
{
$form->add( new \IPS\Helpers\Form\Text( 'location', FALSE, \IPS\Request::i()->location, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack( 'events_search_search_location') ) ) );
}
$form->add( new \IPS\Helpers\Form\DateRange( 'date', array( 'start' => NULL, 'end' => NULL ), FALSE, array() ) );
$form->add( new \IPS\Helpers\Form\Select( 'show', 'all', FALSE, array( 'options' => array('all' => \IPS\Member::loggedIn()->language()->addToStack( 'all_events' ), 'online' => \IPS\Member::loggedIn()->language()->addToStack( 'online_events' ), 'physical' => \IPS\Member::loggedIn()->language()->addToStack( 'physical_events' ) ) ) ) );
return $form;
}
/**
* Search
*
* @return void
*/
protected function search()
{
\IPS\Output::i()->bypassCsrfKeyCheck = TRUE;
$results = array();
/* Build the search form */
$form = $this->getForm();
if( $values = $form->values() )
{
$select = "calendar_events.*, core_clubs.name";
$sort = 'event_start_date asc';
$location = NULL;
$having = array();
$where = array();
$where[] = array( 'event_approved=?', 1 );
$searchNearLocation = FALSE; // Should results be limited to near the provided location only? If not, we'll just use location to allow sorting.
if( isset( \IPS\Request::i()->searchNearLocation ) && \IPS\Request::i()->searchNearLocation )
{
$searchNearLocation = TRUE;
}
if( \IPS\GeoLocation::enabled() )
{
if( \IPS\Request::i()->location )
{
/* Is it a location? */
$locations = static::geocodeLocation( \IPS\Request::i()->location, FALSE );
if( \is_array( $locations ) and \count( $locations ) )
{
if( $locations[0]['value'] )
{
$having[] = "( event_title LIKE CONCAT( '%', '" . $locations[0]['value'] . "', '%' ) OR name LIKE CONCAT( '%', '" . $locations[0]['value'] . "', '%' ) )";
}
$location = array( 'lat' => $locations[0]['lat'], 'lon' => $locations[0]['long'] );
$searchNearLocation = TRUE;
}
else
{
$having[] = "( event_title LIKE CONCAT( '%', '" . \IPS\Request::i()->location . "', '%' ) OR name LIKE CONCAT( '%', '" . \IPS\Request::i()->location . "', '%' ) )";
}
}
else if ( isset( \IPS\Request::i()->lat ) and isset( \IPS\Request::i()->lon ) and \IPS\Request::i()->lat !== 0 and \IPS\Request::i()->lon !== 0 )
{
$location = array( 'lat' => \IPS\Request::i()->lat, 'lon' => \IPS\Request::i()->lon );
$searchNearLocation = TRUE;
}
elseif( $searchNearLocation )
{
/* Do an IP lookup */
try
{
$geo = \IPS\GeoLocation::getByIp( \IPS\Request::i()->ipAddress() );
$location = array( 'lat' => $geo->lat, 'lon' => $geo->long );
}
catch ( \Exception $e )
{
$location = array( 'lat' => \IPS\Settings::i()->map_center_lat, 'lon' => \IPS\Settings::i()->map_center_lon );
}
}
if ( \is_array( $location ) and isset( $location['lat'] ) and isset( $location['lon'] ) and is_numeric( $location['lat'] ) and is_numeric( $location['lon'] ) )
{
$select = $select . ', ( 3959 * acos( cos( radians(' . $location['lat'] . ') ) * cos( radians( event_latitude ) ) * cos( radians( event_longitude ) - radians(' . $location['lon'] . ') ) + sin( radians(' . $location['lat'] . ') ) * sin(radians(event_latitude)) ) ) AS distance';
if( $searchNearLocation )
{
$having[] = 'distance < 500';
}
}
}
$sort = 'event_start_date asc';
if( isset( \IPS\Request::i()->sortBy ) && \IPS\Request::i()->sortBy == 'nearest' && $location )
{
$sort = 'distance asc';
}
/* Filter? */
if( isset( \IPS\Request::i()->show ) && \IPS\Request::i()->show !== 'all' )
{
if( \IPS\Request::i()->show == 'online' )
{
$where[] = array( '( event_online = 1 )' );
}
else {
$where[] = array( '( ( event_end_date IS NULL OR TIMESTAMPDIFF( DAY, event_start_date, event_end_date ) < ? ) AND event_online = 0)', 30 );
}
}
$today = new \IPS\calendar\Date;
$member = \IPS\Member::loggedIn();
$startDate = \IPS\calendar\Date::dateTimeToCalendarDate( $values['date']['start'] ?: $today );
$endDate = $values['date']['end'] ? \IPS\calendar\Date::dateTimeToCalendarDate( $values['date']['end'] ) : NULL;
/* Get timezone adjusted versions of start/end time */
$startDateTimezone = \IPS\calendar\Date::parseTime( $startDate->mysqlDatetime(), TRUE );
$endDateTimezone = ( $endDate !== NULL ) ? \IPS\calendar\Date::parseTime( $endDate->mysqlDatetime() ) : NULL;
if ( $member->timezone )
{
$startDateTimezone->setTimezone( new \DateTimeZone( 'UTC' ) );
if( $endDateTimezone !== NULL )
{
$endDateTimezone->setTimezone( new \DateTimeZone( 'UTC' ) );
}
}
if( $endDate !== NULL AND $startDate == $endDate )
{
$where[] = array(
'(
( event_end_date IS NULL AND DATE( event_start_date ) = ? AND event_all_day=1 )
OR
( event_end_date IS NOT NULL AND DATE( event_start_date ) <= ? AND DATE( event_end_date ) >= ? AND event_all_day=1 )
OR
( event_end_date IS NULL AND event_start_date >= ? AND event_start_date <= ? AND event_all_day=0 )
OR
( event_end_date IS NOT NULL AND event_start_date <= ? AND event_end_date >= ? AND event_all_day=0 )
)',
$startDate->mysqlDatetime( FALSE ),
$endDate->mysqlDatetime( FALSE ),
$startDate->mysqlDatetime( FALSE ),
$startDateTimezone->mysqlDatetime(),
$startDateTimezone->adjust('+1 day')->mysqlDatetime(),
$endDateTimezone->adjust('+1 day')->mysqlDatetime(),
$startDateTimezone->mysqlDatetime()
);
}
elseif( $endDate !== NULL )
{
$where[] = array(
'(
( event_end_date IS NULL AND DATE( event_start_date ) >= ? AND DATE( event_start_date ) <= ? AND event_all_day=1 )
OR
( event_end_date IS NOT NULL AND DATE( event_start_date ) <= ? AND DATE( event_end_date ) >= ? AND event_all_day=1 )
OR
( event_end_date IS NULL AND event_start_date >= ? AND event_start_date <= ? AND event_all_day=0 )
OR
( event_end_date IS NOT NULL AND event_start_date <= ? AND event_end_date >= ? AND event_all_day=0 )
)',
$startDate->mysqlDatetime( FALSE ),
$endDate->mysqlDatetime( FALSE ),
$endDate->mysqlDatetime( FALSE ),
$startDate->mysqlDatetime( FALSE ),
$startDateTimezone->mysqlDatetime(),
$endDateTimezone->mysqlDatetime(),
$endDateTimezone->mysqlDatetime(),
$startDateTimezone->mysqlDatetime()
);
}
else
{
$where[] = array(
"(
( DATE( event_start_date ) >= ? AND event_all_day=1 )
OR
( event_start_date >= ? AND event_all_day=0 )
OR
( event_end_date IS NOT NULL AND DATE( event_start_date ) <= ? AND DATE( event_end_date ) >= ? AND event_all_day=1 )
OR
( event_end_date IS NOT NULL AND event_start_date <= ? AND event_end_date >= ? AND event_all_day=0 )
)",
$startDate->mysqlDatetime( FALSE ),
$startDateTimezone->mysqlDatetime(),
$startDate->mysqlDatetime( FALSE ),
$startDate->mysqlDatetime( FALSE ),
$startDateTimezone->adjust('+1 day')->mysqlDatetime(),
$startDateTimezone->mysqlDatetime()
);
}
$offset = isset( \IPS\Request::i()->offset ) ? \intval( \IPS\Request::i()->offset ) : 0;
$limit = isset( \IPS\Request::i()->limit ) ? min( array( \intval( \IPS\Request::i()->limit ), 50 ) ) : 20;
$query = \IPS\Db::i()->select( $select, 'calendar_events', $where, $sort, array( $offset, $limit ), NULL, implode( " OR ", $having ) );
$query->join( 'calendar_calendars', "event_calendar_id = cal_id" );
$query->join( 'core_clubs', "cal_club_id = id" );
$results = new \IPS\Patterns\ActiveRecordIterator( $query, '\IPS\calendar\Event' );
}
$mapMarkers = array();
foreach ( $results as $event )
{
if( $event->latitude and $event->longitude )
{
$mapMarkers[ $event->id ] = array( 'lat' => (float) $event->latitude, 'long' => (float) $event->longitude , 'title' => $event->title );
}
}
if( \IPS\Request::i()->isAjax() ){
$countQuery = \IPS\Db::i()->select( $select, 'calendar_events', $where, NULL, array(), NULL, implode( " OR ", $having ) );
$countQuery->join( 'calendar_calendars', "event_calendar_id = cal_id" );
$countQuery->join( 'core_clubs', "cal_club_id = id" );
$output = \IPS\Theme::i()->getTemplate( 'events' )->searchResults( $results );
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
$toReturn = array(
'totalCount' => $countQuery->count(),
'count' => \count( $results ),
'content' => $output,
'markers' => $mapMarkers,
'blurb' => '', // @todo
'online' => ( \IPS\Request::i()->show == 'online' )
);
\IPS\Output::i()->sendOutput( json_encode( $toReturn ), 200, 'application/json' );
return;
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( '__app_calendar' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'overview' )->search( $form, $results, json_encode( $mapMarkers ) );
}
/**
* Geocode Location
*
* @param string $input Location search term
* @param bool $asJson Return type
* @return array|string
*/
public static function geocodeLocation( $input = NULL, $asJson = TRUE )
{
$items = array();
try
{
$geolocation = \IPS\GeoLocation::geocodeLocation( $input );
if( $geolocation instanceof \IPS\GeoLocation )
{
$items[] = array(
'value' => $geolocation->placeName,
'html' => $geolocation->placeName,
'lat' => $geolocation->lat,
'long' => $geolocation->long
);
}
}
catch( \BadFunctionCallException ){}
if( $asJson )
{
\IPS\Output::i()->json( $items );
}
else
{
return $items;
}
}
}