Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+16 -2
View File
@@ -24,7 +24,7 @@ class _Application extends \IPS\Application
public function init()
{
/* Requesting iCal/RSS Subscription, but guests are required to login */
if( \IPS\Request::i()->module == 'calendar' and \IPS\Request::i()->controller == 'view' and in_array( \IPS\Request::i()->do, array( 'rss', 'download' ) ) )
if( \IPS\Request::i()->module == 'calendar' and \IPS\Request::i()->controller == 'view' and \in_array( \IPS\Request::i()->do, array( 'rss', 'download' ) ) )
{
/* Validate RSS/Download key */
if( \IPS\Request::i()->member )
@@ -66,6 +66,7 @@ class _Application extends \IPS\Application
/**
* Latest events RSS
*
* @param \IPS\Member|NULL $member Member to generate feed for
* @return void
* @note There is a hard limit of the most recent 500 events updated
*/
@@ -116,6 +117,7 @@ class _Application extends \IPS\Application
/**
* Latest events RSS
*
* @param \IPS\Member|NULL $member Member to generate feed for
* @return void
*/
public function rss( $member=NULL )
@@ -150,7 +152,7 @@ class _Application extends \IPS\Application
}
/* @note application/rss+xml is not a registered IANA mime-type so we need to stick with text/xml for RSS */
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml' );
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml', array(), TRUE );
}
/**
@@ -185,4 +187,16 @@ class _Application extends \IPS\Application
'activityTabs' => array()
);
}
/**
* Return an array of specific links to add to the sitemap
*
* @return array
*/
public function sitemapLinks()
{
return array(
\IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=view', 'front', 'calendar' ),
);
}
}
+14 -9
View File
@@ -12,7 +12,7 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -32,6 +32,7 @@ class _calendars extends \IPS\Node\Api\NodeController
* GET /calendar/calendars
* Get list of calendars
*
* @apiparam int clubs 0|1 Include club calendars, default: 1
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @note For requests using an OAuth Access Token for a particular member, only calendars the authorized user can view will be included
@@ -75,10 +76,17 @@ class _calendars extends \IPS\Node\Api\NodeController
* @apiparam int approve_comments 0|1 Comments must be approved
* @apiparam int allow_reviews 0|1 Allow reviews
* @apiparam int approve_reviews 0|1 Reviews must be approved
* @apiparam object permissions An object with the keys as permission options (view, read, add, reply, review, askrsvp, rsvp) and values as permissions to use (which may be * to grant access to all groups, or an array of group IDs to permit access to)
* @return \IPS\calendar\Calendar
* @throws 1L364/2 NO_TITLE A title for the calendar must be supplied
*/
public function POSTindex()
{
if ( !\IPS\Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1L364/2', 400 );
}
return new \IPS\Api\Response( 201, $this->_create()->apiOutput( $this->member ) );
}
@@ -94,6 +102,8 @@ class _calendars extends \IPS\Node\Api\NodeController
* @apiparam int approve_comments 0|1 Comments must be approved
* @apiparam int allow_reviews 0|1 Allow reviews
* @apiparam int approve_reviews 0|1 Reviews must be approved
* @apiparam object permissions An object with the keys as permission options (view, read, add, reply, review, askrsvp, rsvp) and values as permissions to use (which may be * to grant access to all groups, or an array of group IDs to permit access to)
* @param int $id ID Number
* @return \IPS\calendar\Calendar
*/
public function POSTitem( $id )
@@ -101,7 +111,7 @@ class _calendars extends \IPS\Node\Api\NodeController
$class = $this->class;
$calendar = $class::load( $id );
return new \IPS\Api\Response( 201, $this->_createOrUpdate( $calendar )->apiOutput( $this->member ) );
return new \IPS\Api\Response( 200, $this->_createOrUpdate( $calendar )->apiOutput( $this->member ) );
}
/**
@@ -120,17 +130,12 @@ class _calendars extends \IPS\Node\Api\NodeController
/**
* Create or update node
*
* @param \IPS\node\Model $node The node
* @param \IPS\node\Model $calendar The node
* @return \IPS\node\Model
*/
protected function _createOrUpdate( \IPS\node\Model $calendar )
{
if ( !\IPS\Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '', 400 );
}
if ( isset( \IPS\Request::i()->title ) )
if ( \IPS\Request::i()->title )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_calendar_' . $calendar->id, \IPS\Request::i()->title );
$calendar->title_seo = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->title );
+3 -3
View File
@@ -12,7 +12,7 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -83,7 +83,7 @@ class _comments extends \IPS\Content\Api\CommentController
* POST /calendar/comments
* Create a comment
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @reqapiparam int event The ID number of the event the comment is for
* @reqapiparam int author The ID number of the member making the comment (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
* @apiparam string author_name If author is 0, the guest name that should be used
@@ -149,7 +149,7 @@ class _comments extends \IPS\Content\Api\CommentController
* POST /calendar/comments/{id}
* Edit a comment
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @param int $id ID Number
* @apiparam int author The ID number of the member making the comment (0 for guest). Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam string author_name If author is 0, the guest name that should be used
+66 -9
View File
@@ -12,7 +12,7 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -38,19 +38,76 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam int locked If 1, only events which are locked are returned, if 0 only unlocked
* @apiparam int hidden If 1, only events which are hidden are returned, if 0 only not hidden
* @apiparam int featured If 1, only events which are featured are returned, if 0 only not featured
* @apiparam string sortBy What to sort by. Can be 'date' for creation date, 'title' or leave unspecified for ID
* @apiparam string rangeStart YYYY-MM-DD. Only events occurring on or after this date will be returned.
* @apiparam string rangeEnd YYYY-MM-DD. Only events occurring on or before this date will be returned.
* @apiparam string sortBy What to sort by. Can be 'date' for creation date, 'start' for event start date, 'end' for event end date, 'title' or leave unspecified for ID
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event>
* @throws 1L296/M INVALID_DATE The rangeStart and/or rangeEnd value was not a valid date in YYYY-MM-DD format
*/
public function GETindex()
{
/* Where clause */
$where = array();
/* Are we limiting to a date range? */
if( isset( \IPS\Request::i()->rangeStart ) OR isset( \IPS\Request::i()->rangeEnd ) )
{
$startDate = $endDate = NULL;
foreach( array( 'start', 'end' ) as $limiter )
{
$inputKey = 'range' . mb_ucfirst( $limiter );
if( \IPS\Request::i()->$inputKey )
{
$datePieces = explode( '-', \IPS\Request::i()->$inputKey );
/* Let's make sure the date is valid... */
if( @checkdate( $datePieces[1], $datePieces[2], $datePieces[0] ) )
{
if( $limiter === 'start' )
{
$startDate = \IPS\calendar\Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2] );
}
else
{
$endDate = \IPS\calendar\Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2], 23, 59, 59 );
}
}
else
{
throw new \IPS\Api\Exception( 'INVALID_DATE', '1L296/M', 403 );
}
}
}
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents( $startDate, $endDate, NULL, NULL, FALSE, new \IPS\Member, NULL, TRUE );
if( !\count( $events ) )
{
/* Force no results */
$where[] = array( '0=1' );
}
else
{
$where[] = array( 'event_id IN(' . implode( ',', array_map( function( $event ) { return $event->id; }, $events ) ) . ')' );
}
}
/* Sort by */
$sortBy = NULL;
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'start', 'end' ) ) )
{
$sortBy = 'event_' . \IPS\Request::i()->sortBy . '_date';
}
/* Return */
return $this->_list( $where, 'calendars' );
return $this->_list( $where, 'calendars', FALSE, $sortBy );
}
/**
@@ -77,7 +134,7 @@ class _events extends \IPS\Content\Api\ItemController
* POST /calendar/events
* Create an event
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authentictaed user has permission to lock events).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authenticated user has permission to lock events).
* @reqapiparam int calendar The ID number of the calendar the event should be created in
* @apiparam int author The ID number of the member creating the event (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
* @reqapiparam string title The event title
@@ -180,7 +237,7 @@ class _events extends \IPS\Content\Api\ItemController
* POST /calendar/events/{id}
* Edit an event
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authentictaed user has permission to lock topics).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authenticated user has permission to lock topics).
* @reqapiparam int calendar The ID number of the calendar the event should be created in
* @reqapiparam int author The ID number of the member creating the event (0 for guest). Ignored for requests using an OAuth Access Token for a particular member.
* @reqapiparam string title The event title
@@ -193,11 +250,11 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam \IPS\GeoLocation location The location where the event is taking place
* @apiparam string prefix Prefix tag
* @apiparam string tags Comma-separated list of tags (do not include prefix)
* @apiparam datetime date The date/time that should be used for the event/post post date. If not provided, will use the current date/time. Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam string ip_address The IP address that should be stored for the event/post. If not provided, will use the IP address from the API request. Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam int locked 1/0 indicating if the event should be locked
* @apiparam int hidden 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
* @apiparam int featured 1/0 indicating if the event should be featured
* @param int $id ID Number
* @throws 1L296/I INVALID_ID The event ID is invalid or the authorized user does not have permission to view it
* @throws 1L296/D NO_CALENDAR The calendar ID does not exist or the authorized user does not have permission to post in it
* @throws 1L296/E NO_AUTHOR The author ID does not exist
@@ -397,7 +454,7 @@ class _events extends \IPS\Content\Api\ItemController
*/
public function PUTitem_rsvps( $id, $memberId )
{
if ( !isset( \IPS\Request::i()->response ) or !in_array( (int) \IPS\Request::i()->response, range( 0, 2 ) ) )
if ( !isset( \IPS\Request::i()->response ) or !\in_array( (int) \IPS\Request::i()->response, range( 0, 2 ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RESPONSE', '1L296/L', 400 );
}
@@ -458,7 +515,7 @@ class _events extends \IPS\Content\Api\ItemController
throw new \IPS\Api\Exception( 'INVALID_MEMBER', '2L296/K', 404 );
}
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', intval( $id ), intval( $memberId ) ) );
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', \intval( $id ), \intval( $memberId ) ) );
return new \IPS\Api\Response( 200, NULL );
}
@@ -502,7 +559,7 @@ class _events extends \IPS\Content\Api\ItemController
/* RSVP */
if ( isset( \IPS\Request::i()->rsvp ) and ( !$this->member or $item->container()->can( 'askrsvp', $this->member ) ) )
{
$item->rsvp = intval( \IPS\Request::i()->rsvp );
$item->rsvp = \intval( \IPS\Request::i()->rsvp );
if ( $item->rsvp and isset( \IPS\Request::i()->rsvpLimit ) and \IPS\Request::i()->rsvpLimit )
{
$item->rsvp_limit = \IPS\Request::i()->rsvpLimit;
Whitespace-only changes.
+5 -5
View File
@@ -12,7 +12,7 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -83,7 +83,7 @@ class _reviews extends \IPS\Content\Api\CommentController
* POST /calendar/reviews
* Create a review
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @reqapiparam int event The ID number of the event the review is for
* @reqapiparam int author The ID number of the member making the review (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
* @apiparam string author_name If author is 0, the guest name that should be used
@@ -144,7 +144,7 @@ class _reviews extends \IPS\Content\Api\CommentController
}
/* Check we have a rating */
if ( !\IPS\Request::i()->rating or !in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
if ( !\IPS\Request::i()->rating or !\in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RATING', '1L298/8', 403 );
}
@@ -157,7 +157,7 @@ class _reviews extends \IPS\Content\Api\CommentController
* POST /calendar/reviews/{id}
* Edit a review
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @param int $id ID Number
* @apiparam int author The ID number of the member making the review (0 for guest). Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam string author_name If author is 0, the guest name that should be used
@@ -186,7 +186,7 @@ class _reviews extends \IPS\Content\Api\CommentController
}
/* Check */
if ( isset( \IPS\Request::i()->rating ) and !in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
if ( isset( \IPS\Request::i()->rating ) and !\in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RATING', '1L298/9', 403 );
}
+191
View File
@@ -0,0 +1,191 @@
<?php
/**
* @brief Calendar Venues API
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Calendar
* @since 5 June 2018
*/
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* @brief Calendar Venues API
*/
class _venues extends \IPS\Node\Api\NodeController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Venue';
/**
* GET /calendar/venues
* Get list of venues
*
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Venue>
*/
public function GETindex()
{
/* Return */
return $this->_list();
}
/**
* GET /calendar/venues/{id}
* Get specific venue
*
* @param int $id ID Number
* @throws 1L384/1 INVALID_ID The venue does not exist
* @return \IPS\calendar\Venue
*/
public function GETitem( $id )
{
try
{
return $this->_view( $id );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '1L384/1', 404 );
}
}
/**
* POST /calendar/venues
* Create a venue
*
* @apiclientonly
* @reqapiparam string title The venue title
* @reqapiparam \IPS\GeoLocation address The venue address (latitude and longitude do not need to be supplied and will be ignored)
* @apiparam string description The venue description
* @return \IPS\calendar\Venue
* @throws 1L384/2 NO_ADDRESS An address is required for the venue but was not supplied
* @throws 1L384/3 INVALID_ADDRESS An invalid address was supplied
* @throws 1L384/4 NO_TITLE No title was supplied for the venue
*/
public function POSTindex()
{
if( !\IPS\Request::i()->address OR !\is_array( \IPS\Request::i()->address ) )
{
throw new \IPS\Api\Exception( 'NO_ADDRESS', '1L384/2', 400 );
}
else
{
/* Just check before we try to save */
$this->_getGeoLocationObject();
}
if ( !\IPS\Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1L384/4', 400 );
}
return new \IPS\Api\Response( 201, $this->_create()->apiOutput( $this->member ) );
}
/**
* POST /calendar/venues/{id}
* Edit a venue
*
* @apiclientonly
* @reqapiparam string title The venue title
* @reqapiparam \IPS\GeoLocation address The venue address (latitude and longitude do not need to be supplied and will be ignored)
* @apiparam string description The venue description
* @param int $id ID Number
* @return \IPS\calendar\Venue
* @throws 1L384/2 NO_ADDRESS An address is required for the venue but was not supplied
* @throws 1L384/3 INVALID_ADDRESS An invalid address was supplied
* @throws 1L384/4 NO_TITLE No title was supplied for the venue
*/
public function POSTitem( $id )
{
$class = $this->class;
$venue = $class::load( $id );
return new \IPS\Api\Response( 200, $this->_createOrUpdate( $venue )->apiOutput( $this->member ) );
}
/**
* DELETE /calendar/venues/{id}
* Delete a venue
*
* @apiclientonly
* @param int $id ID Number
* @return void
*/
public function DELETEitem( $id )
{
return $this->_delete( $id );
}
/**
* Create or update node
*
* @param \IPS\node\Model $venue The node
* @return \IPS\node\Model
*/
protected function _createOrUpdate( \IPS\node\Model $venue )
{
if( \IPS\Request::i()->address AND \is_array( \IPS\Request::i()->address ) )
{
$geoLocation = $this->_getGeoLocationObject();
$venue->address = json_encode( $geoLocation );
}
if ( isset( \IPS\Request::i()->title ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id, \IPS\Request::i()->title );
$venue->title_seo = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->title );
}
if( isset( \IPS\Request::i()->description ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id .'_desc', \IPS\Request::i()->description );
}
return parent::_createOrUpdate( $venue );
}
/**
* Get geolocation object
*
* @return array
*/
protected function _getGeoLocationObject()
{
$geoLocation = new \IPS\GeoLocation;
$geoLocation->addressLines = array();
foreach( \IPS\Request::i()->address as $k => $v )
{
if( \in_array( $k, array( 'city', 'postalCode', 'region', 'addressLines', 'country' ) ) )
{
$geoLocation->$k = $v;
}
}
try
{
$geoLocation->getLatLong();
}
catch( \BadMethodCallException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ADDRESS', '1L384/3', 400 );
}
return $geoLocation;
}
}
+53
View File
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<build>
<module key="admin/calendars"><![CDATA[{"default_controller":null,"protected":0,"default":1}]]></module>
<module key="admin/venues"><![CDATA[{"default_controller":"","protected":0,"default":0}]]></module>
<module key="front/calendar"><![CDATA[{"default_controller":"view","protected":0,"default":1}]]></module>
<task frequency="P0Y0M0DT4H0M0S">icalendar</task>
<task frequency="P0Y0M0DT1H0M0S">eventreminders</task>
<setting key="all_activity_calendar_streamitems"><![CDATA[{"key":"all_activity_calendar_streamitems","default":"1","report":"full"}]]></setting>
<setting key="calendar_block_past_changes"><![CDATA[{"key":"calendar_block_past_changes","default":"0","report":"full"}]]></setting>
<setting key="calendar_date_format"><![CDATA[{"key":"calendar_date_format","default":"d_lm_y","report":"full"}]]></setting>
<setting key="calendar_date_format_custom"><![CDATA[{"key":"calendar_date_format_custom","default":"","report":"bool"}]]></setting>
<setting key="calendar_default_view"><![CDATA[{"key":"calendar_default_view","default":"month","report":"full"}]]></setting>
<setting key="calendar_rss_feed"><![CDATA[{"key":"calendar_rss_feed","default":"1","report":"full"}]]></setting>
<setting key="calendar_rss_feed_days"><![CDATA[{"key":"calendar_rss_feed_days","default":"30","report":"full"}]]></setting>
<setting key="calendar_rss_feed_order"><![CDATA[{"key":"calendar_rss_feed_order","default":"0","report":"full"}]]></setting>
<setting key="calendar_venues_enabled"><![CDATA[{"key":"calendar_venues_enabled","default":"0","report":"full"}]]></setting>
<setting key="ipb_calendar_mon"><![CDATA[{"key":"ipb_calendar_mon","default":"0","report":"full"}]]></setting>
<setting key="show_bday_calendar"><![CDATA[{"key":"show_bday_calendar","default":"1","report":"full"}]]></setting>
<widget key="todaysBirthdays"><![CDATA[{"class":"\\IPS\\Widget\\StaticCache","restrict":[],"default_area":"","allow_reuse":false,"menu_style":"menu","embeddable":true}]]></widget>
<widget key="upcomingEvents"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":["sidebar","cms"],"default_area":"","allow_reuse":true,"menu_style":"menu","embeddable":true}]]></widget>
<widget key="recentReviews"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":[],"default_area":"","allow_reuse":false,"menu_style":"menu","embeddable":true}]]></widget>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars"><![CDATA[{"lang_key":"menu__calendar_calendars_calendars","restriction":"calendars_manage","keywords":["calendars"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;do=form"><![CDATA[{"lang_key":"menu__calendar_calendars_calendars","restriction":"calendars_manage","keywords":["edit calendar"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;do=permissions"><![CDATA[{"lang_key":"menu__calendar_calendars_calendars","restriction":"calendars_manage","keywords":["calendar permissions"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=cal_comment_moderate"><![CDATA[{"lang_key":"cal_comment_moderate","restriction":"calendars_manage","keywords":["approved","comments must be approved","require approval"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_1_cal_allow_comments"><![CDATA[{"lang_key":"cal_allow_comments","restriction":"calendars_manage","keywords":["allow comments","comments"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_1_cal_allow_reviews"><![CDATA[{"lang_key":"cal_allow_reviews","restriction":"calendars_manage","keywords":["allow reviews","reviews"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_1_cal_color"><![CDATA[{"lang_key":"cal_color","restriction":"calendars_manage","keywords":["calendar color"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_1_cal_moderate"><![CDATA[{"lang_key":"cal_moderate","restriction":"calendars_manage","keywords":["approve","approve event","event"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_1_cal_title"><![CDATA[{"lang_key":"cal_title","restriction":"calendars_manage","keywords":["calendar name","calendar title"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_new_cal_allow_comments"><![CDATA[{"lang_key":"cal_allow_comments","restriction":"calendars_manage","keywords":["allow comments"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_new_cal_allow_reviews"><![CDATA[{"lang_key":"cal_allow_reviews","restriction":"calendars_manage","keywords":["allow reviews","reviews"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_new_cal_color"><![CDATA[{"lang_key":"cal_color","restriction":"calendars_manage","keywords":["calendar color"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_new_cal_moderate"><![CDATA[{"lang_key":"cal_moderate","restriction":"calendars_manage","keywords":["approve event","event approve","events"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=calendars&amp;searchResult=form_new_cal_title"><![CDATA[{"lang_key":"cal_title","restriction":"calendars_manage","keywords":["calendar title"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical"><![CDATA[{"lang_key":"menu__calendar_calendars_ical","restriction":"calendar_feeds_manage","keywords":["calendar export","feeds","iCal","iCalendar"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=add&amp;searchResult=form_feed_allow_rsvp"><![CDATA[{"lang_key":"feed_allow_rsvp","restriction":"calendar_feeds_manage","keywords":["enable rsvp","rsvp"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=add&amp;searchResult=form_feed_calendar_id"><![CDATA[{"lang_key":"feed_calendar_id","restriction":"calendar_feeds_manage","keywords":["calendar"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=add&amp;searchResult=form_feed_member_id"><![CDATA[{"lang_key":"feed_member_id","restriction":"calendar_feeds_manage","keywords":["member"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=add&amp;searchResult=form_feed_title"><![CDATA[{"lang_key":"feed_title","restriction":"calendar_feeds_manage","keywords":["add icalendar","feed title","iCalendar feed"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=add&amp;searchResult=form_feed_url"><![CDATA[{"lang_key":"feed_url","restriction":"calendar_feeds_manage","keywords":["feed url","icalendar url"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=upload&amp;searchResult=form_feed_calendar_id"><![CDATA[{"lang_key":"feed_calendar_id","restriction":"calendar_feeds_manage","keywords":["calendar"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=upload&amp;searchResult=form_feed_file"><![CDATA[{"lang_key":"feed_file","restriction":"calendar_feeds_manage","keywords":["iCalendar file"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=ical&amp;do=upload&amp;searchResult=form_feed_member_id"><![CDATA[{"lang_key":"feed_member_id","restriction":"calendar_feeds_manage","keywords":["member"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings"><![CDATA[{"lang_key":"menu__calendar_calendars_settings","restriction":"settings_manage","keywords":["calendar settings"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=calendar_rss_feed_days"><![CDATA[{"lang_key":"calendar_rss_feed_days","restriction":"settings_manage","keywords":["days","feed days","forthcoming days","number of days","RSS Feed"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_calendar_date_format"><![CDATA[{"lang_key":"calendar_date_format","restriction":"settings_manage","keywords":["calendar date format"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_calendar_default_view"><![CDATA[{"lang_key":"calendar_default_view","restriction":"settings_manage","keywords":["calendar layout"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_calendar_rss_feed"><![CDATA[{"lang_key":"calendar_rss_feed","restriction":"settings_manage","keywords":["calendar rss","events rss"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_calendar_venues_enabled"><![CDATA[{"lang_key":"calendar_venues_enabled","restriction":"settings_manage","keywords":["address","venue","venues"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_ipb_calendar_mon"><![CDATA[{"lang_key":"ipb_calendar_mon","restriction":"settings_manage","keywords":["calendar start","monday","sunday"]}]]></acpsearch>
<acpsearch key="app=calendar&amp;module=calendars&amp;controller=settings&amp;searchResult=form_show_bday_calendar"><![CDATA[{"lang_key":"show_bday_calendar","restriction":"settings_manage","keywords":["birthdays"]}]]></acpsearch>
</build>
+15 -50
View File
@@ -28,7 +28,7 @@
<table width='100%' cellpadding='5' cellspacing='0' border='0'>
<tr>
<td dir='{dir}' style="font-family: 'Helvetica Neue', helvetica, sans-serif; line-height: 1.5; font-size: 14px; color: #8d8d8d">
{$email->language->addToStack("email_posted_in", FALSE, array( 'sprintf' => array( $content->container()->_title ) ) )}
{$email->language->addToStack("email_posted_in", FALSE, array( 'sprintf' => array( $content->container()->getTitleForLanguage( $email->language ) ) ) )}
</td>
</tr>
<tr>
@@ -49,12 +49,12 @@
</tr>
</table>
<br /><br />
<em style='color: #8c8c8c'>&mdash; {setting="board_name"}</em>]]></template_content_html><template_data>$content, $daysToGo, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("email_event_reminder_plain", FALSE, array( 'sprintf' => array( $email->language->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $daysToGo ) ) ), $content->mapped('title') ) ) )}
<em style='color: #8c8c8c'>&mdash; {setting="board_name"}</em>]]></template_content_html><template_data>$content, $daysToGo, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("email_event_reminder_plain", FALSE, array( 'htmlsprintf' => array( $email->language->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $daysToGo ) ) ), $content->mapped('title') ) ) )}
{$email->language->addToStack("email_event_reminder_when", FALSE, array( 'sprintf' => array( $content->fixedDateTimeDescription( $email->language ) ) ) )}
{{if $content->location}}{$email->language->addToStack("email_event_reminder_where", FALSE, array( 'sprintf' => array( \IPS\GeoLocation::buildFromjson( $content->location )->toString() ) ) )}{{endif}}
{$email->language->addToStack("email_event_reminder_when", FALSE, array( 'htmlsprintf' => array( $content->fixedDateTimeDescription( $email->language ) ) ) )}
{{if $content->location}}{$email->language->addToStack("email_event_reminder_where", FALSE, array( 'htmlsprintf' => array( \IPS\GeoLocation::buildFromjson( $content->location )->toString() ) ) )}{{endif}}
{$email->language->addToStack("go_to_this_x", FALSE, array( 'sprintf' => array( mb_strtolower( $email->language->addToStack( $content::$title, FALSE ) ) ) ) )}: {$content->url()}
{$email->language->addToStack("go_to_this_x", FALSE, array( 'htmlsprintf' => array( mb_strtolower( $email->language->addToStack( $content::$title, FALSE ) ) ) ) )}: {$content->url()}
-- {setting="board_name"}]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>calendar</template_app><template_name>notification_new_content</template_name><template_content_html><![CDATA[
{{if $content->author()->member_id}}
@@ -66,46 +66,11 @@
<br />
<br />
<table width='100%' cellpadding='0' cellspacing='0' border='0'>
<tr>
<td dir='{dir}' width='40' valign='top' class='hidePhone' style='width: 0; max-height: 0; overflow: hidden; float: left;'>
<img src='{$content->author()->get_photo( true, true )}' width='40' height='40' style='border: 1px solid #777777; vertical-align: middle;'>
</td>
<td dir='{dir}' width='30' valign='top' class='hidePhone' style='width: 0; max-height: 0; overflow: hidden; float: left;'>
<br />
<span style='display: block; width: 0px; height: 0px; border-width: 15px; border-color: transparent #f9f9f9 transparent transparent; border-style: solid'></span>
</td>
<td dir='{dir}' valign='top' style='background: #f9f9f9;'>
<table width='100%' cellpadding='10' cellspacing='0' border='0'>
<tr>
<td dir='{dir}'>
<table width='100%' cellpadding='5' cellspacing='0' border='0'>
<tr>
<td dir='{dir}' style="font-family: 'Helvetica Neue', helvetica, sans-serif; line-height: 1.5; font-size: 14px; color: #8d8d8d">
{$email->language->addToStack("email_posted_in", FALSE, array( 'sprintf' => array( $content->container()->_title ) ) )}
</td>
</tr>
<tr>
<td dir='{dir}' style="font-family: 'Helvetica Neue', helvetica, sans-serif; line-height: 1.5; font-size: 14px;">
{$email->parseTextForEmail( $content->content(), $email->language )|raw}
</td>
</tr>
<tr>
<td dir='{dir}'>
<a href='{$content->url()}' style="color: #ffffff; font-family: 'Helvetica Neue', helvetica, sans-serif; text-decoration: none; font-size: 14px; background: {setting="email_color"}; line-height: 32px; padding: 0 10px; display: inline-block; border-radius: 3px;">{$email->language->addToStack("go_to_this_x", FALSE, array( 'sprintf' => array( mb_strtolower( $email->language->addToStack( $content::$title, FALSE ) ) ) ) )}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
{$content->emailContent( $email, 'html' )|raw}
<br /><br />
<em style='color: #8c8c8c'>&mdash; {setting="board_name"}</em>]]></template_content_html><template_data>$content, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("email_new_calevent_plain", FALSE, array( 'sprintf' => array( $content->author()->name, $content->indefiniteArticle( $email->language ), $content->mapped( 'title' ), $content->fixedDateTimeDescription( $email->language ) ) ) )}
<em style='color: #8c8c8c'>&mdash; {setting="board_name"}</em>]]></template_content_html><template_data>$content, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("email_new_calevent_plain", FALSE, array( 'htmlsprintf' => array( $content->author()->name, $content->indefiniteArticle( $email->language ), $content->mapped( 'title' ), $content->fixedDateTimeDescription( $email->language ) ) ) )}
{$email->language->addToStack("go_to_this_x", FALSE, array( 'sprintf' => array( mb_strtolower( $email->language->addToStack( $content::$title, FALSE ) ) ) ) )}: {$content->url()}
{$content->emailContent( $email, 'plaintext' )|raw}
-- {setting="board_name"}]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>calendar</template_app><template_name>digests__item</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
<td dir='{dir}' width='120' valign='top' align='center'>
@@ -130,7 +95,7 @@
</td>
<td dir='{dir}' align='left'>
<p style='font-family: "Helvetica Neue", helvetica, sans-serif; margin: 0; font-size: 13px; font-weight: bold'>
{$email->language->addToStack("x_created_event_in", FALSE, array( 'sprintf' => array( $event->author()->name, $event->container()->_title ) ) )}
{$email->language->addToStack("x_created_event_in", FALSE, array( 'sprintf' => array( $event->author()->name, $event->container()->getTitleForLanguage( $email->language ) ) ) )}
</p>
<h2 style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 18px; font-weight: 500 !important; margin: 0">
<a href='{$event->url()}' style='text-decoration: none;'>{$event->title}</a>
@@ -153,15 +118,15 @@
{{if $event->rsvp}}
<div style="font-size: 13px; font-family: 'Helvetica Neue', helvetica, sans-serif; margin-top: 10px">
{{if $attendees = $event->attendees()}}{{endif}}
<strong style="text-transform: uppercase; font-size: 12px; font-family: 'Helvetica Neue', helvetica, sans-serif;">{$email->language->addToStack("digest_users_going", FALSE, array( 'pluralize' => array( count( $attendees[1] ) ) ) )}</strong>
{{if count( $attendees[1] )}}
<strong style="text-transform: uppercase; font-size: 12px; font-family: 'Helvetica Neue', helvetica, sans-serif;">{$email->language->addToStack("digest_users_going", FALSE, array( 'pluralize' => array( \count( $attendees[1] ) ) ) )}</strong>
{{if \count( $attendees[1] )}}
{{foreach $attendees[1] as $idx => $attendee}}
{{if $idx < 10}}
<img src="{$attendee->get_photo( true, true )}" width="32" height="32" style="border: 1px solid #000; vertical-align: middle;">
{{endif}}
{{endforeach}}
{{if count( $attendees[1] ) > 10}}
&nbsp;&nbsp;&nbsp;<span style="font-size: 13px; font-family: 'Helvetica Neue', helvetica, sans-serif; color: #8c8c8c">{$email->language->addToStack("and_x_more", FALSE, array( 'pluralize' => array( count( $attendees[1] ) - 10 ) ) )}</span>
{{if \count( $attendees[1] ) > 10}}
&nbsp;&nbsp;&nbsp;<span style="font-size: 13px; font-family: 'Helvetica Neue', helvetica, sans-serif; color: #8c8c8c">{$email->language->addToStack("and_x_more", FALSE, array( 'pluralize' => array( \count( $attendees[1] ) - 10 ) ) )}</span>
{{endif}}
{{endif}}
</div>
@@ -180,7 +145,7 @@
</p>
{{endif}}
</td>
</tr>]]></template_content_html><template_data>$event, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_created_event_in", FALSE, array( 'sprintf' => array( $event->author()->name, $event->container()->_title ) ) )}: {$event->title} ({$event->url()})
</tr>]]></template_content_html><template_data>$event, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_created_event_in", FALSE, array( 'htmlsprintf' => array( $event->author()->name, $event->container()->getTitleForLanguage( $email->language ) ) ) )}: {$event->title} ({$event->url()})
]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>calendar</template_app><template_name>digests__comment</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
<td dir='{dir}' width='120' valign='top' align='center'>
<table width='120' cellpadding='10' cellspacing='0' border='0' bgcolor='#fafafa'>
@@ -221,5 +186,5 @@
</div>
</td>
</tr>]]></template_content_html><template_data>$comment, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_commented_event", FALSE, array( 'sprintf' => array( $comment->author()->name ) ) )}: {$comment->item()->name} ({$comment->url()})
</tr>]]></template_content_html><template_data>$comment, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_commented_event", FALSE, array( 'htmlsprintf' => array( $comment->author()->name ) ) )}: {$comment->item()->name} ({$comment->url()})
]]></template_content_plaintext><template_pinned>0</template_pinned></template></emails>
@@ -0,0 +1,38 @@
{
"core": {
"ContentRouter": {
"calendar": "IPS\\calendar\\extensions\\core\\ContentRouter\\calendar"
},
"StreamItems": {
"StreamItems": "IPS\\calendar\\extensions\\core\\StreamItems\\StreamItems"
},
"LiveSearch": {
"Calendars": "IPS\\calendar\\extensions\\core\\LiveSearch\\Calendars"
},
"FileStorage": {
"Events": "IPS\\calendar\\extensions\\core\\FileStorage\\Events"
},
"Announcements": {
"Calendars": "IPS\\calendar\\extensions\\core\\Announcements\\Calendars"
},
"EditorLocations": {
"Venue": "IPS\\calendar\\extensions\\core\\EditorLocations\\Venue",
"Calendar": "IPS\\calendar\\extensions\\core\\EditorLocations\\Calendar"
},
"Permissions": {
"Permissions": "IPS\\calendar\\extensions\\core\\Permissions\\Permissions"
},
"CreateMenu": {
"Event": "IPS\\calendar\\extensions\\core\\CreateMenu\\Event"
},
"FrontNavigation": {
"Calendar": "IPS\\calendar\\extensions\\core\\FrontNavigation\\Calendar"
},
"MemberSync": {
"Calendar": "IPS\\calendar\\extensions\\core\\MemberSync\\Calendar"
},
"Notifications": {
"Events": "IPS\\calendar\\extensions\\core\\Notifications\\Events"
}
}
}
+144 -14
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<javascript app="calendar">
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="103038" javascript_position="1000250"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="105100" javascript_position="1000250"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -105,14 +105,14 @@
*/
_setLoading: function (state) {
if( state ){
this.scope.animate( { opacity: 0.6 }, 'fast' );
this.scope.animate( { opacity: "0.6" }, 'fast' );
} else {
this.scope.animate( { opacity: 1 }, 'fast' );
this.scope.animate( { opacity: "1" }, 'fast' );
}
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="103038" javascript_position="1000250"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="105100" javascript_position="1000250"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -254,7 +254,7 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="103038" javascript_position="1000100"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -288,6 +288,7 @@
this.on( 'click', '[data-action="updateRepeat"]', this.finishRepeat );
this._checkAndSetEventEndState();
this.evaluateRecurringOptions();
this.setup();
},
@@ -330,6 +331,8 @@
*/
setHasFocusedEventOnEndChange: function() {
this._hasFocusedEventEnd = true;
this.evaluateRecurringOptions();
},
/**
@@ -349,6 +352,124 @@
}
},
/**
* When an end date is set, adjust the available recurrence options
*
* @returns {void}
*/
evaluateRecurringOptions: function() {
var startDate = $("#event_start_date").val();
var endDate = $("#event_end_date").val();
if (!this._isValidEndDate(endDate) || $('#check_single_day').prop('checked') ) {
// If the summary isn't visible, make sure the checkbox row is
if( !$('#elRepeatRow_shown').is(':visible') )
{
$('#elRepeatRow_hidden').show();
}
$('#elSelect_event_repeats').find('option').prop( 'disabled', false );
if( $('#elRepeatOn_back').length )
{
$('#elRepeatOn_back').attr( 'id', 'elRepeatOn' );
}
if( $('#elSelect_event_repeats').val() == 'weekly' )
{
$('#elRepeatOn').show();
}
this._updateSummary();
return;
}
startDate = new Date( startDate );
endDate = new Date( endDate );
var dayDifference = parseInt( ( endDate.getTime() - startDate.getTime() ) / ( 24 * 3600 * 1000 ) );
var currentlySelected = $('#elSelect_event_repeats').val();
// If the event spans more than one day, remove "daily" as a recurrence option and hide the "day of the week" options for monthly
if( dayDifference > 1 ) {
$('#elSelect_event_repeats').find('option[value="daily"]').prop( 'disabled', true );
$('#elRepeatOn').hide();
$('#elRepeatOn').attr( 'id', 'elRepeatOn_back' );
if( !currentlySelected || currentlySelected == 'daily' )
{
$('#elSelect_event_repeats').find('option[value="daily"]').prop( 'selected', false );
$('#elSelect_event_repeats').find('option[value="weekly"]').prop( 'selected', true );
currentlySelected = 'weekly';
}
} else {
$('#elSelect_event_repeats').find('option[value="daily"]').prop( 'disabled', false );
if( $('#elRepeatOn_back').length )
{
$('#elRepeatOn_back').attr( 'id', 'elRepeatOn' );
}
if( $('#elSelect_event_repeats').val() == 'weekly' )
{
$('#elRepeatOn').show();
}
}
// If the event spans more than one week, remove "daily" and "weekly" as recurrence options
if( dayDifference > 7 ) {
$('#elSelect_event_repeats').find('option[value="weekly"]').prop( 'disabled', true );
if( !currentlySelected || currentlySelected == 'weekly' )
{
$('#elSelect_event_repeats').find('option[value="weekly"]').prop( 'selected', false );
$('#elSelect_event_repeats').find('option[value="monthly"]').prop( 'selected', true );
currentlySelected = 'monthly';
}
} else {
$('#elSelect_event_repeats').find('option[value="weekly"]').prop( 'disabled', false );
}
// If the event spans more than one month, remove "daily", "weekly" and "monthly" recurrence options
if(
// If there's more than one month between the dates, then we block
( endDate.getMonth() - startDate.getMonth() + ( 12 * ( endDate.getFullYear() - startDate.getFullYear() ) ) > 1 )
||
// Else if there is one month between the dates, then we check the end date is greater than the start date
(
endDate.getMonth() - startDate.getMonth() + ( 12 * ( endDate.getFullYear() - startDate.getFullYear() ) ) == 1 && endDate.getDate() > startDate.getDate()
)
) {
$('#elSelect_event_repeats').find('option[value="monthly"]').prop( 'disabled', true );
if( !currentlySelected || currentlySelected == 'monthly' )
{
$('#elSelect_event_repeats').find('option[value="monthly"]').prop( 'selected', false );
$('#elSelect_event_repeats').find('option[value="yearly"]').prop( 'selected', true );
currentlySelected = 'yearly';
}
} else {
$('#elSelect_event_repeats').find('option[value="monthly"]').prop( 'disabled', false );
}
// If the event spans more than one year, remove ability for event to repeat entirely
if( dayDifference > 365 )
{
$('#elSelect_event_repeats').find('option[value="yearly"]').prop( 'selected', false );
this.disableRecurring();
$('#elRepeatRow_hidden').hide();
}
else
{
$('#elRepeatRow_hidden').show();
}
// And update the summary in case anything changed
this._updateSummary();
},
/**
* Finish setting the options
*
@@ -478,7 +599,10 @@
* @returns {void}
*/
disableRecurring: function (e) {
e.preventDefault();
if( e )
{
e.preventDefault();
}
this.scope.find('#elRepeatCb').prop( 'checked', false );
this._updateSummary();
@@ -588,6 +712,9 @@
return "<em class='ipsType_light ipsType_unbold ipsFaded'>" + ips.getString('select_time') + "</em>";
}
var date = new Date('1970-01-01T' + time + 'Z');
var time = date.toLocaleTimeString( $('html').attr('lang'), { hour: '2-digit', minute: '2-digit', timeZone: 'UTC' } );
return time;
},
@@ -624,6 +751,7 @@
var dateObj = ips.utils.time.getDateFromInput( this.scope.find('input[name="event_dates[repeat_end_date]"]') );
if( ips.utils.time.isValidDateObj( dateObj ) && dateObj.getFullYear() > 1900 ){ // > 1900 just so it doesn't start updating on year 19 etc.
ips.utils.time.removeTimezone( dateObj );
endString = ips.getString('until', { date: ips.utils.time.localeDateString( dateObj, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' } ) } );
}
}
@@ -699,7 +827,7 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="103038" javascript_position="1000200"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="105100" javascript_position="1000200"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -804,14 +932,14 @@
*/
_setLoading: function (state) {
if( state ){
this.scope.animate( { opacity: 0.6 }, 'fast' );
this.scope.animate( { opacity: "0.6" }, 'fast' );
} else {
this.scope.animate( { opacity: 1 }, 'fast' );
this.scope.animate( { opacity: "1" }, 'fast' );
}
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderButton.js" javascript_type="controller" javascript_version="103038" javascript_position="1000150"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderButton.js" javascript_type="controller" javascript_version="105100" javascript_position="1000150"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -869,8 +997,8 @@
.css({
width: dims.outerWidth + 'px',
height: dims.outerHeight + 'px',
top: 0,
left: 0,
top: "0",
left: "0",
position: 'absolute',
zIndex: ips.ui.zIndex()
});
@@ -894,7 +1022,7 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="103038" javascript_position="1000150">/**
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="105100" javascript_position="1000150">/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -1004,7 +1132,7 @@
});
}(jQuery, _));
</file>
<file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="103038" javascript_position="1000050"><![CDATA[/**
<file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="105100" javascript_position="1000050"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*/
@@ -1023,9 +1151,11 @@ controllers</order>
jquery
mustache
jstz
IntersectionObserver
Debug.js
app.js</order>
<order app="global" path="/dev/js//library//jquery">jquery.js
jquery-migrate.js
jquery.history.js
jquery.transform.js</order>
<order app="global" path="/dev/js//library//linkify">linkify.min.js
+35 -15
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<language>
<app key="calendar" version="103038">
<app key="calendar" version="105100">
<word key="__app_calendar" js="0">Calendar</word>
<word key="frontnavigation_calendar" js="0">Calendar</word>
<word key="__indefart_calendar_event_comment" js="0">a comment on a calendar event</word>
@@ -41,6 +41,9 @@
<word key="loc_calendar_viewing_calendar" js="0">Viewing Calendar: %s</word>
<word key="loc_calendar_viewing_calendar_all" js="0">Viewing Calendar</word>
<word key="loc_calendar_viewing_event" js="0">Viewing Event: %s</word>
<word key="loc_calendar_viewing_calendar_action" js="0">%s is viewing a calendar</word>
<word key="loc_calendar_viewing_calendar_all_action" js="0">%s is viewing a calendar</word>
<word key="loc_calendar_viewing_event_action" js="0">%s is viewing an event</word>
<word key="show_bday_calendar" js="0">Show birthdays on calendar</word>
<word key="show_bday_calendar_desc" js="0">When enabled, the calendar will show the number of member birthdays for each day and will list member birthdays when viewing a date.</word>
<word key="ipb_calendar_mon" js="0">Start calendar on Monday</word>
@@ -69,6 +72,8 @@
<word key="calendar_date_format_custom" js="0">Custom date format</word>
<word key="calendar_date_format_custom_desc" js="0"><![CDATA[You can use any <a href='{external.php-strftime}' target='_blank' rel='noopener'>PHP strftime</a> options to specify a custom format for dates in calendar]]></word>
<word key="calendar_no_date_format" js="0">You must either choose a predefined date format or specify a custom date format</word>
<word key="calendar_block_past_changes" js="0">Prevent changes to past events</word>
<word key="calendar_block_past_changes_desc" js="0">If enabled, users will not be able to RSVP for events or edit events that have passed. Moderators will still be able to edit past events.</word>
<word key="calendars" js="0">Calendars</word>
<word key="calendars_sg" js="0">Calendar</word>
<word key="calendar_settings" js="0">Settings</word>
@@ -229,7 +234,7 @@
<word key="event_rpm_ends_occurrencesx" js="0">occurrences</word>
<word key="event_rpm_ends_date" js="0">On</word>
<word key="event_auto_follow" js="0"></word>
<word key="event_auto_follow_suffix" js="0">Notify me when other comments are posted</word>
<word key="event_auto_follow_suffix" js="0">Follow this event</word>
<word key="event_rsvp_limit" js="0">RSVP Limit</word>
<word key="event_rsvp_limit_desc" js="0">Once the limit is reached, no further attendees will be allowed to RSVP for this event.</word>
<word key="event_cover_photo" js="0">Cover Photo</word>
@@ -252,13 +257,15 @@
<word key="events_happening_today" js="0">Events happening today</word>
<word key="day_view_all_day" js="0"><![CDATA[ALL<br>DAY]]></word>
<word key="you_are_going" js="0">You are going</word>
<word key="you_were_going" js="0">You went</word>
<word key="you_arent_going" js="0">You aren't going</word>
<word key="you_werent_going" js="0">You didn't go</word>
<word key="you_are_going_to_this" js="0">You are going to this event</word>
<word key="you_are_not_going_to_this" js="0">You are not going to this event</word>
<word key="rsvp_change" js="0">Change RSVP</word>
<word key="confirm_attendance" js="0">Confirm attendance</word>
<word key="featured_events" js="0">Featured Events</word>
<word key="end_date_before_start" js="0">Please select an end date after the event start date</word>
<word key="end_date_before_start" js="0">The event must end after it starts</word>
<word key="invalid_start_date" js="0">The provided start date is not valid</word>
<word key="invalid_end_date" js="0">The provided end date is not valid</word>
<word key="invalid_recurrence" js="0">The event cannot repeat that frequently. Each occurrence must end before the next starts.</word>
@@ -287,6 +294,9 @@
<word key="rsvp_maybe_event" js="0">Maybe</word>
<word key="rsvp_notgoing_event" js="0">Decline</word>
<word key="rsvp_attendees" js="0">Going</word>
<word key="rsvp_attendees_past" js="0">Went</word>
<word key="rsvp_attended_past_event" js="0">Went</word>
<word key="rsvp_notattended_past_event" js="0">Could not attend</word>
<word key="rsvp_maybe_attendees" js="0">Maybe</word>
<word key="rsvp_notgoing_attendees" js="0">Declined</word>
<word key="event_address" js="0">Event Address</word>
@@ -294,7 +304,11 @@
<word key="no_rsvps_yet" js="0">No one is attending yet.</word>
<word key="no_decline_rsvps_yet" js="0">No one has declined yet.</word>
<word key="no_maybe_rsvps_yet" js="0">No one has said they might go yet.</word>
<word key="no_rsvps_past" js="0">No one went to this event.</word>
<word key="no_maybe_rsvps_past" js="0">No one said they might go.</word>
<word key="no_decline_rsvps_past" js="0">No one declined to attend.</word>
<word key="rsvp_limit_reached" js="0">RSVP limit reached</word>
<word key="no_rsvp_past_event" js="0">The event has already passed</word>
<word key="rsvp_error" js="0">You do not have permission to RSVP for this event</word>
<word key="rsvp_not_going" js="0">Your name has been removed from the guest list for this event</word>
<word key="rsvp_selection_yes" js="0">Your name has been added to the guest list</word>
@@ -302,19 +316,23 @@
<word key="rsvp_selection_maybe" js="0">Your name has been added to the maybe list</word>
<word key="rsvp_download" js="0">Download guest list</word>
<word key="event_rsvp_attendees_other" js="0">Other Responses</word>
<word key="recur_human_yearly" js="0">This event repeats every year %s</word>
<word key="recur_human_yearly_multi" js="0">This event repeats every {# [?:years]} %s</word>
<word key="recur_human_monthly" js="0">This event repeats every month %s</word>
<word key="recur_human_monthly_multi" js="0">This event repeats every {# [?:months]} %s</word>
<word key="recur_human_weekly" js="0">This event repeats every week %s</word>
<word key="recur_human_weekly_multi" js="0">This event repeats every {# [?:weeks]} %s</word>
<word key="recur_human_weekly_days" js="0">This event repeats every week on %s %s</word>
<word key="recur_human_weekly_multi_days" js="0">This event repeats every {# [?:weeks]} on %s %s</word>
<word key="recur_human_daily" js="0">This event repeats every day %s</word>
<word key="recur_human_daily_multi" js="0">This event repeats every {# [?:days]} %s</word>
<word key="recur_human_yearly" js="0">This event {!#[1:began][2:begins]} %s and repeats every year %s</word>
<word key="recur_human_yearly_multi" js="0">This event {!#[1:began][2:begins]} %s and repeats every %s %s</word>
<word key="recur_human_monthly" js="0">This event {!#[1:began][2:begins]} %s and repeats every month %s</word>
<word key="recur_human_monthly_multi" js="0">This event {!#[1:began][2:begins]} %s and repeats every %s %s</word>
<word key="recur_human_weekly" js="0">This event {!#[1:began][2:begins]} %s and repeats every week %s</word>
<word key="recur_human_weekly_multi" js="0">This event {!#[1:began][2:begins]} %s and repeats every %s %s</word>
<word key="recur_human_weekly_days" js="0">This event {!#[1:began][2:begins]} %s and repeats every week on %s %s</word>
<word key="recur_human_weekly_multi_days" js="0">This event {!#[1:began][2:begins]} %s and repeats every %s on %s %s</word>
<word key="recur_human_daily" js="0">This event {!#[1:began][2:begins]} %s and repeats every day %s</word>
<word key="recur_human_daily_multi" js="0">This event {!#[1:began][2:begins]} %s and repeats every %s %s</word>
<word key="recur_human__forever" js="0">forever</word>
<word key="recur_human__occurrences" js="0">for {# [1:occurrence][?:occurrences]}</word>
<word key="recur_human__until" js="0">until %s</word>
<word key="recur_human__xyearly" js="0">{# [1:year][?:years]}</word>
<word key="recur_human__xmonthly" js="0">{# [1:month][?:months]}</word>
<word key="recur_human__xweekly" js="0">{# [1:week][?:weeks]}</word>
<word key="recur_human__xdaily" js="0">{# [1:day][?:days]}</word>
<word key="event_rss_feed_off" js="0">This RSS feed is currently unavailable</word>
<word key="event_rss_feed_off_admin" js="0">The calendar RSS feed is currently disabled in the admin control panel</word>
<word key="event_attendees" js="0">Attendees for %s</word>
@@ -347,6 +365,7 @@
<word key="event_remind_days_before" js="0">days before this event</word>
<word key="event_reminder_removed" js="0">Reminder Removed</word>
<word key="event_reminder_added" js="0">Reminder Saved</word>
<word key="no_edit_past_event" js="0">You do not have permission to edit past events</word>
<word key="block_upcomingEvents" js="0">Upcoming Events</word>
<word key="block_upcomingEvents_desc" js="0">Shows upcoming calendar events</word>
<word key="auto_hide" js="0">Automatically hide block</word>
@@ -423,10 +442,11 @@
<word key="__api_calendar_comments" js="0">Comments</word>
<word key="__api_calendar_reviews" js="0">Reviews</word>
<word key="__api_calendar_calendars" js="0">Calendars</word>
<word key="__api_calendar_venues" js="0">Venues</word>
<word key="calendar_activity_stream_rsvp" js="0"><![CDATA[%s is attending <a href='%s'>%s</a>]]></word>
<word key="all_activity_calendar_streamitems" js="0">When a member RSVPs to an event</word>
<word key="notifications__calendar_Events" js="0">Calendar</word>
<word key="notifications__event_reminder" js="0">Event Reminders</word>
<word key="notifications__calendar_Events" js="0">Event Reminders</word>
<word key="notifications__calendar_Events_desc" js="0">These notifications are sent when an event you have asked to receive a reminder about is coming up.</word>
<word key="mailsub__calendar_notification_event_reminder" js="0"><![CDATA[Event Reminder for {$content->mapped("title")|raw}]]></word>
<word key="email_event_reminder" js="0"><![CDATA[There's now less than %s to go until <a href='%s'>%s</a>.]]></word>
<word key="email_event_reminder_plain" js="0">There's now less than %s to go until %s</word>
+6 -3
View File
@@ -2,17 +2,20 @@
"admin": {
"calendars": {
"default_controller": null,
"protected": 0
"protected": 0,
"default": 1
},
"venues": {
"default_controller": "",
"protected": false
"protected": 0,
"default": 0
}
},
"front": {
"calendar": {
"default_controller": "view",
"protected": 0
"protected": 0,
"default": 1
}
}
}
+132 -27
View File
@@ -1027,18 +1027,100 @@
"zerofill": false
},
"event_meta_data": {
"name": "event_meta_data",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": [],
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"auto_increment": false
},
"event_recurring_end_date": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "End date if this is a recurring event which ends",
"decimals": null,
"default": null,
"length": 0,
"name": "event_recurring_end_date",
"type": "DATETIME",
"unsigned": false,
"values": [],
"zerofill": false
},
"event_timezone": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": 0,
"length": 1,
"name": "event_meta_data",
"type": "BIT",
"default": null,
"length": 255,
"name": "event_timezone",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"event_edit_time": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 10,
"name": "event_edit_time",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"event_edit_member_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "event_edit_member_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"event_append_edit": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 1,
"name": "event_append_edit",
"type": "TINYINT",
"unsigned": false,
"values": [],
"zerofill": false
},
"event_edit_reason": {
"name": "event_edit_reason",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
@@ -1096,20 +1178,6 @@
"event_calendar_id"
]
},
"recurring_events": {
"type": "key",
"name": "recurring_events",
"length": [
180,
null,
null
],
"columns": [
"event_recurring",
"event_approved",
"event_calendar_id"
]
},
"ip_lookup": {
"type": "key",
"name": "ip_lookup",
@@ -1123,31 +1191,48 @@
"event_venue": {
"type": "key",
"name": "event_venue",
"columns": [
"event_venue"
],
"length": [
null
],
"columns": [
"event_venue"
]
},
"event_album": {
"type": "key",
"name": "event_album",
"columns": [
"event_album",
"event_approved",
"event_saved"
],
"length": [
null,
null,
null
],
"columns": [
"event_album",
"event_approved",
"event_saved"
]
},
"recurring_events": {
"type": "key",
"name": "recurring_events",
"length": [
223,
null,
null,
null,
null
],
"columns": [
"event_recurring",
"event_recurring_end_date",
"event_approved",
"event_calendar_id",
"event_start_date"
]
}
},
"collation": "utf8mb4_unicode_ci",
"engine": "InnoDB",
"comment": "",
"reporting": "count"
},
"calendar_import_feeds": {
@@ -1324,6 +1409,16 @@
"columns": [
"feed_last_run"
]
},
"member": {
"type": "key",
"name": "member",
"columns": [
"feed_member_id"
],
"length": [
null
]
}
},
"comment": "",
@@ -1824,6 +1919,16 @@
"length": [
null
]
},
"member": {
"type": "key",
"name": "member",
"columns": [
"reminder_member_id"
],
"length": [
null
]
}
}
},
+5
View File
@@ -4,6 +4,11 @@
"default": "1",
"report": "full"
},
{
"key": "calendar_block_past_changes",
"default": "0",
"report": "full"
},
{
"key": "calendar_date_format",
"default": "d_lm_y",
File diff suppressed because it is too large. Load diff
+93 -1
View File
@@ -255,5 +255,97 @@
"103035": "4.3.6",
"103036": "4.3.6",
"103037": "4.3.6",
"103038": "4.3.6"
"103038": "4.3.6",
"103039": "4.3.6",
"104000": "4.4.0 Beta 1",
"104001": "4.4.0 Beta 2",
"104002": "4.4.0 Beta 3",
"104004": "4.4.0 Beta 4",
"104003": "4.4.0 Beta 4",
"104005": "4.4.0",
"104006": "4.4.0",
"104007": "4.4.0",
"104008": "4.4.0",
"104009": "4.4.1",
"104010": "4.4.1 Beta 2",
"104011": "4.4.1",
"104012": "4.4.1",
"104013": "4.4.1",
"104014": "4.4.1",
"104015": "4.4.2 Beta 1",
"104016": "4.4.2",
"104017": "4.4.2",
"104018": "4.4.2",
"104019": "4.4.2",
"104020": "4.4.2",
"104021": "4.4.3 Beta 1",
"104022": "4.4.3 Beta 2",
"104023": "4.4.3",
"104024": "4.4.3",
"104025": "4.4.3",
"104026": "4.4.4 Beta 1",
"104027": "4.4.4",
"104028": "4.4.4",
"104029": "4.4.4",
"104030": "4.4.5 Beta 1",
"104031": "4.4.5 Beta 2",
"104032": "4.4.5 Beta 2",
"104033": "4.4.5",
"104034": "4.4.5",
"104035": "4.4.5",
"104036": "4.4.5",
"104037": "4.4.5",
"104038": "4.4.6",
"104039": "4.4.6",
"104040": "4.4.6",
"104041": "4.4.7 Beta 1",
"104042": "4.4.7 Beta 2",
"104043": "4.4.7 Beta 3",
"104044": "4.4.7",
"104045": "4.4.8 Beta 1",
"104046": "4.4.8 Beta 2",
"104047": "4.4.8",
"104048": "4.4.9 Beta 1",
"104049": "4.4.9",
"104050": "4.4.9",
"104051": "4.4.9",
"104052": "4.4.9",
"104053": "4.4.9.1",
"104054": "4.4.9.1",
"104055": "4.4.9.2",
"104056": "4.4.9.2",
"104057": "4.4.10 Beta 1",
"104058": "4.4.10 Beta 2",
"104059": "4.4.10 Beta 3",
"104060": "4.4.10 Beta 4",
"104061": "4.4.10",
"104062": "4.4.10",
"104063": "4.4.10",
"104064": "4.4.10",
"104065": "4.4.10",
"104066": "4.4.10",
"104067": "4.4.10",
"104068": "4.4.10",
"104069": "4.4.10",
"105013": "4.5.0 Beta 1",
"105014": "4.5.0 Beta 1",
"105015": "4.5.0 Beta 2",
"105016": "4.5.0 Beta 3",
"105017": "4.5.0 Beta 4",
"105018": "4.5.0 Beta 4",
"105019": "4.5.0 Beta 4",
"105020": "4.5.0 Beta 4",
"105021": "4.5.0 Beta 5",
"105022": "4.5.0 Beta 6",
"105023": "4.5.0 Beta 6",
"105024": "4.5.0 Beta 7",
"105025": "4.5.0 Beta 8",
"105026": "4.5.0 Beta 8",
"105027": "4.5.0 Beta 8",
"105028": "4.5.0 Beta 9",
"105029": "4.5.0 Beta 10",
"105030": "4.5.0 Beta 11",
"105031": "4.5.0 Beta 11",
"105032": "4.5.0 Beta 12",
"105100": "4.5.0"
}
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\Announcements;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\ContentRouter;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\CreateMenu;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\EditorLocations;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\EditorLocations;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -59,7 +59,7 @@ class _Venue
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
return FALSE;
}
/**
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\FileStorage;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\FrontNavigation;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\LiveSearch;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -26,7 +26,7 @@ class _Calendars
/**
* Check we have access
*
* @return void
* @return bool
*/
public function hasAccess()
{
@@ -37,7 +37,7 @@ class _Calendars
/**
* Get the search results
*
* @param string Search Term
* @param string $searchTerm Search Term
* @return array Array of results
*/
public function getResults( $searchTerm )
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\MemberSync;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -11,7 +11,7 @@
namespace IPS\calendar\extensions\core\Notifications;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,15 +23,23 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
class _Events
{
/**
* Get configuration
* Get fields for configuration
*
* @param \IPS\Member|null $member The member
* @param \IPS\Member|null $member The member (to take out any notification types a given member will never see) or NULL if this is for the ACP
* @return array
*/
public function getConfiguration( $member )
public static function configurationOptions( \IPS\Member $member = NULL )
{
return array(
'event_reminder' => array( 'default' => array( 'email' ), 'disabled' => array() ),
'event_reminder' => array(
'type' => 'standard',
'notificationTypes' => array( 'event_reminder' ),
'title' => 'notifications__calendar_Events',
'showTitle' => FALSE,
'description' => 'notifications__calendar_Events_desc',
'default' => array( 'inline', 'push', 'email' ),
'disabled' => array()
)
);
}
@@ -39,6 +47,7 @@ class _Events
* Parse notification: new_content
*
* @param \IPS\Notification\Inline $notification The notification
* @param bool $htmlEscape TRUE to escape HTML in title
* @return array
* @code
return array(
@@ -51,7 +60,7 @@ class _Events
);
* @endcode
*/
public function parse_new_content( $notification )
public function parse_new_content( $notification, $htmlEscape=TRUE )
{
$item = $notification->item;
if ( !$item )
@@ -60,7 +69,14 @@ class _Events
}
return array(
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__new_content', FALSE, array( 'sprintf' => array( $item->author()->name, mb_strtolower( $item->indefiniteArticle() ), $item->container()->_title, $item->mapped('title') ) ) ),
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__new_content', FALSE, array(
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array(
$item->author()->name,
mb_strtolower( $item->indefiniteArticle() ),
$item->container()->getTitleForLanguage( \IPS\Member::loggedIn()->language(), $htmlEscape ? array( 'escape' => TRUE ) : array() ),
$item->mapped('title')
)
) ),
'url' => $notification->item->url(),
'content' => $notification->item->content(),
'author' => $notification->item->author(),
@@ -72,6 +88,7 @@ class _Events
* Parse notification: Event reminder
*
* @param \IPS\Notification\Inline $notification The notification
* @param bool $htmlEscape TRUE to escape HTML in title
* @return array
* @code
return array(
@@ -84,7 +101,7 @@ class _Events
);
* @endcode
*/
public function parse_event_reminder( $notification )
public function parse_event_reminder( $notification, $htmlEscape=TRUE )
{
$item = $notification->item;
if ( !$item )
@@ -93,11 +110,37 @@ class _Events
}
return array(
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__event_reminder', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $notification->extra['daysToGo'] ) ) ), $item->mapped('title') ) ) ),
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__event_reminder', FALSE, array(
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array( \IPS\Member::loggedIn()->language()->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $notification->extra['daysToGo'] ) ) ), $item->mapped('title') )
) ),
'url' => $notification->item->url(),
'content' => $notification->item->content(),
'author' => $notification->item->author(),
'unread' => (bool) ( $item->unread() )
);
}
/**
* Parse notification for mobile: event_reminder
*
* @param \IPS\Lang $language The language that the notification should be in
* @param \IPS\Member $member The member that started following the recipient
* @return array
*/
public static function parse_mobile_event_reminder( \IPS\Lang $language, \IPS\calendar\Event $event, $daysToGo )
{
return array(
'body' => $language->addToStack( 'notification__event_reminder', FALSE, array( 'htmlsprintf' => array(
$language->addToStack( "days_to_go", FALSE, array( 'pluralize' => array(
$daysToGo
) ) ),
$event->mapped('title')
) ) ),
'data' => array(
'url' => (string) $event->url(),
'author' => $event->author()
),
'channelId' => 'events',
);
}
}
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\Permissions;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\extensions\core\StreamItems;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -47,14 +47,21 @@ class _StreamItems
}
foreach ( \IPS\Db::i()->select( '*', 'calendar_event_rsvp', $where, 'rsvp_date DESC', 10 ) as $rsvp )
{
$event = \IPS\calendar\Event::load( $rsvp[ 'rsvp_event_id' ] );
if( $event->canView() )
try
{
$member = \IPS\Member::load( $rsvp['rsvp_member_id'] );
$title = htmlspecialchars( $event->title, ENT_DISALLOWED, 'UTF-8', FALSE );
$rsvps[] = new \IPS\Content\Search\Result\Custom( \IPS\DateTime::ts( $rsvp[ 'rsvp_date' ] ), \IPS\Member::loggedIn()->language()->addToStack( 'calendar_activity_stream_rsvp', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( $member ), $event->url(), $title ) ) ) );
$event = \IPS\calendar\Event::load( $rsvp[ 'rsvp_event_id' ] );
if( $event->canView() )
{
$member = \IPS\Member::load( $rsvp['rsvp_member_id'] );
$title = htmlspecialchars( $event->title, ENT_DISALLOWED, 'UTF-8', FALSE );
$rsvps[] = new \IPS\Content\Search\Result\Custom( \IPS\DateTime::ts( $rsvp[ 'rsvp_date' ] ), \IPS\Member::loggedIn()->language()->addToStack( 'calendar_activity_stream_rsvp', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( $member ), $event->url(), $title ) ) ) );
}
}
catch ( \OutOfRangeException $e )
{
/* Event doesn't exist */
}
}
/* Return */
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\admin\calendars;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _calendars extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\admin\calendars;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -22,7 +22,12 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
* iCalendar feed management
*/
class _ical extends \IPS\Dispatcher\Controller
{
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -99,7 +104,7 @@ class _ical extends \IPS\Dispatcher\Controller
$return = array( 'update' => array(
'icon' => 'refresh',
'title' => 'update_ical',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=refresh&id=' ) . $row['feed_id'],
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=refresh&id=' . $row['feed_id'] )->csrf(),
'hotkey' => 'r'
) );
@@ -118,7 +123,7 @@ class _ical extends \IPS\Dispatcher\Controller
$return['delete'] = array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=delete&id=' ) . $row['feed_id'],
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=delete&id=' . $row['feed_id'] )->csrf(),
'data' => array( 'delete' => '' ),
);
}
@@ -241,7 +246,7 @@ class _ical extends \IPS\Dispatcher\Controller
) ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$form->add( new \IPS\Helpers\Form\Node( 'feed_venue_id', NULL, TRUE, array(
$form->add( new \IPS\Helpers\Form\Node( 'feed_venue_id', NULL, FALSE, array(
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=upload' ),
'class' => 'IPS\calendar\Venue',
) ) );
@@ -255,7 +260,8 @@ class _ical extends \IPS\Dispatcher\Controller
try
{
$icsParser = new \IPS\calendar\Icalendar\ICSParser;
$count = $icsParser->parse( \file_get_contents( $values['feed_file'] ), $values['feed_calendar_id'], $values['feed_member_id'], ( isset( $values['feed_venue_id'] ) ) ? $values['feed_venue_id']->_id : NULL );
$count = $icsParser->parse( \file_get_contents( $values['feed_file'] ), $values['feed_calendar_id'], $values['feed_member_id'], NULL, ( isset( $values['feed_venue_id'] ) AND $values['feed_venue_id'] ) ? $values['feed_venue_id']->_id : NULL );
}
catch( \UnexpectedValueException $e )
{
@@ -305,7 +311,7 @@ class _ical extends \IPS\Dispatcher\Controller
$options[ $calendar->id ] = $calendar->_title;
}
$form->add( new \IPS\Helpers\Form\Select( 'feed_calendar_id', $feed->calendar_id, TRUE, array( 'options' => $options, 'parse' => 'normal' ) ) );
$form->add( new \IPS\Helpers\Form\Node( 'feed_calendar_id', \IPS\calendar\Calendar::load( $feed->calendar_id ), TRUE, array( 'class' => 'IPS\calendar\Calendar', 'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=edit&id=' . \IPS\Request::i()->id, 'admin' ) ) ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
@@ -369,6 +375,7 @@ class _ical extends \IPS\Dispatcher\Controller
{
/* Check permissions */
\IPS\Dispatcher::i()->checkAcpPermission( 'calendar_feeds_delete' );
\IPS\Session::i()->csrfCheck();
/* Build the form */
$form = new \IPS\Helpers\Form( 'form', 'delete' );
@@ -412,6 +419,8 @@ class _ical extends \IPS\Dispatcher\Controller
*/
public function refresh()
{
\IPS\Session::i()->csrfCheck();
/* Refresh the feed */
try
{
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\admin\calendars;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -60,11 +65,10 @@ class _settings extends \IPS\Dispatcher\Controller
1 => 'calendar_rss_feed_order_publish'
) ), NULL, NULL, NULL, 'calendar_rss_feed_order' ) );
$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 ( $values = $form->values() )
{
if( $values['calendar_date_format'] == -1 AND !$values['calendar_date_format_custom'] )
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\admin\calendars;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _venues extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\front\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -55,6 +55,8 @@ class _event extends \IPS\Content\Controller
{
\IPS\Output::i()->error( 'node_error', '2L179/2', 404, '' );
}
$this->event->container()->clubCheckRules();
/* We want to present the same breadcrumb structure as the rest of the calendar */
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=view", 'front', 'calendar' ), \IPS\Member::loggedIn()->language()->addToStack('module__calendar_calendar') );
@@ -88,9 +90,9 @@ class _event extends \IPS\Content\Controller
$tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : array_shift( $_tabs );
$activeTabContents = $this->event->commentReviews( $tab );
if ( count( $tabs ) > 1 )
if ( \count( $tabs ) > 1 )
{
$commentsAndReviews = count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $this->event->url(), 'tab', FALSE, TRUE ) : NULL;
$commentsAndReviews = \count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $this->event->url(), 'tab', FALSE, TRUE ) : NULL;
}
else
{
@@ -131,23 +133,24 @@ class _event extends \IPS\Content\Controller
}
/* Add JSON-LD */
$format = $this->event->all_day ? "Y-m-d" : \IPS\DateTime::ISO8601;
\IPS\Output::i()->jsonLd['event'] = array(
'@context' => "http://schema.org",
'@type' => "Event",
'url' => (string) $this->event->url(),
'name' => $this->event->mapped('title'),
'description' => strip_tags( $this->event->truncated() ),
'description' => $this->event->truncated( TRUE, NULL ),
'eventStatus' => "EventScheduled",
'startDate' => $this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' ) ?
$this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format( \IPS\DateTime::ISO8601 ) :
$this->event->lastOccurrence( 'startDate' )->format( \IPS\DateTime::ISO8601 )
$this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format( $format ) :
$this->event->lastOccurrence( 'startDate' )->format( $format )
);
if( $this->event->_end_date )
{
\IPS\Output::i()->jsonLd['event']['endDate'] = $this->event->nextOccurrence( $this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' ) ?: \IPS\calendar\Date::getDate(), 'endDate' ) ?
$this->event->nextOccurrence( $this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' ) ?: \IPS\calendar\Date::getDate(), 'endDate' )->format( \IPS\DateTime::ISO8601 ) :
$this->event->lastOccurrence( 'endDate' )->format( \IPS\DateTime::ISO8601 );
$this->event->nextOccurrence( $this->event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' ) ?: \IPS\calendar\Date::getDate(), 'endDate' )->format( $format ) :
$this->event->lastOccurrence( 'endDate' )->format( $format );
}
if( $this->event->container()->allow_reviews AND $this->event->reviews AND $this->event->averageReviewRating() )
@@ -167,7 +170,7 @@ class _event extends \IPS\Content\Controller
if( $this->event->rsvp )
{
if( count( $attendees[1] ) )
if( \count( $attendees[1] ) )
{
\IPS\Output::i()->jsonLd['event']['attendee'] = array();
@@ -227,7 +230,7 @@ class _event extends \IPS\Content\Controller
{
$dateBits = explode( '-', \IPS\Request::i()->sd );
if( count( $dateBits ) === 3 )
if( \count( $dateBits ) === 3 )
{
$date = \IPS\calendar\Date::getDate( $dateBits[0], $dateBits[1], $dateBits[2] );
}
@@ -288,6 +291,11 @@ class _event extends \IPS\Content\Controller
\IPS\Output::i()->error( 'rsvp_error', '2L179/3', 403, '' );
}
if( $this->event->hasPassed() AND \IPS\Settings::i()->calendar_block_past_changes )
{
\IPS\Output::i()->error( 'no_rsvp_past_event', '2L179/6', 403, '' );
}
\IPS\Session::i()->csrfCheck();
/* We delete either way at this point, because even if we select a different action we have to remove any existing RSVP preference */
@@ -327,7 +335,7 @@ class _event extends \IPS\Content\Controller
}
/* And we have to actually check the limit */
if( $_go == \IPS\calendar\Event::RSVP_YES and count( $this->event->attendees( \IPS\calendar\Event::RSVP_YES ) ) >= $this->event->rsvp_limit )
if( $_go == \IPS\calendar\Event::RSVP_YES and \count( $this->event->attendees( \IPS\calendar\Event::RSVP_YES ) ) >= $this->event->rsvp_limit )
{
\IPS\Output::i()->error( 'rsvp_limit_reached', '3L179/5', 403, '' );
}
@@ -353,11 +361,32 @@ class _event extends \IPS\Content\Controller
*/
protected function edit()
{
/* Are we blocking changes to past events? */
if( $this->event->hasPassed() AND \IPS\Settings::i()->calendar_block_past_changes )
{
if ( !\IPS\calendar\Event::modPermission( 'edit', \IPS\Member::loggedIn(), $this->event->containerWrapper() ) )
{
\IPS\Output::i()->error( 'no_edit_past_event', '2L179/7', 403, '' );
}
}
/* Output resources and go */
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_submit.js', 'calendar', 'front' ) );
return parent::edit();
}
/**
* Return the form for editing. Abstracted so controllers can define a custom template if desired.
*
* @param \IPS\Helpers\Form $form The form
* @return string
*/
protected function getEditForm( $form )
{
return $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'submit', 'calendar' ), 'submitForm' ) );
}
/**
* Set a reminder
*
@@ -417,11 +446,11 @@ class _event extends \IPS\Content\Controller
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'event_set_reminder' );
$output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'view', 'calendar' ) ), 'reminderForm' ) );
$output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'view', 'calendar' ), 'reminderForm' ) );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\front\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -113,14 +113,16 @@ class _submit extends \IPS\Dispatcher\Controller
$form = \IPS\calendar\Event::create( $calendar );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->submitPage( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'submit', 'calendar' ) ), 'submitForm' ) ), \IPS\Member::loggedIn()->language()->addToStack('add_cal_event_header'), $calendar );
if ( \IPS\calendar\Event::moderateNewItems( \IPS\Member::loggedIn() ) )
$extraOutput = '';
$guestPostBeforeRegister = ( !\IPS\Member::loggedIn()->member_id ) ? ( $calendar and !$calendar->can( 'add', \IPS\Member::loggedIn(), FALSE ) ) : NULL;
$modQueued = \IPS\calendar\Event::moderateNewItems( \IPS\Member::loggedIn(), $calendar, $guestPostBeforeRegister );
if ( $guestPostBeforeRegister or $modQueued )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->modQueueMessage( \IPS\Member::loggedIn()->warnings( 5, NULL, 'mq' ), \IPS\Member::loggedIn()->mod_posts ) . \IPS\Output::i()->output;
}
$extraOutput .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->postingInformation( $guestPostBeforeRegister, $modQueued, TRUE );
}
/* Display */
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'submit' )->submitPage( $extraOutput . $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'submit', 'calendar' ), 'submitForm' ) ), \IPS\Member::loggedIn()->language()->addToStack('add_cal_event_header'), $calendar );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'submit_event' );
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'add_cal_event_header' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_submit.js', 'calendar', 'front' ) );
@@ -143,7 +145,7 @@ class _submit extends \IPS\Dispatcher\Controller
}
/* Are we the author of the existing event? */
if( $existing->author() !== \IPS\Member::loggedIn() )
if( $existing->author()->member_id !== \IPS\Member::loggedIn()->member_id )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ) );
}
@@ -153,7 +155,7 @@ class _submit extends \IPS\Dispatcher\Controller
$formElements = \IPS\Calendar\Event::formElements( $existing, $existing->container() );
foreach ( $formElements as $key => $object )
{
if ( is_object( $object ) )
if ( \is_object( $object ) )
{
$form->add( $object );
}
@@ -204,7 +206,7 @@ class _submit extends \IPS\Dispatcher\Controller
}
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->submitPage( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'submit', 'calendar' ) ), 'submitForm' ) ), \IPS\Member::loggedIn()->language()->addToStack('copy_cal_event_header', TRUE, array( 'sprintf' => $existing->title ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->submitPage( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'submit', 'calendar' ), 'submitForm' ) ), \IPS\Member::loggedIn()->language()->addToStack('copy_cal_event_header', TRUE, array( 'sprintf' => $existing->title ) ) );
if ( \IPS\calendar\Event::moderateNewItems( \IPS\Member::loggedIn() ) )
{
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\front\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -98,7 +98,7 @@ class _venue extends \IPS\Dispatcher\Controller
/* Display */
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $upcomingOutput, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $upcomingOutput, 200, 'text/html' );
}
else
{
@@ -12,7 +12,7 @@
namespace IPS\calendar\modules\front\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -33,6 +33,11 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected $_today = NULL;
/**
* @brief Root nodes
*/
protected $roots = NULL;
/**
* Route
*
@@ -52,11 +57,11 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Is there only one calendar? */
$roots = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
if ( count( $roots ) == 1 AND !isset( \IPS\Request::i()->id ) )
$this->roots = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
if ( \count( $this->roots ) == 1 AND !isset( \IPS\Request::i()->id ) )
{
$roots = array_shift( $roots );
$this->_calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $roots->_id );
$root = array_shift( $this->roots );
$this->_calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $root->_id );
}
/* Are we viewing a specific calendar only? */
@@ -70,19 +75,17 @@ class _view extends \IPS\Dispatcher\Controller
{
\IPS\Output::i()->error( 'node_error', '2L182/2', 404, '' );
}
/* If we're viewing a club, set the breadcrumbs appropriately */
if ( $club = $this->_calendar->club() )
{
\IPS\core\FrontNavigation::$clubTabActive = TRUE;
\IPS\Output::i()->breadcrumb = array();
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ), \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs') );
\IPS\Output::i()->breadcrumb[] = array( $club->url(), $club->name );
\IPS\Output::i()->breadcrumb[] = array( $this->_calendar->url(), $this->_calendar->_title );
$this->_calendar->clubCheckRules();
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $club, $this->_calendar, 'sidebar' );
}
$club->setBreadcrumbs( $this->_calendar );
}
else
{
\IPS\Output::i()->breadcrumb[] = array( NULL, $this->_calendar->_title );
}
}
@@ -125,7 +128,7 @@ class _view extends \IPS\Dispatcher\Controller
/* Online User Location */
if ( $this->_calendar )
{
\IPS\Session::i()->setLocation( $this->_calendar->url(), array(), 'loc_calendar_viewing_calendar', array( "calendar_calendar_{$this->_calendar->id}" => TRUE ) );
\IPS\Session::i()->setLocation( $this->_calendar->url(), $this->_calendar->permissions()['perm_view'], 'loc_calendar_viewing_calendar', array( "calendar_calendar_{$this->_calendar->id}" => TRUE ) );
}
else
{
@@ -142,9 +145,6 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected function _viewMonth( $jump, $featured=array() )
{
/* Get the calendars we can view */
$calendars = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
/* Get the month data */
$day = NULL;
@@ -158,7 +158,7 @@ class _view extends \IPS\Dispatcher\Controller
$date = \IPS\calendar\Date::getDate( \IPS\Request::i()->y ?: NULL, \IPS\Request::i()->m ?: NULL, $day );
/* Get birthdays */
$birthdays = ( $this->_calendar === NULL OR count( $calendars ) == 1 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
$birthdays = ( $this->_calendar === NULL OR \count( $this->roots ) == 1 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
@@ -173,17 +173,17 @@ class _view extends \IPS\Dispatcher\Controller
}
/* 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 )
if( \count($events) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarMonth( $calendars, $date, $featured, $birthdays, $events, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarMonth( $this->roots, $date, $featured, $birthdays, $events, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
@@ -191,7 +191,7 @@ class _view extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWrapper(
$output,
$calendars,
$this->roots,
$this->_calendar,
$jump,
$date,
@@ -210,9 +210,6 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected function _viewWeek( $jump, $featured=array() )
{
/* Get the calendars we can view */
$calendars = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
/* Get the month data */
$week = \IPS\Request::i()->w ? explode( '-', \IPS\Request::i()->w ) : NULL;
try
@@ -238,7 +235,7 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Get birthdays */
$birthdays = ( $this->_calendar === NULL OR count( $calendars ) == 1 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
$birthdays = ( $this->_calendar === NULL OR \count( $this->roots ) == 1 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
@@ -253,17 +250,17 @@ class _view extends \IPS\Dispatcher\Controller
}
/* 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 )
if( \count( $events ) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWeek( $calendars, $date, $featured, $birthdays, $events, $nextWeek, $lastWeek, $days, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWeek( $this->roots, $date, $featured, $birthdays, $events, $nextWeek, $lastWeek, $days, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
@@ -278,7 +275,7 @@ class _view extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWrapper(
$output,
$calendars,
$this->roots,
$this->_calendar,
$jump,
$date,
@@ -297,9 +294,6 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected function _viewDay( $jump, $featured=array() )
{
/* Get the calendars we can view */
$calendars = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
/* Get the month data */
try
{
@@ -310,8 +304,8 @@ class _view extends \IPS\Dispatcher\Controller
\IPS\Output::i()->error( 'error_bad_date', '2L182/9', 403, '' );
}
$tomorrow = $date->adjust( '+1 day' );
$yesterday = $date->adjust( '-1 day' );
$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 )
@@ -327,14 +321,14 @@ class _view extends \IPS\Dispatcher\Controller
return;
}
$birthdayCount = ( $this->_calendar === NULL OR count( $calendars ) == 1 ) ? $date->getBirthdays( TRUE, TRUE ) : array();
$birthdays = ( $this->_calendar === NULL OR count( $calendars ) == 1 ) ? $date->getBirthdays( TRUE, FALSE ) : array();
$birthdayCount = ( $this->_calendar === NULL OR \count( $this->roots ) == 1 ) ? $date->getBirthdays( TRUE, TRUE ) : array();
$birthdays = ( $this->_calendar === NULL OR \count( $this->roots ) == 1 ) ? $date->getBirthdays( TRUE, FALSE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents( $date, $date, $this->_calendar );
$events = \IPS\calendar\Event::retrieveEvents( clone $date, clone $date, $this->_calendar );
/* 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 )
if( \count($events) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
@@ -370,18 +364,18 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarDay( $calendars, $date, $featured, $birthdays, $birthdayCount, $dayEvents, $tomorrow, $yesterday, $this->_today, $this->_calendar, $jump );
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarDay( $this->roots, $date, $featured, $birthdays, $birthdayCount, $dayEvents, $tomorrow, $yesterday, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('cal_month_day', FALSE, array( 'sprintf' => array( $date->monthName, $date->mday, $date->year ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWrapper(
$output,
$calendars,
$this->roots,
$this->_calendar,
$jump,
$date,
@@ -405,9 +399,6 @@ class _view extends \IPS\Dispatcher\Controller
*/
protected function _viewStream( $jump, $featured=array() )
{
/* Get the calendars we can view */
$calendars = \IPS\Settings::i()->club_nodes_in_apps ? \IPS\calendar\Calendar::rootsWithClubs() : \IPS\calendar\Calendar::roots();
/* Get the month data */
$day = NULL;
@@ -459,7 +450,7 @@ class _view extends \IPS\Dispatcher\Controller
/* Pagination */
$pagination = array(
'page' => ( isset( \IPS\Request::i()->page ) ) ? \IPS\Request::i()->page : 1,
'pages' => ( count( $events ) > 0 ) ? ceil( count( $events ) / $this->streamPerPage ) : 1,
'pages' => ( \count( $events ) > 0 ) ? ceil( \count( $events ) / $this->streamPerPage ) : 1,
'limit' => $this->streamPerPage
);
@@ -469,27 +460,27 @@ class _view extends \IPS\Dispatcher\Controller
}
/* 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 )
if( \count( $events ) === 0 )
{
\IPS\Output::i()->metaTags['robots'] = 'noindex';
}
else
{
$events = array_slice( $events, ( $pagination['page'] - 1 ) * $this->streamPerPage, $this->streamPerPage );
$events = \array_slice( $events, ( $pagination['page'] - 1 ) * $this->streamPerPage, $this->streamPerPage );
}
/* Non-existent page */
if( $pagination['page'] > 1 AND !count( $events ) )
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( $calendars, $date, $featured, $events, $this->_calendar, $jump, $pagination );
$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', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $output, 200, 'text/html' );
}
else
{
@@ -499,7 +490,7 @@ class _view extends \IPS\Dispatcher\Controller
\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,
$calendars,
$this->roots,
$this->_calendar,
$jump,
$date,
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_100002;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_100015;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_100018;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_100028;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_100042;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -32,7 +32,7 @@ class _Upgrade
{
$perCycle = 500;
$did = 0;
$limit = intval( \IPS\Request::i()->extra );
$limit = \intval( \IPS\Request::i()->extra );
/* Try to prevent timeouts to the extent possible */
$cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_101064;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_102005;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -0,0 +1,34 @@
{
"1": {
"method": "addIndex",
"params": [
"calendar_event_reminders",
{
"type": "key",
"name": "member",
"columns": [
"reminder_member_id"
],
"length": [
null
]
}
]
},
"2": {
"method": "addIndex",
"params": [
"calendar_import_feeds",
{
"type": "key",
"name": "member",
"columns": [
"feed_member_id"
],
"length": [
null
]
}
]
}
}
@@ -0,0 +1,37 @@
{
"added": [
"app=calendar&module=calendars&controller=calendars",
"app=calendar&module=calendars&controller=calendars&do=form",
"app=calendar&module=calendars&controller=calendars&do=permissions",
"app=calendar&module=calendars&controller=calendars&searchResult=cal_comment_moderate",
"app=calendar&module=calendars&controller=calendars&searchResult=form_1_cal_allow_comments",
"app=calendar&module=calendars&controller=calendars&searchResult=form_1_cal_allow_reviews",
"app=calendar&module=calendars&controller=calendars&searchResult=form_1_cal_color",
"app=calendar&module=calendars&controller=calendars&searchResult=form_1_cal_moderate",
"app=calendar&module=calendars&controller=calendars&searchResult=form_1_cal_title",
"app=calendar&module=calendars&controller=calendars&searchResult=form_new_cal_allow_comments",
"app=calendar&module=calendars&controller=calendars&searchResult=form_new_cal_allow_reviews",
"app=calendar&module=calendars&controller=calendars&searchResult=form_new_cal_color",
"app=calendar&module=calendars&controller=calendars&searchResult=form_new_cal_moderate",
"app=calendar&module=calendars&controller=calendars&searchResult=form_new_cal_title",
"app=calendar&module=calendars&controller=ical",
"app=calendar&module=calendars&controller=ical&do=add&searchResult=form_feed_allow_rsvp",
"app=calendar&module=calendars&controller=ical&do=add&searchResult=form_feed_calendar_id",
"app=calendar&module=calendars&controller=ical&do=add&searchResult=form_feed_member_id",
"app=calendar&module=calendars&controller=ical&do=add&searchResult=form_feed_title",
"app=calendar&module=calendars&controller=ical&do=add&searchResult=form_feed_url",
"app=calendar&module=calendars&controller=ical&do=upload&searchResult=form_feed_calendar_id",
"app=calendar&module=calendars&controller=ical&do=upload&searchResult=form_feed_file",
"app=calendar&module=calendars&controller=ical&do=upload&searchResult=form_feed_member_id",
"app=calendar&module=calendars&controller=settings",
"app=calendar&module=calendars&controller=settings&searchResult=calendar_rss_feed_days",
"app=calendar&module=calendars&controller=settings&searchResult=form_calendar_date_format",
"app=calendar&module=calendars&controller=settings&searchResult=form_calendar_default_view",
"app=calendar&module=calendars&controller=settings&searchResult=form_calendar_rss_feed",
"app=calendar&module=calendars&controller=settings&searchResult=form_calendar_venues_enabled",
"app=calendar&module=calendars&controller=settings&searchResult=form_ipb_calendar_mon",
"app=calendar&module=calendars&controller=settings&searchResult=form_show_bday_calendar"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,24 @@
{
"id": 105013,
"name": "4.5.0 Beta 1",
"steps": {
"queries": true,
"lang": true,
"theme": true,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": true,
"settings": true,
"tasks": true,
"modules": true,
"widgets": true,
"whatsnew": false,
"customOptions": false,
"customRoutines": true
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,18 @@
{
"files": {
"added": [],
"edited": [
"calendar\/front\/controllers\/browse\/ips.browse.main.js",
"calendar\/front\/controllers\/venue\/ips.venue.main.js",
"calendar\/front\/controllers\/view\/ips.view.reminderButton.js"
],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/\/jquery"
],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"normal": {
"added": [
"recur_human__xyearly",
"recur_human__xmonthly",
"recur_human__xweekly",
"recur_human__xdaily"
],
"edited": [
"event_auto_follow_suffix",
"recur_human_yearly_multi",
"recur_human_monthly_multi",
"recur_human_weekly_multi",
"recur_human_weekly_multi_days",
"recur_human_daily_multi"
],
"removed": []
},
"js": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,9 @@
{
"added": [
"admin\/calendars",
"admin\/venues",
"front\/calendar"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,187 @@
{
"1": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_recurring_end_date",
"type": "DATETIME",
"length": null,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "End date if this is a recurring event which ends",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"2": {
"method": "changeIndex",
"params": [
"calendar_events",
"recurring_events",
{
"type": "key",
"name": "recurring_events",
"columns": [
"event_recurring",
"event_recurring_end_date",
"event_approved",
"event_calendar_id",
"event_start_date"
],
"length": [
250,
null,
null,
null,
null
]
}
]
},
"3": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_timezone",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"4": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_edit_time",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"5": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_edit_member_name",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"6": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_appened_edit",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": true,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"7": {
"method": "changeColumn",
"params": [
"calendar_events",
"event_appened_edit",
{
"name": "event_append_edit",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": [],
"allow_null": true,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"8": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_edit_reason",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"9": {
"method": "changeColumn",
"params": [
"calendar_events",
"event_meta_data",
{
"name": "event_meta_data",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": [],
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"auto_increment": false
}
]
}
}
@@ -0,0 +1,17 @@
{
"added": [
"all_activity_calendar_streamitems",
"calendar_block_past_changes",
"calendar_date_format",
"calendar_date_format_custom",
"calendar_default_view",
"calendar_rss_feed",
"calendar_rss_feed_days",
"calendar_rss_feed_order",
"calendar_venues_enabled",
"ipb_calendar_mon",
"show_bday_calendar"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,8 @@
{
"added": [
"icalendar",
"eventreminders"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,51 @@
{
"html": {
"added": [],
"edited": [
"front\/browse\/calendarDay",
"front\/browse\/calendarFeatured",
"front\/browse\/calendarHeader",
"front\/browse\/calendarMonth",
"front\/browse\/calendarStream",
"front\/browse\/calendarWeek",
"front\/browse\/calendarWrapper",
"front\/browse\/dateJump",
"front\/global\/commentTableHeader",
"front\/global\/embedEvent",
"front\/global\/embedEventComment",
"front\/global\/embedEventReview",
"front\/global\/manageFollowRow",
"front\/global\/rows",
"front\/modcp\/approvalQueueItem",
"front\/submit\/datesForm",
"front\/submit\/submitForm",
"front\/venue\/upcomingStream",
"front\/view\/comments",
"front\/view\/eventBlock",
"front\/view\/eventBlocks",
"front\/view\/eventSidebar",
"front\/view\/eventStreamBlock",
"front\/view\/reviews",
"front\/view\/rsvpControls",
"front\/view\/view",
"front\/widgets\/recentReviews",
"front\/widgets\/upcomingEvents"
],
"removed": []
},
"css": {
"added": [],
"edited": [
"front\/calendar_responsive.css",
"front\/calendar.css",
"front\/embed.css",
"front\/profile.css"
],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,123 @@
<?php
/**
* @brief 4.5.0 Beta 1 Upgrade Code
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Calendar
* @since 19 Jul 2019
*/
namespace IPS\calendar\setup\upg_105013;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* 4.5.0 Beta 1 Upgrade Code
*/
class _Upgrade
{
/**
* Set the event recurring end date/time for recurring events that end
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step1()
{
$perCycle = 100;
$did = 0;
$limit = \intval( \IPS\Request::i()->extra );
/* Try to prevent timeouts to the extent possible */
$cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
foreach( \IPS\Db::i()->select( '*', 'calendar_events', array( 'event_recurring IS NOT NULL' ), 'event_id ASC', array( $limit, $perCycle ) ) as $event )
{
if( $cutOff !== null AND time() >= $cutOff )
{
return ( $limit + $did );
}
$did++;
$recurrenceRule = \IPS\calendar\Icalendar\ICSParser::parseRrule( $event['event_recurring'], 'UTC' );
$endDate = NULL;
/* Please be easy. Please be easy. */
if( $recurrenceRule['repeat_end_date'] )
{
$endDate = $recurrenceRule['repeat_end_date']->format( 'Y-m-d H:i' );
}
/* Ok, then check if occurrences limit is present... */
elseif( $recurrenceRule['repeat_end_occurrences'] )
{
switch( $recurrenceRule['event_repeats'] )
{
case 'daily':
$keyword = "days";
break;
case 'weekly':
$keyword = 'weeks';
break;
case 'monthly':
$keyword = "months";
break;
case 'yearly':
$keyword = "years";
break;
}
$period = new \DatePeriod( \IPS\calendar\Date::parseTime( $event['event_start_date'], $event['event_all_day'] ? FALSE : TRUE ), new \DateInterval( 'P' . $recurrenceRule['event_repeat_freq'] . mb_strtoupper( mb_substr( $keyword, 0, 1 ) ) ), $recurrenceRule['repeat_end_occurrences'] );
foreach( $period as $dateOccurrence )
{
$endDate = $dateOccurrence->format( 'Y-m-d H:i' );
}
}
if( $endDate !== NULL )
{
\IPS\Db::i()->update( 'calendar_events', array( 'event_recurring_end_date' => $endDate ), array( 'event_id=?', $event['event_id'] ) );
}
}
if( $did )
{
return ( $limit + $did );
}
else
{
unset( $_SESSION['_step1Count'] );
return TRUE;
}
}
/**
* Custom title for this step
*
* @return string
*/
public function step1CustomTitle()
{
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
if( !isset( $_SESSION['_step1Count'] ) )
{
$_SESSION['_step1Count'] = \IPS\Db::i()->select( 'COUNT(*)', 'calendar_events', array( 'event_recurring IS NOT NULL' ) )->first();
}
return "Upgrading recurring calendar events (Upgraded so far: " . ( ( $limit > $_SESSION['_step1Count'] ) ? $_SESSION['_step1Count'] : $limit ) . ' out of ' . $_SESSION['_step1Count'] . ')';
}
// You can create as many additional methods (step2, step3, etc.) as is necessary.
// Each step will be executed in a new HTTP request
}
@@ -0,0 +1,9 @@
{
"added": [
"todaysBirthdays",
"upcomingEvents",
"recentReviews"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,24 @@
{
"id": 105014,
"name": "4.5.0 Beta 1",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105015,
"name": "4.5.0 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,14 @@
{
"files": {
"added": [],
"edited": [],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/\/jquery"
],
"removed": []
}
}
@@ -0,0 +1,21 @@
{
"html": {
"added": [],
"edited": [
"front\/browse\/calendarHeader",
"front\/browse\/calendarWrapper",
"front\/view\/view"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105016,
"name": "4.5.0 Beta 3",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,19 @@
{
"html": {
"added": [],
"edited": [
"front\/browse\/calendarWrapper"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105017,
"name": "4.5.0 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,19 @@
{
"html": {
"added": [],
"edited": [
"front\/global\/commentTableHeader"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105018,
"name": "4.5.0 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105019,
"name": "4.5.0 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105020,
"name": "4.5.0 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105021,
"name": "4.5.0 Beta 5",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105022,
"name": "4.5.0 Beta 6",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105023,
"name": "4.5.0 Beta 6",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105024,
"name": "4.5.0 Beta 7",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,20 @@
{
"html": {
"added": [],
"edited": [
"front\/global\/rows",
"front\/global\/searchResultEventSnippet"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105025,
"name": "4.5.0 Beta 8",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105026,
"name": "4.5.0 Beta 8",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105027,
"name": "4.5.0 Beta 8",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105028,
"name": "4.5.0 Beta 9",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,19 @@
{
"html": {
"added": [],
"edited": [
"front\/view\/view"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105029,
"name": "4.5.0 Beta 10",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,19 @@
{
"html": {
"added": [],
"edited": [
"front\/view\/coverPhotoOverlay"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105030,
"name": "4.5.0 Beta 11",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105031,
"name": "4.5.0 Beta 11",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105032,
"name": "4.5.0 Beta 12",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105100,
"name": "4.5.0",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_32000;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -42,7 +42,7 @@ class _Upgrade
)
) );
if ( count( $toRun ) )
if ( \count( $toRun ) )
{
\IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 1 => 'calendar', 'extra' => array( '_upgradeStep' => 2 ) ) );
@@ -12,7 +12,7 @@
namespace IPS\calendar\setup\upg_40000;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -335,6 +335,11 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public function _saveClubForm( \IPS\Member\Club $club, $values )
{
if ( $values['club_node_name'] )
{
$this->title_seo = \IPS\Http\Url\Friendly::seoTitle( $values['club_node_name'] );
}
$this->allow_comments = $values['cal_allow_comments'];
$this->allow_reviews = $values['cal_allow_reviews'];
}
+20 -8
View File
@@ -12,7 +12,7 @@
namespace IPS\calendar;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -233,7 +233,7 @@ class _Date extends \IPS\DateTime
else
{
$validTimezone = TRUE;
if( in_array( \IPS\Member::loggedIn()->timezone, static::getTimezoneIdentifiers() ) )
if( \in_array( \IPS\Member::loggedIn()->timezone, static::getTimezoneIdentifiers() ) )
{
try
{
@@ -268,7 +268,7 @@ class _Date extends \IPS\DateTime
$datetime = new \IPS\DateTime( $datetime, $timezone );
/* Now correct it back if necessary */
if( $forceUTC === TRUE AND \IPS\Member::loggedIn()->timezone )
if( $forceUTC === TRUE AND \IPS\Dispatcher::hasInstance() AND \IPS\Member::loggedIn()->timezone )
{
$datetime->setTimezone( new \DateTimeZone( \IPS\Member::loggedIn()->timezone ) );
}
@@ -291,6 +291,11 @@ class _Date extends \IPS\DateTime
return static::getDate( gmdate( 'Y', $datetime->getTimestamp() ), gmdate( 'm', $datetime->getTimestamp() ), gmdate( 'd', $datetime->getTimestamp() ), gmdate( 'H', $datetime->getTimestamp() ), gmdate( 'i', $datetime->getTimestamp() ), gmdate( 's', $datetime->getTimestamp() ) );
}
/**
* @brief Cache results of getDayNames() for performance
*/
protected static $cachedDayNames = NULL;
/**
* Get the localized day names in correct order
*
@@ -299,6 +304,11 @@ class _Date extends \IPS\DateTime
*/
public static function getDayNames()
{
if( static::$cachedDayNames !== NULL )
{
return static::$cachedDayNames;
}
$dayNames = array();
$startDay = \IPS\Settings::i()->ipb_calendar_mon ? 'Monday' : 'Sunday';
@@ -310,6 +320,8 @@ class _Date extends \IPS\DateTime
$dayNames[] = array( 'full' => \IPS\Member::loggedIn()->language()->convertString( strftime( '%A', $_time ) ), 'english' => date( 'l', $_time ), 'abbreviated' => $_abbr, 'letter' => mb_substr( $_abbr, 0, 1 ), 'ical' => mb_strtoupper( mb_substr( date( 'D', $_time ), 0, 2 ) ) );
}
static::$cachedDayNames = $dayNames;
return $dayNames;
}
@@ -422,9 +434,9 @@ class _Date extends \IPS\DateTime
/* Make sure we have 3 pieces and that all are 2 digits */
$_timeBits = explode( ':', $time );
if ( count( $_timeBits ) < 3 )
if ( \count( $_timeBits ) < 3 )
{
while( count( $_timeBits ) < 3 )
while( \count( $_timeBits ) < 3 )
{
$_timeBits[] = '00';
}
@@ -768,7 +780,7 @@ class _Date extends \IPS\DateTime
* Returns whether the current locale uses AM/PM or 24 hour format
*
* @return bool
* @link <a href='http://stackoverflow.com/questions/6871258/how-to-determine-if-current-locale-has-24-hour-or-12-hour-time-format-in-php'>Check for 24 hour locale use</a>
* @see <a href='http://stackoverflow.com/questions/6871258/how-to-determine-if-current-locale-has-24-hour-or-12-hour-time-format-in-php'>Check for 24 hour locale use</a>
*/
public static function usesAmPm()
{
@@ -778,7 +790,7 @@ class _Date extends \IPS\DateTime
/**
* Get the 12 hour version of an hour value
*
* @param int Hour The hour value between 0 and 23
* @param int $hour The hour value between 0 and 23
* @return int
*/
public static function getTwelveHour( $hour )
@@ -800,7 +812,7 @@ class _Date extends \IPS\DateTime
/**
* Get the AM/PM value for the current locale
*
* @param int Hour The hour value between 0 and 23
* @param int $hour The hour value between 0 and 23
* @return string
*/
public static function getAmPm( $hour )
@@ -12,7 +12,7 @@
namespace IPS\calendar\Event;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
File diff suppressed because it is too large. Load diff
Loaded 100 of 3791 files, more files were not shown because too many files have changed in this diff. Show more