Version 4.2.0

This commit is contained in:
Neo committed 2025-12-19 05:44:59 -08:00
1 parent 0dc2aee5ed
commit 96997ddd8e
2074 files changed
+125454 -55780

No files matched your search

+2 -2
View File
@@ -2,8 +2,8 @@
/**
* @brief Calendar Application Class
* @author <a href=''>Invision Power Services, Inc.</a>
* @copyright (c) 2013 Invision Power Services, Inc.
* @package IPS Community Suite
* @copyright (c) Invision Power Services, Inc.
* @package Invision Community
* @subpackage Calendar
* @since 18 Dec 2013
* @version
+143
View File
@@ -0,0 +1,143 @@
<?php
/**
* @brief Calendars 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 3 Apr 2017
*/
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 Calendars API
*/
class _calendars extends \IPS\Node\Api\NodeController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Calendar';
/**
* GET /calendar/calendar
* Get list of calendars
*
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Calendar>
*/
public function GETindex()
{
/* Return */
return $this->_list();
}
/**
* GET /calendar/calendar/{id}
* Get specific calendar
*
* @param int $id ID Number
*
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Calendar>
*/
public function GETitem( $id )
{
/* Return */
return $this->_view( $id );
}
/**
* POST /calendar/calendar
* Create a calendar
*
* @reqapiparam string title The calendar title
* @apiparam string color The calendar color (Hexadecimal)
* @apiparam int approve_events 0|1 Events must be approved?
* @apiparam int allow_comments 0|1 Allow comments
* @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
*
* @return \IPS\calendar\Calendar
*/
public function POSTindex()
{
return $this->_create();
}
/**
* POST /calendar/calendar/{id}
* Edit a calendar
*
* @reqapiparam string title The calendar title
* @apiparam string color The calendar color (Hexadecimal)
* @apiparam int approve_events 0|1 Events must be approved?
* @apiparam int allow_comments 0|1 Allow comments
* @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
*
* @return \IPS\calendar\Calendar
*/
public function POSTitem( $id )
{
$class = static::$class;
$calendar = $class::load( $id );
$calendar = $this->_createOrUpdate( $calendar );
return $calendar;
}
/**
* DELETE /calendar/calendar/{id}
* Delete a calendar
*
* @param int $id ID Number
* @return void
*/
public function DELETEitem( $id )
{
return $this->_delete( $id );
}
/**
* Create or update node
*
* @param \IPS\node\Model $node 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 ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_calendar_' . $calendar->id, \IPS\Request::i()->title );
$calendar->title_seo = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->title );
}
if ( isset( \IPS\Request::i()->color ) )
{
$calendar->color = \IPS\Request::i()->color;
}
$calendar->moderate = (int) isset( \IPS\Request::i()->approve_events ) ? \IPS\Request::i()->approve_events : 0;
$calendar->allow_comments = (int) isset( \IPS\Request::i()->allow_comments ) ? \IPS\Request::i()->allow_comments : 0;
$calendar->comment_moderate = (int) isset( \IPS\Request::i()->approve_comments ) ? \IPS\Request::i()->approve_comments : 0;
$calendar->allow_reviews = (int) isset( \IPS\Request::i()->allow_reviews ) ? \IPS\Request::i()->allow_reviews : 0;
$calendar->review_moderate = (int) isset( \IPS\Request::i()->approve_reviews ) ? \IPS\Request::i()->approve_reviews : 0;
return parent::_createOrUpdate( $calendar );
}
}
+4 -5
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Events Comments API
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 8 Dec 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api;
+4 -5
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Events API
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 8 Dec 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api;
+4 -5
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Events Reviews API
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 8 Dec 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api;
+6
View File
@@ -6,6 +6,12 @@
"do": "",
"restriction": "calendars_manage"
},
"venues": {
"tab": "community",
"controller": "venues",
"do": "",
"restriction": "venues_manage"
},
"ical": {
"tab": "community",
"controller": "ical",
@@ -5,6 +5,7 @@
"calendars_add": "calendars_add",
"calendars_edit": "calendars_edit",
"calendars_permissions": "calendars_permissions",
"calendars_massManageContent": "calendars_massManageContent",
"calendars_delete": "calendars_delete"
},
"ical": {
@@ -16,5 +17,10 @@
"settings": {
"settings_manage": "settings_manage"
}
},
"venues": {
"venues": {
"venues_manage": "venues_manage"
}
}
}
@@ -217,6 +217,15 @@
"events rss"
]
},
"app=calendar&module=calendars&controller=settings&searchResult=form_calendar_venues_enabled": {
"lang_key": "calendar_venues_enabled",
"restriction": "settings_manage",
"keywords": [
"address",
"venue",
"venues"
]
},
"app=calendar&module=calendars&controller=settings&searchResult=form_ipb_calendar_mon": {
"lang_key": "ipb_calendar_mon",
"restriction": "settings_manage",
+58 -1
View File
@@ -1,5 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<emails><template><template_app>calendar</template_app><template_name>notification_new_content</template_name><template_content_html><![CDATA[
<emails><template><template_app>calendar</template_app><template_name>notification_event_reminder</template_name><template_content_html><![CDATA[
{$email->language->addToStack("email_event_reminder", FALSE, array( 'sprintf' => array( $email->language->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $daysToGo ) ) ), $content->url(), $content->mapped('title') ) ) )}
<br />
<br />
{$email->language->addToStack("email_event_reminder_when", FALSE, array( 'sprintf' => array( $content->fixedDateTimeDescription( $email->language ) ) ) )}
{{if $content->location}}
<br />
{$email->language->addToStack("email_event_reminder_where", FALSE, array( 'sprintf' => array( \IPS\GeoLocation::buildFromjson( $content->location )->toString() ) ) )}
{{endif}}
<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>
<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') ) ) )}
{$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("go_to_this_x", FALSE, array( 'sprintf' => array( mb_strtolower( $email->language->addToStack( $content::$title, FALSE ) ) ) ) )}: {$content->url()}
-- {setting="board_name"}]]></template_content_plaintext></template><template><template_app>calendar</template_app><template_name>notification_new_content</template_name><template_content_html><![CDATA[
{{if $content->author()->member_id}}
{$email->language->addToStack("email_new_calevent", FALSE, array( 'sprintf' => array( $content->author()->url(), $content->author()->name, $content->indefiniteArticle( $email->language ), $content->url(), $content->mapped('title'), $content->fixedDateTimeDescription( $email->language ) ) ) )}
{{else}}
+5
View File
@@ -83,6 +83,11 @@
"friendly": "submit",
"real": "app=calendar&module=calendar&controller=submit"
},
"calendar_venue": {
"friendly": "venue/{#id}-{?}",
"real": "app=calendar&module=calendar&controller=venue",
"verify": "\\IPS\\calendar\\Venue"
},
"calendar": {
"friendly": "",
"real": "app=calendar&module=calendar&controller=view"
+382 -16
View File
@@ -1,8 +1,8 @@
<?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="101099" javascript_position="1000050"><![CDATA[/**
* IPS Community Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="102002" javascript_position="1000050"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.browse.main.js - Calendar main browsing controller
*
@@ -112,9 +112,9 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="101099" javascript_position="1000050"><![CDATA[/**
* IPS Community Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="102002" javascript_position="1000050"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.browse.monthView.js - Month view controller
*
@@ -254,9 +254,9 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="101099" javascript_position="1000100"><![CDATA[/**
* IPS Community Suite 4
* (c) 2013 Invision Power Services - http://www.invisionpower.com
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="102002" javascript_position="1000100"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.submit.dates.js - Helper for date selection enhancements
*
@@ -268,6 +268,8 @@
ips.controller.register('calendar.front.submit.dates', {
initialize: function () {
this._hasFocusedEventEnd = false;
this.on( 'click', '[data-action="updateTimezone"]', this.updateTimezone );
// Monitor focus in recurring event input fields and select appropriate radio button
@@ -275,26 +277,74 @@
this.on( 'focus', 'input[name="repeat_end_date"]', function(){ $('#event_repeat_end_ondate').prop('checked', true); } );
this.on( 'change', 'input, select', this.checkForSummaryChange );
this.on( 'change', 'input, select', this.setEndDate );
this.on( 'change', '#check_single_day, #check_all_day', this.toggleFields );
this.on( 'click', '#elRecurRemove', this.disableRecurring );
this.on( 'change', 'input[name="event_dates[start_date]"]', this.setEndDateOnStartChange );
this.on( 'change', '#event_end_date', this.setHasFocusedEventOnEndChange );
$( window ).on( 'resize', _.bind( this._resizeEndGrid, this ) );
this.on( 'click', '[data-action="updateRepeat"]', this.finishRepeat );
this._checkAndSetEventEndState();
this.setup();
},
/**
* Set the end date for single & all day event
* On page load check to see what the current state of the end date is. If its set lets just go ahead and ignore any start date changes
*
* @returns {void}
*/
setEndDate: function() {
var singleDay = this.scope.find('#check_single_day');
var allDay = this.scope.find('#check_all_day');
_checkAndSetEventEndState: function() {
var eventEndDate = $("#event_end_date");
var date = eventEndDate.val();
if( singleDay.is(':checked') && !allDay.is(':checked') ) {
this.scope.find('input[name="event_dates[end_date]"]').val( this.scope.find('input[name="event_dates[start_date]"]').val() )
if (!this._hasFocusedEventEnd && this._isValidEndDate(date)) {
this._hasFocusedEventEnd = true;
}
},
/**
* Is the date passed in a valid date?
*
* @param {date} date Date to check
* @returns {boolean}
*/
_isValidEndDate: function(date) {
var tempDate = new Date(date);
if(!isNaN(tempDate.getDate())) {
return true;
}
return false;
},
/**
* If the end field has changed from input go ahead and ignore any start date changes
*
* @returns {void}
*/
setHasFocusedEventOnEndChange: function() {
this._hasFocusedEventEnd = true;
},
/**
* Event handler, handles changes to the start date
*
* @returns {void}
*/
setEndDateOnStartChange: function() {
var isSameDay = $("#check_single_day").is(":checked");
var eventStartDate = $('input[name="event_dates[start_date]');
var eventEndDate = $("#event_end_date");
if(!isSameDay && !this._hasFocusedEventEnd) {
if( ips.utils.time.supportsHTMLDate() ) {
eventEndDate.val(eventStartDate.val());
}
}
},
@@ -614,6 +664,320 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="102002" javascript_position="1000150"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.venue.main.js - Venue main browsing controller
*
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('calendar.front.venue.main', {
_ajaxObj: null,
initialize: function () {
this.on( 'click', '[data-action="changeView"]', this.changeView );
this.on( window, 'statechange', this.stateChange );
this.setup();
},
/**
* Controller setup method
*
* @returns {void}
*/
setup: function () {
History.pushState( { controller: 'venueView' }, document.title, window.location.href );
},
/**
* Changes the calendar view dynamically
*
* @param {event} e Event object
* @returns {void}
*/
changeView: function (e) {
e.preventDefault();
// Load the url via ajax instead
var self = this;
var title = $( e.currentTarget ).attr('title');
var url = $( e.currentTarget ).attr('href');
History.pushState( { controller: 'venueView' }, title, url );
},
/**
* Event handler for history state changes
*
* @param {event} e Event object
* @returns {void}
*/
stateChange: function () {
var state = History.getState();
if( _.isUndefined( state.data.controller ) || state.data.controller != 'venueView' ) {
return;
}
// Track page view
ips.utils.analytics.trackPageView( state.url );
this._updateView( state.url, state.title )
},
/**
* Loads a new view
*
* @param {string} url URL to load
* @param {string} title New browser title
* @returns {void}
*/
_updateView: function (url, title) {
var self = this;
if( this._ajaxObj && _.isFunction( this._ajaxObj.abort ) ){
this._ajaxObj.abort();
}
this._setLoading( true );
this._ajaxObj = ips.getAjax()( url, {
showLoading: true
} )
.done( function (response) {
console.log( response );
self.scope.html( response );
$( document ).trigger( 'contentChange', [ self.scope ] );
History.pushState( { controller: 'venueView' }, title, url );
})
.always( function () {
self._setLoading( false );
});
},
/**
* Toggles the loading state on the view
*
* @param {boolean} state Enable the loading state?
* @returns {void}
*/
_setLoading: function (state) {
if( state ){
this.scope.animate( { opacity: 0.6 }, 'fast' );
} else {
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="102002" javascript_position="1000200"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.calendar.reminderButton.js - Controller for event reminder button
*
* Author: Andrew Millne
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('calendar.front.view.reminderButton', {
initialize: function () {
this.setup();
this.on( document, 'reminderItem', this.reminderItemChange );
},
setup: function () {
this._id = this.scope.attr('data-reminderID');
this._button = this.scope.find('[data-role="reminderButton"]');
},
/**
* Responds to events indicating the reminder status has changed
*
* @param {event} e Event object
* @param {object} data Event data object
* @returns {void}
*/
reminderItemChange: function (e, data) {
this._reloadButton();
},
/**
* Gets a new reminder button from the server and replaces the current one with the response
*
* @returns {void}
*/
_reloadButton: function () {
// Show button as loading
this._button.addClass('ipsFaded ipsFaded_more');
var self = this;
var pos = ips.utils.position.getElemPosition( this._button );
var dims = ips.utils.position.getElemDims( this._button );
this.scope.append( ips.templates.render('calendar.reminder.loading') );
// Adjust sizing
this.scope
.css({
position: 'relative'
})
.find('.ipsLoading')
.css({
width: dims.outerWidth + 'px',
height: dims.outerHeight + 'px',
top: 0,
left: 0,
position: 'absolute',
zIndex: ips.ui.zIndex()
});
// Load new contents
ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=calendar&module=calendar&controller=event&do=reminderButton', {
data: _.extend({
id: this._id
}, ( this.scope.attr('data-buttonType') ) ? { button_type: this.scope.attr('data-buttonType') } : {} )
})
.done( function (response) {
self.scope.html( response );
$( document ).trigger( 'contentChange', [ self.scope ] );
})
.fail( function () {
self._button.removeClass('ipsFaded ipsFaded_more');
})
.always( function () {
self.scope.find('.ipsLoading').remove();
});
}
});
}(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="102002" javascript_position="1000200">/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.calendar.reminderButton.js - Controller for reminder button
*
* Author: Andrew Millne
*/
;( function($, _, undefined){
&quot;use strict&quot;;
ips.controller.register('calendar.front.view.reminderForm', {
initialize: function () {
this.on( 'submit', this.submitForm );
this.on( 'click', '[data-action=&quot;removereminder&quot;]', this.removereminder );
this.setup();
},
/**
* Setup method
*
* @returns {void}
*/
setup: function () {
},
/**
* Event handler for removing reminder
*
* @param {event} e Event object
* @returns {void}
*/
removereminder: function (e) {
e.preventDefault();
this._doRemindAction( $( e.currentTarget ).attr('href'), {}, true );
},
/**
* Event handler for submitting the reminder form
*
* @param {event} e Event object
* @returns {void}
*/
submitForm: function (e) {
e.preventDefault();
this._doRemindAction( this.scope.attr('action'), this.scope.serialize(), false );
},
/**
* Performs an ajax action.
*
* @param {string} url URL to call
* @param {object} data Object of data to include in the request
* @returns {void}
*/
_doRemindAction: function (url, data, removereminder ) {
var self = this;
var dims = ips.utils.position.getElemDims( this.scope.parent('div') );
// Set it to loading
this.scope
.hide()
.parent('div')
.css({
width: dims.outerWidth + 'px',
height: dims.outerHeight + 'px'
})
.addClass('ipsLoading');
// Update reminder preference via ajax
ips.getAjax()( url, {
data: data,
type: 'post'
})
.done( function (response, status, jqXHR) {
if( jqXHR.getAllResponseHeaders().indexOf('X-IPS-FormError: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('X-IPS-FormNoSubmit: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('x-ips-formerror: true') !== -1 || jqXHR.getAllResponseHeaders().indexOf('x-ips-formnosubmit: true') !== -1 ){
self.scope
.show()
.html( response )
.parent('div')
.removeClass('ipsLoading')
.css({
width: 'auto',
height: 'auto'
});
} else {
// Success, so trigger event to update button
self.trigger('reminderItem');
if( removereminder ) {
ips.ui.flashMsg.show(ips.getString('event_reminder_removed'));
}
else {
ips.ui.flashMsg.show(ips.getString('event_reminder_added'));
}
self.scope.parents('.ipsHovercard').remove();
}
})
.fail( function (jqXHR, textStatus, errorThrown) {
window.location = url;
})
.always( function () {
// If we're in a hovercard, remove it
});
}
});
}(jQuery, _));
</file>
<file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="102002" javascript_position="1000250"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*/
/* REMINDER BUTTON LOADING */
ips.templates.set('calendar.reminder.loading', " \
<div class='ipsLoading ipsLoading_tiny'></div>\
");]]></file>
<order app="global" path="/dev/js//framework/">templates
common/ips.loader.js
common/ui
@@ -629,4 +993,6 @@ app.js</order>
<order app="global" path="/dev/js//library//jquery">jquery.js
jquery.history.js
jquery.transform.js</order>
<order app="global" path="/dev/js//library//linkify">linkify.min.js
linkify-jquery.min.js</order>
</javascript>
+58 -3
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<language>
<app key="calendar" version="101099">
<app key="calendar" version="102002">
<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>
@@ -17,9 +17,11 @@
<word key="module__calendar_calendar" js="0">Calendar</word>
<word key="module__calendar_calendars" js="0">Calendars</word>
<word key="module__calendar_events" js="0">Events</word>
<word key="menu__calendar_venues" js="0">Venues</word>
<word key="event" js="0">Event</word>
<word key="editor__calendar_Events" js="0">Calendar Events</word>
<word key="editor__calendar_Calendar" js="0">Calendars</word>
<word key="editor__calendar_Venue" js="0">Venues</word>
<word key="acp_search_title_calendar_Calendars" js="0">Calendars</word>
<word key="calendar_event_pl_lc" js="0">calendar events</word>
<word key="search_contextual_item_calendars" js="0">This Calendar</word>
@@ -29,6 +31,7 @@
<word key="r__calendars_add" js="0">Can add calendars?</word>
<word key="r__calendars_edit" js="0">Can edit calendars?</word>
<word key="r__calendars_permissions" js="0">Can manage calendar permissions?</word>
<word key="r__calendars_massManageContent" js="0">Can mass move/delete events in calendars?</word>
<word key="r__calendars_delete" js="0">Can delete calendars?</word>
<word key="r__ical" js="0">iCalendar Feeds</word>
<word key="r__calendar_feeds_manage" js="0">Can manage iCalendar feed imports?</word>
@@ -92,6 +95,7 @@
<word key="can_feature_calendar_event" js="0">Can feature events?</word>
<word key="can_unfeature_calendar_event" js="0">Can unfeature events?</word>
<word key="can_move_calendar_event" js="0">Can move events?</word>
<word key="can_move_calendar_event_desc" js="0">Will be able to move events only between the calendars they have permission to moderate, not to any other calendar.</word>
<word key="can_lock_calendar_event" js="0">Can lock events?</word>
<word key="can_unlock_calendar_event" js="0">Can unlock events?</word>
<word key="can_reply_to_locked_calendar_event" js="0">Can comment on locked events?</word>
@@ -110,6 +114,11 @@
<word key="can_unhide_calendar_event_review" js="0">Can unhide reviews?</word>
<word key="can_view_hidden_calendar_event_review" js="0">Can view hidden reviews?</word>
<word key="can_delete_calendar_event_review" js="0">Can delete reviews?</word>
<word key="can_feature_comments_calendar_event" js="0">Can recommend comments on events?</word>
<word key="can_unfeature_comments_calendar_event" js="0">Can remove comments recommendations on events?</word>
<word key="can_add_item_message_calendar_event" js="0">Can add messages to events?</word>
<word key="can_edit_item_message_calendar_event" js="0">Can edit messages on events?</word>
<word key="can_delete_item_message_calendar_event" js="0">Can delete messages on events?</word>
<word key="ical_title" js="0">iCalendar Feed Imports</word>
<word key="ical_feed_title" js="0">Title</word>
<word key="ical_feed_added" js="0">Added</word>
@@ -176,8 +185,8 @@
<word key="calendar_event_comment_pl_lc" js="0">event comments</word>
<word key="calendar_event_review_pl" js="0">Event Reviews</word>
<word key="calendar_event_review_pl_lc" js="0">event reviews</word>
<word key="event_review_count" js="0"><![CDATA[<span id='reviewCount'>{#}</span> {!# [1:Review][?:Reviews]}]]></word>
<word key="event_comment_count" js="0"><![CDATA[<span id='commentCount'>{#}</span> {!# [1:Comment][?:Comments]}]]></word>
<word key="event_review_count" js="0">{# [1:Review][?:Reviews]}</word>
<word key="event_comment_count" js="0">{# [1:Comment][?:Comments]}</word>
<word key="event_rsvp_attendees_list" js="0">{# [1:user has][?:users have]} RSVPed{!#[0: ][?:, including]}</word>
<word key="calendar_rss_title" js="0">Upcoming Events</word>
<word key="submit_event" js="0">Submit an event</word>
@@ -230,6 +239,8 @@
<word key="submit_event_repeats" js="0">Repeats</word>
<word key="submit_event_remove_repeat" js="0">remove</word>
<word key="add_cal_event_header" js="0">Add Calendar Event</word>
<word key="copy_cal_event" js="0">Copy Calendar Event</word>
<word key="copy_cal_event_header" js="0">Copy %s</word>
<word key="calendar_jump" js="0">Go</word>
<word key="calendar_jump_today" js="0">Go to today</word>
<word key="jump_to_placeholder" js="0">Jump to...</word>
@@ -237,8 +248,10 @@
<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_arent_going" js="0">You aren't going</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>
@@ -272,6 +285,7 @@
<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>
<word key="add_similar_event" js="0">Add Similar Event</word>
<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>
@@ -320,6 +334,14 @@
<word key="lock_title_event" js="0">Lock this event</word>
<word key="unlock_title_event" js="0">Unlock this event</word>
<word key="approve_title_event" js="0">Approve this event</word>
<word key="event_set_reminder" js="0">Set Reminder</word>
<word key="event_set_reminder_tip" js="0">Remind me when this event is approaching</word>
<word key="event_edit_reminder" js="0">Update Reminder</word>
<word key="event_dont_remind" js="0">Delete Reminder</word>
<word key="event_remind_me" js="0">Remind me</word>
<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="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>
@@ -385,6 +407,7 @@
<word key="digest_area_calendar_event" js="0">Event</word>
<word key="x_created_event_in" js="0">%s posted an event in %s</word>
<word key="x_commented_event" js="0">%s commented on an event</word>
<word key="x_reviewed_event" js="0">%s reviewed an event</word>
<word key="digest_event_on" js="0">Event on</word>
<word key="digest_users_going" js="0">{# [1:user][?:users]} going</word>
<word key="mailsub__calendar_notification_new_content" js="0"><![CDATA[{$content->mapped("title")|raw}]]></word>
@@ -394,6 +417,36 @@
<word key="__api_calendar_events" js="0">Events</word>
<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="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="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>
<word key="email_event_reminder_when" js="0">When: %s</word>
<word key="email_event_reminder_where" js="0">Where: %s</word>
<word key="days_to_go" js="0">{# [1:day][?:days]}</word>
<word key="notification__event_reminder" js="0">Less than %s to go until %s</word>
<word key="menu__calendar_calendars_venues" js="0">Venues</word>
<word key="venues" js="0">Venues</word>
<word key="venue_title" js="0">Venue Name</word>
<word key="event_venue" js="0">Venue</word>
<word key="venues_not_listed" js="0">Venue not listed</word>
<word key="venue_address" js="0">Address</word>
<word key="r__venues" js="0">Venues</word>
<word key="r__venues_manage" js="0">Can Manage Venues</word>
<word key="module__venues_view" js="0">Venues</word>
<word key="editor__venues_Venue" js="0">Venue Description</word>
<word key="venue_description" js="0">Description</word>
<word key="calendar_venues_enabled" js="0">Enable Venues</word>
<word key="calendar_venues_enabled_desc" js="0">When enabled, administrators can create pre-defined venues that can be selected when creating events.</word>
<word key="calendar_more_events_at_x" js="0">More Events At This Venue</word>
<word key="venue_details" js="0">About the Venue</word>
<word key="venue_upcoming_events" js="0">Upcoming Events</word>
<word key="feed_venue_id" js="0">Venue</word>
<word key="event_new_venue" js="0">Save location as a new Venue?</word>
<word key="x_daily" js="1">{# [1:day][?:days]}</word>
<word key="x_weekly" js="1">{# [1:week][?:weeks]}</word>
<word key="x_monthly" js="1">{# [1:month][?:months]}</word>
@@ -418,5 +471,7 @@
<word key="not_single_not_allday" js="1"><![CDATA[From <strong>{{startDate}}</strong> at <strong>{{startTime}}</strong> until <strong>{{endDate}}</strong> at <strong>{{endTime}}</strong>]]></word>
<word key="not_single_allday" js="1"><![CDATA[From <strong>{{startDate}}</strong> to <strong>{{endDate}}</strong>]]></word>
<word key="select_time" js="1">(select time)</word>
<word key="event_reminder_removed" js="1">Reminder Removed</word>
<word key="event_reminder_added" js="1">Reminder Saved</word>
</app>
</language>
+5 -1
View File
@@ -3,12 +3,16 @@
"calendars": {
"default_controller": null,
"protected": 0
},
"venues": {
"default_controller": "",
"protected": false
}
},
"front": {
"calendar": {
"default_controller": "view",
"protected": false
"protected": 0
}
}
}
+278 -1
View File
@@ -127,6 +127,34 @@
"zerofill": false,
"auto_increment": false,
"binary": false
},
"cal_club_id": {
"name": "cal_club_id",
"type": "BIGINT",
"length": "20",
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "The club ID if this calendar belongs to a club, or NULL",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"cal_calendar_bitoptions": {
"name": "cal_calendar_bitoptions",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
@@ -965,6 +993,34 @@
"unsigned": true,
"values": [],
"zerofill": false
},
"event_venue": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 5,
"name": "event_venue",
"type": "INT",
"unsigned": true,
"values": [],
"zerofill": false
},
"event_meta_data": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": 0,
"length": 1,
"name": "event_meta_data",
"type": "BIT",
"unsigned": false,
"values": [],
"zerofill": false
}
},
"indexes": {
@@ -1045,9 +1101,20 @@
"columns": [
"event_ip_address"
]
},
"event_venue": {
"type": "key",
"name": "event_venue",
"columns": [
"event_venue"
],
"length": [
null
]
}
},
"collation": "utf8mb4_unicode_ci"
"collation": "utf8mb4_unicode_ci",
"engine": "InnoDB"
},
"calendar_import_feeds": {
"name": "calendar_import_feeds",
@@ -1177,6 +1244,20 @@
"unsigned": true,
"values": [],
"zerofill": false
},
"feed_venue_id": {
"name": "feed_venue_id",
"type": "INT",
"length": 5,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
@@ -1582,5 +1663,201 @@
]
}
}
},
"calendar_event_reminders": {
"name": "calendar_event_reminders",
"columns": {
"reminder_id": {
"name": "reminder_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "ID Number",
"unsigned": true,
"zerofill": false,
"auto_increment": true,
"binary": false
},
"reminder_event_id": {
"name": "reminder_event_id",
"type": "BIGINT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "Event to remind about",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_member_id": {
"name": "reminder_member_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "Member to notify",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_date": {
"name": "reminder_date",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "Timestamp after which to send notification",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_days_before": {
"name": "reminder_days_before",
"type": "INT",
"length": 2,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"columns": [
"reminder_id"
],
"length": [
null
]
},
"reminder": {
"type": "key",
"name": "reminder",
"columns": [
"reminder_event_id",
"reminder_member_id"
],
"length": [
null,
null
]
},
"date": {
"type": "key",
"name": "date",
"columns": [
"reminder_date"
],
"length": [
null
]
}
}
},
"calendar_venues": {
"name": "calendar_venues",
"columns": {
"venue_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
"comment": "ID Number",
"decimals": null,
"default": null,
"length": 20,
"name": "venue_id",
"type": "BIGINT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_position": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 5,
"name": "venue_position",
"type": "INT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_enabled": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "1",
"length": 1,
"name": "venue_enabled",
"type": "TINYINT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_title_seo": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "venue_title_seo",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"venue_address": {
"name": "venue_address",
"type": "TEXT",
"length": 0,
"decimals": null,
"values": [],
"allow_null": true,
"default": "",
"comment": "Physical Address",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"venue_id"
]
}
}
}
}
+8
View File
@@ -1,4 +1,8 @@
[
{
"key": "all_activity_calendar_streamitems",
"default": "1"
},
{
"key": "calendar_date_format",
"default": "d_lm_y"
@@ -19,6 +23,10 @@
"key": "calendar_rss_feed_days",
"default": "30"
},
{
"key": "calendar_venues_enabled",
"default": "0"
},
{
"key": "ipb_calendar_mon",
"default": "1"
+1 -1
View File
@@ -1 +1 @@
{"icalendar":"P0Y0M0DT4H0M0S"}
{"icalendar":"P0Y0M0DT4H0M0S","eventreminders":"P0Y0M0DT1H0M0S"}
File diff suppressed because it is too large. Load diff
+22 -1
View File
@@ -149,5 +149,26 @@
"101096": "4.1.19.2",
"101097": "4.1.19.2",
"101098": "4.1.19.3",
"101099": "4.1.19.4"
"101099": "4.1.19.4",
"101100": "4.2.0 Beta 1",
"101101": "4.2.0 Beta 1",
"101102": "4.2.0 Beta 1",
"101103": "4.2.0 Beta 1",
"101104": "4.2.0 Beta 2",
"101105": "4.2.0 Beta 3",
"101106": "4.2.0 Beta 3a",
"101107": "4.2.0 Beta 4",
"101108": "4.2.0 Beta 4",
"101109": "4.2.0 Beta 5",
"101110": "4.2.0 Beta 5a",
"101111": "4.2.0 Beta 6",
"101112": "4.2.0 Beta 6a",
"101113": "4.2.0 Beta 6a",
"101114": "4.2.0 Beta 7",
"101115": "4.2.0 Beta 7a",
"101116": "4.2.0 Beta 8",
"101117": "4.2.0 Beta 8",
"102000": "4.2.0",
"102001": "4.2.0",
"102002": "4.2.0"
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief Announcements Extension: Calendar
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 29 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\Announcements;
@@ -1,13 +1,12 @@
<?php
/**
* @brief Content Router extension: Calendar
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\ContentRouter;
@@ -32,10 +31,10 @@ class _Calendar
/**
* Constructor
*
* @param \IPS\Member|NULL $member If checking access, the member to check for, or NULL to not check access
* @param \IPS\Member|IPS\Member\Group|NULL $member If checking access, the member/group to check for, or NULL to not check access
* @return void
*/
public function __construct( \IPS\Member $member = NULL )
public function __construct( $member = NULL )
{
if ( $member === NULL or $member->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar', 'front' ) ) )
{
@@ -1,13 +1,12 @@
<?php
/**
* @brief Create Menu Extension
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 23 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\CreateMenu;
@@ -1,13 +1,12 @@
<?php
/**
* @brief Editor Extension: Event text
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\EditorLocations;
@@ -0,0 +1,77 @@
<?php
/**
* @brief Editor Extension: Venue
* @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 Venues
* @since 10 Feb 2017
*/
namespace IPS\calendar\extensions\core\EditorLocations;
/* 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;
}
/**
* Editor Extension: Venue
*/
class _Venue
{
/**
* Can we use HTML in this editor?
*
* @param \IPS\Member $member The member
* @return bool|null NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
*/
public function canUseHtml( $member )
{
return NULL;
}
/**
* Can we use attachments in this editor?
*
* @param \IPS\Member $member The member
* @param \IPS\Helpers\Form\Editor $field The editor field
* @return bool|null NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
*/
public function canAttach( $member, $field )
{
return FALSE;
}
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
{
return TRUE;
}
/**
* Attachment lookup
*
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @return \IPS\Http\Url|\IPS\Content|\IPS\Node\Model
* @throws \LogicException
*/
public function attachmentLookup( $id1, $id2, $id3 )
{
// return \IPS\Http\Url::internal( ... );
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief File Storage Extension: Events
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 13 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\FileStorage;
@@ -81,7 +80,7 @@ class _Events
/**
* Check if a file is valid
*
* @param \IPS\Http\Url $file The file to check
* @param string $file The file path to check
* @return bool
*/
public function isValidFile( $file )
@@ -1,13 +1,12 @@
<?php
/**
* @brief Front Navigation Extension: Calendar
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 23 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\FrontNavigation;
@@ -71,6 +70,6 @@ class _Calendar extends \IPS\core\FrontNavigation\FrontNavigationAbstract
*/
public function active()
{
return \IPS\Dispatcher::i()->application->directory === 'calendar';
return !\IPS\core\FrontNavigation::$clubTabActive and \IPS\Dispatcher::i()->application->directory === 'calendar';
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief ACP Live Search Extension
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 08 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\LiveSearch;
@@ -54,7 +53,7 @@ class _Calendars
$calendars = \IPS\Db::i()->select(
"*",
'calendar_calendars',
array( "word_custom LIKE CONCAT( '%', ?, '%' ) AND lang_id=?", $searchTerm, \IPS\Member::loggedIn()->language()->id ),
array( "cal_club_id IS NULL AND word_custom LIKE CONCAT( '%', ?, '%' ) AND lang_id=?", $searchTerm, \IPS\Member::loggedIn()->language()->id ),
NULL,
NULL
)->join(
@@ -1,13 +1,12 @@
<?php
/**
* @brief Member Sync
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\MemberSync;
@@ -36,6 +35,7 @@ class _Calendar
\IPS\Db::i()->update( 'calendar_event_rsvp', array( 'rsvp_member_id' => $member->member_id ), array( 'rsvp_member_id=?', $member2->member_id ), array(), NULL, \IPS\Db::IGNORE );
\IPS\Db::i()->update( 'calendar_import_feeds', array( 'feed_member_id' => $member->member_id ), array( 'feed_member_id=?', $member2->member_id ) );
\IPS\Db::i()->update( 'calendar_events', array( 'event_approved_by' => $member->member_id ), array( 'event_approved_by=?', $member2->member_id ) );
\IPS\Db::i()->update( 'calendar_event_reminders', array( 'reminder_member_id' => $member->member_id ), array( 'reminder_member_id=?', $member2->member_id ) );
}
/**
@@ -49,5 +49,6 @@ class _Calendar
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_member_id=?', $member->member_id ) );
\IPS\Db::i()->update( 'calendar_import_feeds', array( 'feed_member_id' => 0 ), array( 'feed_member_id=?', $member->member_id ) );
\IPS\Db::i()->update( 'calendar_events', array( 'event_approved_by' => 0 ), array( 'event_approved_by=?', $member->member_id ) );
\IPS\Db::i()->delete( 'calendar_event_reminders', array( 'reminder_member_id=?', $member->member_id ) );
}
}
@@ -1,12 +1,11 @@
<?php
/**
* @brief Notification Options
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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
* @since 20 May 2016
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\Notifications;
@@ -31,7 +30,9 @@ class _Events
*/
public function getConfiguration( $member )
{
return array();
return array(
'event_reminder' => array( 'default' => array( 'email' ), 'disabled' => array() ),
);
}
/**
@@ -66,4 +67,37 @@ class _Events
'unread' => (bool) ( $item->unread() )
);
}
/**
* Parse notification: Event reminder
*
* @param \IPS\Notification\Inline $notification The notification
* @return array
* @code
return array(
'title' => "Mark has replied to A Topic", // The notification title
'url' => new \IPS\Http\Url( ... ), // The URL the notification should link to
'content' => "Lorem ipsum dolar sit", // [Optional] Any appropriate content. Do not format this like an email where the text
// explains what the notification is about - just include any appropriate content.
// For example, if the notification is about a post, set this as the body of the post.
'author' => \IPS\Member::load( 1 ), // [Optional] The user whose photo should be displayed for this notification
);
* @endcode
*/
public function parse_event_reminder( $notification )
{
$item = $notification->item;
if ( !$item )
{
throw new \OutOfRangeException;
}
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') ) ) ),
'url' => $notification->item->url(),
'content' => $notification->item->content(),
'author' => $notification->item->author(),
'unread' => (bool) ( $item->unread() )
);
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief Permissions
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 16 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\extensions\core\Permissions;
@@ -0,0 +1,64 @@
<?php
/**
* @brief Activity stream items extension: StreamItems
* @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 21 Feb 2017
*/
namespace IPS\calendar\extensions\core\StreamItems;
/* 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 Activity stream items extension: StreamItems
*/
class _StreamItems
{
/**
* Is there content to display?
*
* @param \IPS\Member|NULL $author The author to limit extra items to
* @param Timestamp|NULL $lastTime If provided, only items since this date are included. If NULL, it works out which to include based on what results are being shown
* @param Timestamp|NULL $firstTime If provided, only items before this date are included. If NULL, it works out which to include based on what results are being shown
* @return array Array of \IPS\Content\Search\Result\Custom objects
*/
public function extraItems( $author=NULL, $lastTime=NULL, $firstTime=NULL )
{
$rsvps = array();
/* RSVP */
$where = array( array( 'rsvp_date>? and calendar_event_rsvp.rsvp_response=?', $lastTime, 1 ) );
if ( $firstTime )
{
$where[] = array( 'rsvp_date<?', $firstTime );
}
if ( $author )
{
$where[] = array( 'calendar_event_rsvp.rsvp_member_id=?', $author->member_id );
}
foreach ( \IPS\Db::i()->select( '*', 'calendar_event_rsvp', $where, 'rsvp_date DESC', 10 ) as $rsvp )
{
$member = \IPS\Member::load( $rsvp['rsvp_member_id'] );
$event = \IPS\calendar\Event::load( $rsvp[ 'rsvp_event_id' ] );
$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(), $event->title ) ) ) );
}
/* Return */
if ( !empty( $rsvps ) )
{
return $rsvps;
}
return array();
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendars
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\admin\calendars;
@@ -1,13 +1,12 @@
<?php
/**
* @brief iCalendar feed management
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\admin\calendars;
@@ -130,25 +129,25 @@ class _ical extends \IPS\Dispatcher\Controller
/* Root buttons */
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'calendar', 'calendars', 'calendar_feeds_add' ) )
{
$table->rootButtons = array(
'add' => array(
'icon' => 'plus',
'title' => 'calendar_feeds_add',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=add' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('calendar_feeds_add') )
),
'upload' => array(
'icon' => 'upload',
'title' => 'calendar_feeds_upload',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=upload' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('calendar_feeds_upload') )
),
\IPS\Output::i()->sidebar['actions']['add'] = array(
'primary' => true,
'icon' => 'plus',
'title' => 'calendar_feeds_add',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=add' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('calendar_feeds_add') )
);
\IPS\Output::i()->sidebar['actions']['upload'] = array(
'icon' => 'upload',
'title' => 'calendar_feeds_upload',
'link' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=upload' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('calendar_feeds_upload') )
);
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('ical_title');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table );
\IPS\Output::i()->output = (string) $table;
}
/**
@@ -169,6 +168,10 @@ class _ical extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\Text( 'feed_title', NULL, TRUE ) );
$form->add( new \IPS\Helpers\Form\Url( 'feed_url', NULL, TRUE, array( 'allowedProtocols' => array( 'http', 'https', 'webcal', 'webcals' ) ) ) );
$form->add( new \IPS\Helpers\Form\Node( 'feed_calendar_id', NULL, TRUE, array( 'class' => 'IPS\calendar\Calendar', 'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=add', 'admin' ) ) ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$form->add( new \IPS\Helpers\Form\Node( 'feed_venue_id', NULL, FALSE, array( 'class' => 'IPS\calendar\Venue', 'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=add', 'admin' ) ) ) );
}
$form->add( new \IPS\Helpers\Form\Member( 'feed_member_id', NULL, TRUE, array() ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'feed_allow_rsvp', NULL, FALSE ) );
@@ -194,6 +197,12 @@ class _ical extends \IPS\Dispatcher\Controller
$feed->title = $values['feed_title'];
$feed->url = $values['feed_url'];
$feed->calendar_id = $values['feed_calendar_id']->_id;
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$feed->venue_id = $values['feed_venue_id']->_id;
}
$feed->member_id = $values['feed_member_id']->member_id;
$feed->allow_rsvp = $values['feed_allow_rsvp'];
$feed->save();
@@ -230,6 +239,13 @@ class _ical extends \IPS\Dispatcher\Controller
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=upload' ),
'class' => 'IPS\calendar\Calendar',
) ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$form->add( new \IPS\Helpers\Form\Node( 'feed_venue_id', NULL, TRUE, array(
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=upload' ),
'class' => 'IPS\calendar\Venue',
) ) );
}
$form->add( new \IPS\Helpers\Form\Member( 'feed_member_id', NULL, TRUE ) );
/* Handle submissions */
@@ -239,7 +255,7 @@ 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'] );
$count = $icsParser->parse( \file_get_contents( $values['feed_file'] ), $values['feed_calendar_id'], $values['feed_member_id'], $values['feed_venue_id'] );
}
catch( \UnexpectedValueException $e )
{
@@ -290,6 +306,12 @@ class _ical extends \IPS\Dispatcher\Controller
}
$form->add( new \IPS\Helpers\Form\Select( 'feed_calendar_id', $feed->calendar_id, TRUE, array( 'options' => $options, 'parse' => 'normal' ) ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$form->add( new \IPS\Helpers\Form\Node( 'feed_venue_id', NULL, FALSE, array( 'class' => 'IPS\calendar\Venue', 'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendars&controller=ical&do=edit', 'admin' ) ) ) );
}
$form->add( new \IPS\Helpers\Form\Member( 'feed_member_id', \IPS\Member::load( $feed->member_id )->name, TRUE ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'feed_allow_rsvp', $feed->allow_rsvp, FALSE ) );
@@ -314,6 +336,12 @@ class _ical extends \IPS\Dispatcher\Controller
$feed->title = $values['feed_title'];
$feed->url = $values['feed_url'];
$feed->calendar_id = $values['feed_calendar_id'];
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$feed->venue_id = $values['feed_venue_id']->_id;
}
$feed->member_id = $values['feed_member_id']->member_id;
$feed->allow_rsvp = $values['feed_allow_rsvp'];
$feed->save();
@@ -1,13 +1,12 @@
<?php
/**
* @brief Settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\admin\calendars;
@@ -57,6 +56,8 @@ class _settings extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\YesNo( 'calendar_rss_feed', \IPS\Settings::i()->calendar_rss_feed, FALSE, array( 'togglesOn' => array( 'calendar_rss_feed_days' ) ) ) );
$form->add( new \IPS\Helpers\Form\Number( 'calendar_rss_feed_days', \IPS\Settings::i()->calendar_rss_feed_days, FALSE, array( 'unlimited' => -1 ), NULL, NULL, NULL, 'calendar_rss_feed_days' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'calendar_venues_enabled', \IPS\Settings::i()->calendar_venues_enabled ) );
if ( $values = $form->values() )
{
if( $values['calendar_date_format'] == -1 AND !$values['calendar_date_format_custom'] )
@@ -0,0 +1,41 @@
<?php
/**
* @brief venues
* @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 24 Feb 2017
*/
namespace IPS\calendar\modules\admin\calendars;
/* 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;
}
/**
* venues
*/
class _venues extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = '\IPS\calendar\Venue';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'venues_manage' );
parent::execute();
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief View Event Controller
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 14 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\front\calendar;
@@ -106,17 +105,136 @@ class _event extends \IPS\Content\Controller
/* Online User Location */
\IPS\Session::i()->setLocation( $this->event->url(), $this->event->onlineListPermissions(), 'loc_calendar_viewing_event', array( $this->event->title => FALSE ) );
/* Reminder */
$reminder = NULL;
try
{
$reminder = \IPS\Db::i()->select( '*', 'calendar_event_reminders', array( 'reminder_event_id=? and reminder_member_id=?', $this->event->id, (int) \IPS\Member::loggedIn()->member_id ) )->first();
}
catch ( \UnderflowException $e ) {}
/* Address */
$address = NULL;
if ( $this->event->location )
$location = NULL;
$addressName = NULL;
if ( \IPS\Settings::i()->calendar_venues_enabled and $this->event->venue() )
{
$address = \IPS\GeoLocation::buildFromjson( $this->event->location )->toString();
$location = \IPS\GeoLocation::buildFromjson( $this->event->venue()->address );
$address = $location->toString();
$addressName = $this->event->venue()->_title;
}
else if ( $this->event->location )
{
$location = \IPS\GeoLocation::buildFromjson( $this->event->location );
$address = $location->toString();
}
/* Add JSON-LD */
\IPS\Output::i()->jsonLd['event'] = array(
'@context' => "http://schema.org",
'@type' => "Event",
'url' => (string) $this->event->url(),
'name' => htmlspecialchars( $this->event->mapped('title'), ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
'description' => strip_tags( $this->event->truncated() ),
'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 )
);
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 );
}
if( $this->event->container()->allow_reviews )
{
\IPS\Output::i()->jsonLd['event']['aggregateRating'] = array(
'@type' => 'AggregateRating',
'reviewCount' => $this->event->reviews,
'ratingValue' => $this->event->averageReviewRating(),
'bestRating' => \IPS\Settings::i()->reviews_rating_out_of,
);
\IPS\Output::i()->jsonLd['event']['interactionStatistic'][] = array(
'@type' => 'InteractionCounter',
'interactionType' => "http://schema.org/ReviewAction",
'userInteractionCount' => $this->event->reviews
);
}
if( $this->event->container()->allow_comments )
{
\IPS\Output::i()->jsonLd['event']['interactionStatistic'][] = array(
'@type' => 'InteractionCounter',
'interactionType' => "http://schema.org/CommentAction",
'userInteractionCount' => $this->event->mapped('num_comments')
);
\IPS\Output::i()->jsonLd['event']['commentCount'] = $this->event->mapped('num_comments');
}
if( $this->event->coverPhoto()->file )
{
\IPS\Output::i()->jsonLd['event']['image'] = (string) $this->event->coverPhoto()->file->url;
}
if( $this->event->rsvp )
{
\IPS\Output::i()->jsonLd['event']['potentialAction'] = array(
'@type' => 'RsvpAction',
'target' => (string) $this->event->url( 'rsvp' )->setQueryString( 'action', '{rsvpResponse}' ),
'rsvpResponse-input' => "required name=rsvpResponse"
);
if( count( $attendees[1] ) )
{
\IPS\Output::i()->jsonLd['event']['attendee'] = array();
foreach( $attendees[1] as $attendee )
{
\IPS\Output::i()->jsonLd['event']['attendee'][] = array(
'@type' => 'Person',
'name' => htmlspecialchars( $attendee->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE )
);
}
}
}
if( $location )
{
\IPS\Output::i()->jsonLd['event']['location'] = array(
'@type' => 'Place',
'address' => array(
'@type' => 'PostalAddress',
'streetAddress' => implode( ', ', $location->addressLines ),
'addressLocality' => $location->city,
'addressRegion' => $location->region,
'postalCode' => $location->postalCode,
'addressCountry' => $location->country,
)
);
if( $addressName )
{
\IPS\Output::i()->jsonLd['event']['location']['name'] = $addressName;
}
}
else
{
\IPS\Output::i()->jsonLd['event']['location'] = array(
'@type' => 'Place',
'name' => \IPS\Settings::i()->board_name,
'address' => \IPS\Output::i()->jsonLd['event']['url'],
'url' => \IPS\Output::i()->jsonLd['event']['url']
);
}
/* Display */
//\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'view' )->eventSidebar( $this->event, $attendees );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view' )->view( $this->event, $commentsAndReviews, $attendees, $address );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view' )->view( $this->event, $commentsAndReviews, $attendees, $address, $reminder );
}
/**
@@ -263,4 +381,116 @@ class _event extends \IPS\Content\Controller
return parent::edit();
}
/**
* Set a reminder
*
* @return void
*/
protected function setReminder()
{
\IPS\Session::i()->csrfCheck();
/* Existing reminder? */
$existing = NULL;
try
{
$existing = \IPS\Db::i()->select( '*', 'calendar_event_reminders', array( 'reminder_event_id=? and reminder_member_id=?', $this->event->id, (int) \IPS\Member::loggedIn()->member_id ) )->first();
}
catch ( \UnderflowException $e ) {}
/* Build the form */
/* How far in the future is this event so we can set realistic max reminders */
$diff = $this->event->_start_date->diff( \IPS\DateTime::create() );
$max = $diff->d;
$form = new \IPS\Helpers\Form;
$form->class = 'ipsForm_vertical';
$form->add( new \IPS\Helpers\Form\Number( 'event_remind_me', isset( $existing ) ? $existing['reminder_days_before'] : ( ( $max < 3 ) ? $max : 3 ), TRUE, array( 'min' => 1, 'max' => (int) $max ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('event_remind_days_before'), 'event_remind_me' ) );
if ( $existing )
{
$form->addButton( 'event_dont_remind', 'link', \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=event&do=removeReminder&action=remove&id={$this->event->id}")->csrf(), 'ipsButton ipsButton_negative ipsPos_right', array('data-action' => 'removereminder') );
}
if( $values = $form->values() )
{
/* Delete existing */
\IPS\Db::i()->delete( 'calendar_event_reminders', array( 'reminder_event_id=? AND reminder_member_id=?', $this->event->id, (int) \IPS\Member::loggedIn()->member_id ) );
\IPS\Db::i()->insert( 'calendar_event_reminders', array(
'reminder_event_id' => $this->event->id,
'reminder_member_id' => (int) \IPS\Member::loggedIn()->member_id,
'reminder_date' => $this->event->_start_date->sub( new \DateInterval( 'P' . (int) $values['event_remind_me'] . 'D' ) )->getTimestamp(),
'reminder_days_before' => (int) $values['event_remind_me'],
) );
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'eventreminders' ) );
$message = 'event_reminder_added';
\IPS\Output::i()->redirect( $this->event->url(), $message );
}
/* 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' ) );
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
}
else
{
\IPS\Output::i()->output = $output;
}
}
/**
* Remve Reminder
*
* @return void
*/
protected function removeReminder()
{
\IPS\Session::i()->csrfCheck();
if ( \IPS\Request::i()->action == 'remove' )
{
/* Delete existing */
\IPS\Db::i()->delete( 'calendar_event_reminders', array( 'reminder_event_id=? AND reminder_member_id=?', $this->event->id, (int) \IPS\Member::loggedIn()->member_id ) );
$message = 'event_reminder_removed';
}
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( 'ok' );
}
else
{
\IPS\Output::i()->redirect( $this->event->url(), $message );
}
}
/**
* Reminder button
*
* @return void
*/
protected function reminderButton()
{
/* Existing reminder? */
$existing = NULL;
try
{
$existing = \IPS\Db::i()->select( '*', 'calendar_event_reminders', array( 'reminder_event_id=? and reminder_member_id=?', $this->event->id, (int)\IPS\Member::loggedIn()->member_id ) )->first();
}
catch ( \UnderflowException $e )
{
}
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'view', 'calendar', 'front' )->reminderButton( $this->event, $existing ) );
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief Submit Event Controller
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 8 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\front\calendar;
@@ -48,6 +47,12 @@ class _submit extends \IPS\Dispatcher\Controller
$form->hiddenValues['d'] = \IPS\Request::i()->d;
}
/* Are we coming from a venue? */
if( \IPS\Settings::i()->calendar_venues_enabled and \IPS\Request::i()->venue )
{
$form->hiddenValues['venue'] = \IPS\Request::i()->venue;
}
if ( $values = $form->values() )
{
$url = \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit&do=submit', 'front', 'calendar_submit' )->setQueryString( 'id', $values['calendar']->_id );
@@ -57,6 +62,11 @@ class _submit extends \IPS\Dispatcher\Controller
$url = $url->setQueryString( 'd', $values['d'] )->setQueryString( 'm', $values['m'] )->setQueryString( 'y', $values['y'] );
}
if( \IPS\Settings::i()->calendar_venues_enabled and isset( $values['venue'] ) )
{
$url = $url->setQueryString( 'venue', $values['venue'] );
}
\IPS\Output::i()->redirect( $url );
}
@@ -74,10 +84,26 @@ class _submit extends \IPS\Dispatcher\Controller
*/
protected function submit()
{
$calendar = NULL;
$club = NULL;
try
{
$calendar = \IPS\calendar\Calendar::loadAndCheckPerms( \IPS\Request::i()->id );
if ( $club = $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( $calendar->url(), $calendar->_title );
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $club, $calendar, 'sidebar' );
}
}
}
catch ( \OutOfRangeException $e )
{
@@ -86,7 +112,7 @@ 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\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() ) )
{
@@ -95,8 +121,90 @@ class _submit extends \IPS\Dispatcher\Controller
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'submit_event' );
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\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' ) );
}
/**
* Copy Event
*
* @return void
*/
protected function copy()
{
try
{
$existing = \IPS\calendar\Event::loadAndCheckPerms( \IPS\Request::i()->event_id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->redirect( IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ) );
}
/* Are we the author of the existing event? */
if( $existing->author() !== \IPS\Member::loggedIn() )
{
\IPS\Output::i()->redirect( IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ) );
}
/* Reset elements we don't want to copy */
$existing->start_date = NULL;
$existing->end_date = NULL;
$form = new \IPS\Helpers\Form( 'form', \IPS\Member::loggedIn()->language()->checkKeyExists( \IPS\Calendar\Event::$formLangPrefix . '_save' ) ? \IPS\Calendar\Event::$formLangPrefix . '_save' : 'save' );
$form->class = 'ipsForm_vertical';
$formElements = \IPS\Calendar\Event::formElements( $existing, $existing->container() );
foreach ( $formElements as $key => $object )
{
if ( is_object( $object ) )
{
$form->add( $object );
}
else
{
$form->addMessage( $object, NULL, FALSE, $key );
}
}
if ( $values = $form->values() )
{
/* Disable read/write separation */
\IPS\Db::i()->readWriteSeparation = FALSE;
try
{
$obj = \IPS\calendar\Event::createFromForm( $values );
if ( !\IPS\Member::loggedIn()->member_id and $obj->hidden() )
{
\IPS\Output::i()->redirect( $obj->container()->url(), 'mod_queue_message' );
}
else if ( $obj->hidden() == 1 )
{
\IPS\Output::i()->redirect( $obj->url(), 'mod_queue_message' );
}
else
{
\IPS\Output::i()->redirect( $obj->url() );
}
}
catch ( \DomainException $e )
{
$form->error = $e->getMessage();
}
}
\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 ) ) );
if ( \IPS\calendar\Event::moderateNewItems( \IPS\Member::loggedIn() ) )
{
\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;
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('copy_cal_event_header', TRUE, array( 'sprintf' => $existing->title ) );
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('copy_cal_event_header', TRUE, array( 'sprintf' => $existing->title ) ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_submit.js', 'calendar', 'front' ) );
}
}
@@ -0,0 +1,122 @@
<?php
/**
* @brief Venue
* @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 27 Feb 2017
*/
namespace IPS\calendar\modules\front\calendar;
/* 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;
}
/**
* venue
*/
class _venue extends \IPS\Dispatcher\Controller
{
/**
* @brief Venue we are viewing
*/
protected $venue = NULL;
/**
* Init
*
* @return void
*/
public function execute()
{
try
{
$this->venue = \IPS\calendar\Venue::loadAndCheckPerms( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2L354/1', 404, '' );
}
parent::execute();
}
/**
* Manage
*
* @return void
*/
public function manage()
{
/* Load the css for Calendar badges */
\IPS\calendar\Calendar::addCss();
$today = \IPS\calendar\Date::getDate();
/* Get the month data */
$day = NULL;
if( ( !\IPS\Request::i()->y OR \IPS\Request::i()->y == $today->year ) AND ( !\IPS\Request::i()->m OR \IPS\Request::i()->m == $today->mon ) )
{
$day = $today->mday;
}
try
{
$date = \IPS\calendar\Date::getDate( \IPS\Request::i()->y ?: NULL, \IPS\Request::i()->m ?: NULL, $day );
}
catch( \InvalidArgumentException $e )
{
\IPS\Output::i()->error( 'error_bad_date', '', 403, '' ); //@todo
}
$upcoming = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ),
\IPS\calendar\Date::getDate( $date->lastDayOfMonth('year'), $date->lastDayOfMonth('mon'), $date->lastDayOfMonth('mday'), 23, 59, 59 ),
NULL,
NULL,
FALSE,
NULL,
$this->venue
);
$upcomingOutput = \IPS\Theme::i()->getTemplate( 'venue', 'calendar', 'front' )->upcomingStream( $date, $upcoming, $this->venue );
/* Address */
$address = NULL;
if ( $this->venue->address )
{
$address = \IPS\GeoLocation::buildFromjson( $this->venue->address )->toString();
}
/* Display */
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( $upcomingOutput, 200, 'text/html', \IPS\Output::i()->httpHeaders );
}
else
{
/* Add JSON-LD */
\IPS\Output::i()->jsonLd['eventVenue'] = array(
'@context' => "http://schema.org",
'@type' => "EventVenue",
'url' => (string) $this->venue->url(),
'name' => htmlspecialchars( $this->venue->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE )
);
\IPS\Output::i()->title = $this->venue->_title;
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_venue.js', 'calendar', 'front' ) );
/* 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') );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'venue', 'calendar', 'front' )->view( $this->venue, $upcomingOutput, NULL, $address );
}
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Views
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 23 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\modules\front\calendar;
@@ -71,6 +70,20 @@ class _view extends \IPS\Dispatcher\Controller
{
\IPS\Output::i()->error( 'node_error', '2L182/2', 404, '' );
}
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 );
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $club, $this->_calendar, 'sidebar' );
}
}
}
if( $this->_calendar !== NULL AND $this->_calendar->_id )
@@ -138,22 +151,22 @@ class _view extends \IPS\Dispatcher\Controller
try
{
$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();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ),
\IPS\calendar\Date::getDate( $date->lastDayOfMonth('year'), $date->lastDayOfMonth('mon'), $date->lastDayOfMonth('mday'), 23, 59, 59 ),
$this->_calendar
);
}
catch( \Exception $e )
{
\IPS\Output::i()->error( 'error_bad_date', '3L182/3', 403, '' );
}
/* Get birthdays */
$birthdays = ( $this->_calendar === NULL OR count( $calendars ) == 1 ) ? $date->getBirthdays( FALSE, TRUE ) : array();
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents(
\IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ),
\IPS\calendar\Date::getDate( $date->lastDayOfMonth('year'), $date->lastDayOfMonth('mon'), $date->lastDayOfMonth('mday'), 23, 59, 59 ),
$this->_calendar
);
/* 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 )
{
@@ -161,7 +174,6 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarMonth( $calendars, $date, $featured, $birthdays, $events, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
@@ -236,7 +248,6 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWeek( $calendars, $date, $featured, $birthdays, $events, $nextWeek, $lastWeek, $days, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
@@ -347,7 +358,6 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarDay( $calendars, $date, $featured, $birthdays, $birthdayCount, $dayEvents, $tomorrow, $yesterday, $this->_today, $this->_calendar, $jump );
if( \IPS\Request::i()->isAjax() )
@@ -412,6 +422,28 @@ class _view extends \IPS\Dispatcher\Controller
FALSE
);
/* Sort */
$startDate = \IPS\calendar\Date::getDate();
@usort( $events, function( $a, $b ) use ( $startDate )
{
if( $a->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return -1;
}
if( $b->nextOccurrence( $startDate, 'startDate' ) === NULL )
{
return 1;
}
if ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() == $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() )
{
return 0;
}
return ( $a->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() < $b->nextOccurrence( $startDate, 'startDate' )->mysqlDatetime() ) ? -1 : 1;
} );
/* Pagination */
$pagination = array(
'page' => ( isset( \IPS\Request::i()->page ) ) ? \IPS\Request::i()->page : 1,
@@ -435,7 +467,6 @@ class _view extends \IPS\Dispatcher\Controller
}
/* Display */
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
$output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarStream( $calendars, $date, $featured, $events, $this->_calendar, $jump, $pagination );
if( \IPS\Request::i()->isAjax() )
@@ -444,6 +475,9 @@ class _view extends \IPS\Dispatcher\Controller
}
else
{
/* We can show the sidebar in stream view */
\IPS\Output::i()->sidebar['enabled'] = TRUE;
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'cal_month_stream_title', FALSE, array( 'sprintf' => array( $date->monthName, $date->year ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->calendarWrapper(
$output,
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.0 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 30 Oct 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_100002;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.0 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 15 Jan 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_100015;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.0 RC 5 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 May 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_100018;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.5 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 May 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_100028;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.12 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 21 Jul 2015
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_100042;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.1.16 Beta 1 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 30 Sep 2016
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_101064;
@@ -0,0 +1,321 @@
{
"1": {
"method": "createTable",
"params": [
{
"name": "calendar_event_reminders",
"columns": {
"reminder_id": {
"name": "reminder_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "ID Number",
"unsigned": true,
"zerofill": false,
"auto_increment": true,
"binary": false
},
"reminder_event_id": {
"name": "reminder_event_id",
"type": "BIGINT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "Event to remind about",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_member_id": {
"name": "reminder_member_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "Member to notify",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_date": {
"name": "reminder_date",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "Timestamp after which to send notification",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"reminder_days_before": {
"name": "reminder_days_before",
"type": "INT",
"length": 2,
"decimals": null,
"values": null,
"allow_null": false,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"columns": [
"reminder_id"
],
"length": [
null
]
},
"reminder": {
"type": "key",
"name": "reminder",
"columns": [
"reminder_event_id",
"reminder_member_id"
],
"length": [
null,
null
]
},
"date": {
"type": "key",
"name": "date",
"columns": [
"reminder_date"
],
"length": [
null
]
}
}
}
]
},
"2": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_venue",
"type": "INT",
"length": 5,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true
}
]
},
"3": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_meta_data",
"type": "BIT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"4": {
"method": "addColumn",
"params": [
"calendar_import_feeds",
{
"name": "feed_venue_id",
"type": "INT",
"length": 5,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"5": {
"method": "createTable",
"params": [
{
"name": "calendar_venues",
"columns": {
"venue_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
"comment": "ID Number",
"decimals": null,
"default": "0",
"length": 20,
"name": "venue_id",
"type": "BIGINT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_position": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 5,
"name": "venue_position",
"type": "INT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_enabled": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "1",
"length": 1,
"name": "venue_enabled",
"type": "TINYINT",
"unsigned": true,
"values": [],
"zerofill": false
},
"venue_title_seo": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "venue_title_seo",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"venue_address": {
"name": "venue_address",
"type": "TEXT",
"length": 0,
"decimals": null,
"values": [],
"allow_null": true,
"default": "",
"comment": "Physical Address",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"venue_id"
]
}
}
}
]
},
"6": {
"method": "addIndex",
"params": [
"calendar_events",
{
"type": "key",
"name": "event_venue",
"columns": [
"event_venue"
],
"length": [
null
]
}
]
},
"7": {
"method": "addColumn",
"params": [
"calendar_calendars",
{
"name": "cal_club_id",
"type": "BIGINT",
"length": null,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "The club ID if this calendar belongs to a club, or NULL",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"8": {
"method": "addColumn",
"params": [
"calendar_calendars",
{
"name": "cal_bitoptions",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.0 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 24 Oct 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_32000;
@@ -1,13 +1,12 @@
<?php
/**
* @brief 4.0.0 Alpha 1 Upgrade Code
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @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/
* @subpackage Calendar
* @package IPS Community Suite
* @package Invision Community
* @since 8 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\setup\upg_40000;
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Node
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar;
@@ -24,6 +23,8 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
{
use \IPS\Content\ClubContainer;
/**
* @brief [ActiveRecord] Multiton Store
*/
@@ -113,6 +114,18 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
* @brief [Node] Prefix string that is automatically prepended to permission matrix language strings
*/
public static $permissionLangPrefix = 'calperm_';
/**
* @brief Bitwise values for cal_bitoptions field
*/
public static $bitOptions = array(
'calendar_bitoptions' => array(
'calendar_bitoptions' => array(
'bw_disable_tagging' => 1,
'bw_disable_prefixes' => 2
)
)
);
/**
* [Node] Set whether or not this node is enabled
@@ -155,6 +168,13 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_comment_moderate', $this->id ? $this->comment_moderate : FALSE, FALSE, array(), NULL, NULL, NULL, 'cal_comment_moderate' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_allow_reviews', $this->id ? $this->allow_reviews : FALSE, FALSE, array( 'togglesOn' => array( 'cal_review_moderate' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_review_moderate', $this->id ? $this->review_moderate : FALSE, FALSE, array(), NULL, NULL, NULL, 'cal_review_moderate' ) );
if ( \IPS\Settings::i()->tags_enabled )
{
$form->addHeader( 'tags' );
$form->add( new \IPS\Helpers\Form\YesNo( 'bw_disable_tagging', !$this->calendar_bitoptions['bw_disable_tagging'], FALSE, array( 'togglesOn' => array( 'bw_disable_prefixes' ) ), NULL, NULL, NULL, 'bw_disable_tagging' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'bw_disable_prefixes', !$this->calendar_bitoptions['bw_disable_prefixes'], FALSE, array(), NULL, NULL, NULL, 'bw_disable_prefixes' ) );
}
}
/**
@@ -178,6 +198,16 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
unset( $values['cal_title'] );
}
/* Bitwise */
foreach ( array( 'bw_disable_tagging', 'bw_disable_prefixes' ) as $k )
{
if( isset( $values[ $k ] ) )
{
$values['calendar_bitoptions'][ $k ] = !$values[ $k ];
unset( $values[ $k ] );
}
}
return $values;
}
@@ -269,4 +299,43 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Output::i()->headCss = \IPS\Output::i()->headCss . $output;
}
/* !Clubs */
/**
* Get front-end language string
*
* @return string
*/
public static function clubFrontTitle()
{
return 'calendars_sg';
}
/**
* Set form for creating a node of this type in a club
*
* @param \IPS\Helpers\Form $form Form object
* @return void
*/
public function clubForm( \IPS\Helpers\Form $form )
{
$itemClass = static::$contentItemClass;
$form->add( new \IPS\Helpers\Form\Text( 'club_node_name', $this->_id ? $this->_title : \IPS\Member::loggedIn()->language()->addToStack( $itemClass::$title . '_pl' ), TRUE, array( 'maxLength' => 255 ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_allow_comments', $this->id ? $this->allow_comments : TRUE, FALSE, array( 'togglesOn' => array( 'cal_comment_moderate' ) ) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_allow_reviews', $this->id ? $this->allow_reviews : FALSE, FALSE, array( 'togglesOn' => array( 'cal_review_moderate' ) ) ) );
}
/**
* Class-specific routine when saving club form
*
* @param \IPS\Member\Club $club The club
* @param array $values Values
* @return void
*/
public function _saveClubForm( \IPS\Member\Club $club, $values )
{
$this->allow_comments = $values['cal_allow_comments'];
$this->allow_reviews = $values['cal_allow_reviews'];
}
}
+18 -9
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar-specific date functions
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 30 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar;
@@ -428,18 +427,28 @@ class _Date extends \IPS\DateTime
* @return string
*/
public function calendarDate( $memberOrLanguage=NULL )
{
return static::determineLanguage( $memberOrLanguage )->convertString( strftime( static::calendarDateFormat(), $this->getTimestamp() + $this->offset ) );
}
/**
* Return the format used by calendarDate()
*
* @return string
*/
public static function calendarDateFormat()
{
if( \IPS\Settings::i()->calendar_date_format == -1 AND \IPS\Settings::i()->calendar_date_format_custom )
{
return static::determineLanguage( $memberOrLanguage )->convertString( strftime( \IPS\Settings::i()->calendar_date_format_custom, $this->getTimestamp() + $this->offset ) );
return \IPS\Settings::i()->calendar_date_format_custom;
}
elseif( isset( static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ] ) )
{
return static::determineLanguage( $memberOrLanguage )->convertString( strftime( static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ], $this->getTimestamp() + $this->offset ) );
return static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ];
}
else
{
return static::localeDate();
return '%x';
}
}
@@ -778,6 +787,6 @@ class _Date extends \IPS\DateTime
*/
public function localeTime( $seconds=TRUE, $minutes=TRUE, $memberOrLanguage=NULL )
{
return static::determineLanguage( $memberOrLanguage )->convertString( strftime( $this->localeTimeFormat( $seconds, $minutes, $memberOrLanguage ), $this->getTimestamp() + $this->offset ) );
return static::determineLanguage( $memberOrLanguage )->convertString( strftime( static::localeTimeFormat( $seconds, $minutes, $memberOrLanguage ), $this->getTimestamp() + $this->offset ) );
}
}
+29 -11
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Event Comment Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\Event;
@@ -22,8 +21,10 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
/**
* Event Comment Model
*/
class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \IPS\Content\ReportCenter, \IPS\Content\Hideable, \IPS\Content\Reputation, \IPS\Content\Searchable, \IPS\Content\Embeddable
class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory, \IPS\Content\ReportCenter, \IPS\Content\Hideable, \IPS\Content\Searchable, \IPS\Content\Embeddable
{
use \IPS\Content\Reactable;
/**
* @brief [ActiveRecord] Multiton Store
*/
@@ -75,11 +76,6 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
*/
public static $icon = 'calendar';
/**
* @brief Reputation Type
*/
public static $reputationType = 'comment_id';
/**
* @brief [Content] Key for hide reasons
*/
@@ -138,4 +134,26 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
return \IPS\Theme::i()->getTemplate( 'global', 'calendar', 'front' )->searchResultCommentSnippet( $indexData, $nextOccurance, $startDate, $endDate, $itemData['event_all_day'], $reviewRating, $view == 'condensed' );
}
/**
* Reaction Type
*
* @return string
*/
public static function reactionType()
{
return 'comment_id';
}
/**
* Get content for embed
*
* @param array $params Additional parameters to add to URL
* @return string
*/
public function embedContent( $params )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'embed.css', 'calendar', 'front' ) );
return \IPS\Theme::i()->getTemplate( 'global', 'calendar' )->embedEventComment( $this, $this->item(), $this->url()->setQueryString( $params ) );
}
}
+233 -36
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Calendar Event Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar;
@@ -25,15 +24,17 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
class _Event extends \IPS\Content\Item implements
\IPS\Content\Permissions,
\IPS\Content\Tags,
\IPS\Content\Reputation,
\IPS\Content\Followable,
\IPS\Content\ReportCenter,
\IPS\Content\ReadMarkers,
\IPS\Content\Hideable, \IPS\Content\Featurable, \IPS\Content\Lockable,
\IPS\Content\Shareable,
\IPS\Content\Searchable,
\IPS\Content\Embeddable
\IPS\Content\Embeddable,
\IPS\Content\MetaData
{
use \IPS\Content\Reactable;
/**
* @brief Application
*/
@@ -101,6 +102,7 @@ class _Event extends \IPS\Content\Item implements
'ip_address' => 'ip_address',
'cover_photo' => 'cover_photo',
'cover_photo_offset' => 'cover_offset',
'meta_data' => 'meta_data'
);
/**
@@ -118,11 +120,6 @@ class _Event extends \IPS\Content\Item implements
*/
public static $formLangPrefix = 'event_';
/**
* @brief Reputation Type
*/
public static $reputationType = 'event_id';
/**
* @brief Cover Photo Storage Extension
*/
@@ -132,6 +129,11 @@ class _Event extends \IPS\Content\Item implements
* @brief Cached date objects
*/
protected $dateObjects = array( 'start' => NULL, 'end' => NULL );
/**
* @brief Cached venue
*/
protected $venueObject = NULL;
/**
* @brief [Content] Key for hide reasons
@@ -923,23 +925,39 @@ class _Event extends \IPS\Content\Item implements
/**
* Are comments supported by this class?
*
* @param \IPS\Member\NULL $member The member to check for or NULL fto not check permission
* @return int
* @param \IPS\Member|NULL $member The member to check for or NULL to not check permission
* @param \IPS\Node\Model|NULL $container The container to check in, or NULL for any container
* @return bool
*/
public static function supportsComments( \IPS\Member $member = NULL )
{
return parent::supportsComments() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_comments=1' ) ) );
public static function supportsComments( \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
{
if( $container !== NULL )
{
return parent::supportsComments() and $container->allow_comments AND ( !$member or $container->can( 'read', $member ) );
}
else
{
return parent::supportsComments() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_comments=1' ) ) );
}
}
/**
* Are reviews supported by this class?
*
* @param \IPS\Member\NULL $member The member to check for or NULL to not check permission
* @return int
* @param \IPS\Member|NULL $member The member to check for or NULL to not check permission
* @param \IPS\Node\Model|NULL $container The container to check in, or NULL for any container
* @return bool
*/
public static function supportsReviews( \IPS\Member $member = NULL )
public static function supportsReviews( \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
{
return parent::supportsReviews() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_reviews=1' ) ) );
if( $container !== NULL )
{
return parent::supportsReviews() and $container->allow_reviews AND ( !$member or $container->can( 'read', $member ) );
}
else
{
return parent::supportsReviews() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_reviews=1' ) ) );
}
}
/**
@@ -952,11 +970,11 @@ class _Event extends \IPS\Content\Item implements
$tabs = array();
if ( $this->container()->allow_reviews )
{
$tabs['reviews'] = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get( 'event_review_count' ), array( $this->mapped('num_reviews') ) );
$tabs['reviews'] = \IPS\Member::loggedIn()->language()->addToStack( 'event_review_count', TRUE, array( 'pluralize' => array( $this->mapped('num_reviews') ) ) );
}
if ( $this->container()->allow_comments )
{
$tabs['comments'] = \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get( 'event_comment_count' ), array( $this->mapped('num_comments') ) );
$tabs['comments'] = \IPS\Member::loggedIn()->language()->addToStack( 'event_comment_count', TRUE, array( 'pluralize' => array( $this->mapped('num_comments') ) ) );
}
return $tabs;
@@ -1174,13 +1192,16 @@ class _Event extends \IPS\Content\Item implements
}, NULL, NULL, 'event_dates' );
/* Init */
$return['calendar'] = new \IPS\Helpers\Form\Node( static::$formLangPrefix . 'container', $container ? $container->id : ( isset( \IPS\Request::i()->calendar ) ? \IPS\Request::i()->calendar : NULL ), TRUE, array(
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ),
'class' => 'IPS\calendar\Calendar',
'permissionCheck' => 'add',
'togglePerm' => 'askrsvp',
'toggleIds' => array( 'event_rsvp' ),
) );
if ( !$container or !$container->club() )
{
$return['calendar'] = new \IPS\Helpers\Form\Node( static::$formLangPrefix . 'container', $container ? $container->id : ( isset( \IPS\Request::i()->calendar ) ? \IPS\Request::i()->calendar : NULL ), TRUE, array(
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ),
'class' => 'IPS\calendar\Calendar',
'permissionCheck' => 'add',
'togglePerm' => 'askrsvp',
'toggleIds' => array( 'event_rsvp' ),
) );
}
/* Get default elements */
$return = array_merge( $return, parent::formElements( $item, $container ) );
@@ -1190,7 +1211,27 @@ class _Event extends \IPS\Content\Item implements
/* Cover photo and location */
$return['header'] = new \IPS\Helpers\Form\Upload( 'event_cover_photo', ( $item AND $item->cover_photo ) ? \IPS\File::get( 'calendar_Events', $item->cover_photo ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'calendar_Events' ) );
$return['location'] = new \IPS\Helpers\Form\Address( 'event_location', ( $item AND $item->location ) ? \IPS\GeoLocation::buildFromJson( $item->location ) : NULL, FALSE, array( 'minimize' => TRUE, 'requireFullAddress' => FALSE ) );
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$return['venue'] = new \IPS\Helpers\Form\Node( static::$formLangPrefix . 'venue', ( $item ) ? $item->venue ?: 0 : ( isset( \IPS\Request::i()->venue ) ? \IPS\Request::i()->venue : NULL ), FALSE, array(
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ),
'class' => 'IPS\calendar\Venue',
'zeroVal' => 'venues_not_listed',
'zeroValTogglesOn' => array( 'event_location', 'event_new_venue' ),
'permissionCheck' => 'add',
) );
}
$return['location'] = new \IPS\Helpers\Form\Address( 'event_location', ( $item AND $item->location ) ? \IPS\GeoLocation::buildFromJson( $item->location ) : NULL, FALSE, array( 'minimize' => TRUE, 'requireFullAddress' => FALSE ), NULL, NULL, NULL, 'event_location' );
/* Save location as a new venue? */
if ( \IPS\Settings::i()->calendar_venues_enabled and \IPS\Member::loggedIn()->hasAcpRestriction( 'calendar', 'calendars', 'venues_manage' ) )
{
$return['save_new_venue'] = new \IPS\Helpers\Form\YesNo( 'event_new_venue', NULL, FALSE, array( 'togglesOn' => array( 'venue_title', 'venue_description' ) ), NULL, NULL, NULL, 'event_new_venue' );
$return['venue_title'] = new \IPS\Helpers\Form\Translatable( 'venue_title', NULL, TRUE, array( 'app' => 'calendar', 'key' => NULL ), NULL, NULL, NULL, 'venue_title' );
$return['venue_description'] = new \IPS\Helpers\Form\Translatable( 'venue_description', NULL, FALSE, array( 'app' => 'calendar', 'key' => NULL, 'editor' => array( 'app' => 'calendar', 'key' => 'Venue', 'autoSaveKey' => "calendar-new-venue", 'attachIds' => NULL ) ), NULL, NULL, NULL, 'venue_description' );
}
/* Gallery album association */
if( \IPS\Application::appIsEnabled( 'gallery' ) )
@@ -1246,8 +1287,11 @@ class _Event extends \IPS\Content\Item implements
}
/* Calendar */
$this->calendar_id = ( $values[ static::$formLangPrefix . 'container' ] instanceof \IPS\Node\Model ) ? $values[ static::$formLangPrefix . 'container' ]->_id : intval( $values[ static::$formLangPrefix . 'container' ] );
if ( isset( $values[ static::$formLangPrefix . 'container' ] ) )
{
$this->calendar_id = ( $values[ static::$formLangPrefix . 'container' ] instanceof \IPS\Node\Model ) ? $values[ static::$formLangPrefix . 'container' ]->_id : intval( $values[ static::$formLangPrefix . 'container' ] );
}
/* Start and end dates */
$this->start_date = \IPS\calendar\Date::createFromForm( $values['event_dates']['start_date'], ( ( !isset( $values['event_dates']['all_day'] ) OR !$values['event_dates']['all_day'] ) ? $values['event_dates']['start_time'] : NULL ), ( isset( $values['event_dates']['all_day'] ) AND $values['event_dates']['all_day'] ) ? 'UTC' : $values['event_dates']['event_timezone'] )->format( 'Y-m-d H:i' );
$this->end_date = null;
@@ -1308,6 +1352,37 @@ class _Event extends \IPS\Content\Item implements
/* Set location */
$this->location = ( $values['event_location'] !== NULL ) ? json_encode( $values['event_location'] ) : NULL;
if( \IPS\Settings::i()->calendar_venues_enabled )
{
$this->venue = NULL;
if( $values['event_venue'] instanceof \IPS\calendar\Venue )
{
$this->venue = $values['event_venue']->_id;
}
elseif ( \IPS\Member::loggedIn()->hasAcpRestriction( 'calendar', 'calendars', 'venues_manage' ) and $values['event_new_venue'] and $values['event_location'] )
{
$venue = new \IPS\calendar\Venue;
$venue->address = json_encode( $values['event_location'] );
$venue->save();
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id, $values['venue_title'] );
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id . '_desc', $values['venue_description'] );
$venue->title_seo = \IPS\Http\Url\Friendly::seoTitle( $values['venue_title'][ \IPS\Lang::defaultLanguage() ] );
/* Set the order */
$order = \IPS\Db::i()->select( array( "MAX( `venue_position` )" ), 'calendar_venues', array() )->first();
$venue->position = $order + 1;
$venue->save();
/* Set the new event to this venue */
$this->venue = $venue->id;
$this->location = NULL;
}
}
/* Gallery album association */
if( \IPS\Application::appIsEnabled( 'gallery' ) AND $values['event_album'] instanceof \IPS\gallery\Album )
{
@@ -1322,6 +1397,10 @@ class _Event extends \IPS\Content\Item implements
$this->rsvp = isset( $values['event_rsvp'] ) ? $values['event_rsvp'] : FALSE;
$this->rsvp_limit = isset( $values['event_rsvp_limit'] ) ? $values['event_rsvp_limit'] : 0;
unset( $values['save_new_venue'] );
unset( $values['venue_title'] );
unset( $values['venue_description'] );
/* Get the normal stuff */
parent::processForm( $values );
}
@@ -1337,6 +1416,8 @@ class _Event extends \IPS\Content\Item implements
{
parent::processAfterCreate( $comment, $values );
$this->expireWidgetCaches();
/* And claim attachments */
\IPS\File::claimAttachments( 'calendar-event', $this->id );
@@ -1344,6 +1425,19 @@ class _Event extends \IPS\Content\Item implements
$this->expireWidgetCaches();
}
/**
* Process created object AFTER the object has been edited
*
* @param array $values Values from form
* @return void
*/
public function processAfterEdit( $values )
{
parent::processAfterEdit( $values );
$this->expireWidgetCaches();
}
/**
* Create Notification
*
@@ -1366,7 +1460,8 @@ class _Event extends \IPS\Content\Item implements
parent::delete();
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=?', $this->id ) );
\IPS\Db::i()->delete( 'calendar_event_reminders', array( 'reminder_event_id=?', $this->id ) );
/* We should not delete maps for imported events, because we do not want to reimport them */
//\IPS\Db::i()->delete( 'calendar_import_map', array( 'import_event_id=?', $this->id ) );
}
@@ -1381,6 +1476,20 @@ class _Event extends \IPS\Content\Item implements
*/
public function map( $width, $height )
{
/* Show venue map */
if( \IPS\Settings::i()->calendar_venues_enabled )
{
if( $this->venue )
{
try
{
$this->location = \IPS\calendar\Venue::load( $this->venue )->address;
}
catch( \OutOfRangeException $e ){}
}
}
/* No venue? Do we have a specific event location? */
if( $this->location )
{
try
@@ -1402,11 +1511,12 @@ class _Event extends \IPS\Content\Item implements
* @param int|null $limit Maximum number of events to return (only supported when not formatting events)
* @param bool $formatEvents Whether or not to format events into a structured array
* @param \IPS\Member $member The member (NULL to use currently logged in member)
* @param \IPS\calendar\Venue $venue The venue to filter by (if provided)
* @return \IPS\Patterns\ActiveRecordIterator
* @throws \InvalidArgumentException
* @see \IPS\Content\_Item::getItemsWithPermission()
*/
public static function retrieveEvents( $startDate, $endDate=NULL, $calendar=NULL, $limit=NULL, $formatEvents=TRUE, $member=NULL )
public static function retrieveEvents( $startDate, $endDate=NULL, $calendar=NULL, $limit=NULL, $formatEvents=TRUE, $member=NULL, $venue=NULL )
{
$where = array();
@@ -1423,6 +1533,11 @@ class _Event extends \IPS\Content\Item implements
}
}
if( $venue!== NULL )
{
$where[] = array( 'event_venue=?', (int) $venue->_id );
}
if( $endDate === NULL AND $formatEvents === TRUE )
{
throw new \InvalidArgumentException;
@@ -1700,7 +1815,8 @@ class _Event extends \IPS\Content\Item implements
*/
public function embedContent( $params )
{
return \IPS\Theme::i()->getTemplate( 'global', 'calendar' )->embedCalendar_event( $this, $this->url()->setQueryString( $params ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'embed.css', 'calendar', 'front' ) );
return \IPS\Theme::i()->getTemplate( 'global', 'calendar' )->embedEvent( $this, $this->url()->setQueryString( $params ), $this->embedImage() );
}
/**
@@ -1812,4 +1928,85 @@ class _Event extends \IPS\Content\Item implements
$member = $member ?: \IPS\Member::loggedIn();
return parent::canReview( $member ) and $this->container()->allow_reviews;
}
/**
* Reaction Type
*
* @return string
*/
public static function reactionType()
{
return 'event_id';
}
/**
* Can remind?
*
* @return bool
*/
public function canRemind()
{
/* Does the event happen more than 1 day into the future? */
return (bool) ( $this->_start_date->sub( new \DateInterval( 'P1D' ) ) > \IPS\DateTime::create() );
}
/* !Tags */
/**
* Can tag?
*
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
* @param \IPS\Node\Model|NULL $container The container to check if tags can be used in, if applicable
* @return bool
*/
public static function canTag( \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
{
return parent::canTag( $member, $container ) and ( $container === NULL or !$container->calendar_bitoptions['bw_disable_tagging'] );
}
/**
* Can use prefixes?
*
* @param \IPS\Member|NULL $member The member to check for (NULL for currently logged in member)
* @param \IPS\Node\Model|NULL $container The container to check if tags can be used in, if applicable
* @return bool
*/
public static function canPrefix( \IPS\Member $member = NULL, \IPS\Node\Model $container = NULL )
{
return parent::canPrefix( $member, $container ) and ( $container === NULL or !$container->calendar_bitoptions['bw_disable_prefixes'] );
}
/**
* Venue
*
* @return NULL|\IPS\calendar\Venue
*/
public function venue()
{
if ( \IPS\Settings::i()->calendar_venues_enabled and $this->venue )
{
try
{
if ( !$this->venueObject )
{
$this->venueObject = \IPS\calendar\Venue::load( $this->venue );
}
return $this->venueObject;
}
catch( \OutOfRangeException $e ){}
}
return NULL;
}
/**
* Supported Meta Data Types
*
* @return array
*/
public static function supportedMetaDataTypes()
{
return array( 'core_FeaturedComments', 'core_ContentMessages' );
}
}
+29 -11
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief Event Review Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 7 Jan 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\Event;
@@ -22,8 +21,10 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
/**
* Event Review Model
*/
class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \IPS\Content\ReportCenter, \IPS\Content\Hideable, \IPS\Content\Reputation, \IPS\Content\Searchable, \IPS\Content\Embeddable
class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \IPS\Content\ReportCenter, \IPS\Content\Hideable, \IPS\Content\Searchable, \IPS\Content\Embeddable
{
use \IPS\Content\Reactable;
/**
* @brief [ActiveRecord] Multiton Store
*/
@@ -79,11 +80,6 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
*/
public static $icon = 'calendar';
/**
* @brief Reputation Type
*/
public static $reputationType = 'review_id';
/**
* @brief [Content] Key for hide reasons
*/
@@ -126,4 +122,26 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
{
return \IPS\calendar\Event\Comment::searchResultSnippet( $indexData, $authorData, $itemData, $containerData, $reputationData, $reviewRating, $view );
}
/**
* Reaction Type
*
* @return string
*/
public static function reactionType()
{
return 'review_id';
}
/**
* Get content for embed
*
* @param array $params Additional parameters to add to URL
* @return string
*/
public function embedContent( $params )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'embed.css', 'calendar', 'front' ) );
return \IPS\Theme::i()->getTemplate( 'global', 'calendar' )->embedEventReview( $this, $this->item(), $this->url()->setQueryString( $params ) );
}
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief iCalendar ICS Parser
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\Icalendar;
@@ -246,10 +245,11 @@ class _ICSParser
* @param int|\IPS\calendar\Calendar $calendar The calendar to import to
* @param int|\IPS\Member $member The member the imported events should be 'from'
* @param int $feed The feed we are importing (used to detect and prevent duplicate imports)
* @param int $venue The venue if provided
* @return array Number of events imported and skipped
* @throws \UnexpectedValueException
*/
public function parse( $content, $calendar, $member, $feed=NULL )
public function parse( $content, $calendar, $member, $feed=NULL, $venue=NULL )
{
/* Load the calendar */
$this->calendar = ( $calendar instanceof \IPS\calendar\Calendar ) ? $calendar : \IPS\calendar\Calendar::load( $calendar );
@@ -416,6 +416,12 @@ class _ICSParser
$newEvent->post_key = md5( uniqid() );
$newEvent->member_id = $this->member->member_id;
$newEvent->calendar_id = $this->calendar->id;
if( $venue )
{
$newEvent->venue = $venue;
}
$newEvent->approved = 1;
/* RSVP ? */
@@ -447,6 +453,19 @@ class _ICSParser
}
catch( \BadFunctionCallException $e ){}
}
elseif( isset( $event['location'] ) )
{
try
{
$location = new \IPS\GeoLocation;
$location->addressLines = array( $event['location'] );
$location->getLatLong();
/* We get by LatLong because getLatLong() does not populate the other address data. */
$newEvent->location = json_encode( \IPS\GeoLocation::getByLatLong( $location->lat, $location->long ) );
}
catch( \BadFunctionCallException $e ){}
}
/* Save */
$newEvent->save();
@@ -866,7 +885,6 @@ class _ICSParser
*
* @param string $text String to unencode
* @return string Unencoded string
* @link http://community.invisionpower.com/tracker/issue-33787-formatting-problem-with-imported-ics-file-calendar-app/
*/
protected function _unencodeSpecialCharacters( $text )
{
@@ -930,42 +948,50 @@ class _ICSParser
*/
protected function _unparseTimeInfo( $string )
{
if( mb_strpos( $string, '=' ) !== false )
/* init */
$value = NULL;
$rawTime = NULL;
$tzid = NULL;
/* split the timestamp from the properties */
$dt = explode( ':', $string );
/* Set the raw time value */
$rawTime = $dt[1];
/* Which properties do we have */
$properties = explode( ';', $dt[0] );
foreach( $properties as $property )
{
$_tmp = explode( '=', $string );
$_key = explode( ';', $_tmp[0] );
$tmp = explode( ':', $_tmp[1] );
}
else
{
$_tmp = array();
$_key = array();
$tmp = explode( ':', $string );
/* The date string may be in the format of "DTSTART;20160219T140000Z" (for example) */
if ( !isset( $tmp[1] ) )
if( mb_strpos( $property, '=' ) !== false )
{
if ( mb_strpos( $string, ';' ) !== false )
$_property = explode( '=', $property );
/* Grab our needed values from the given properties */
switch( $_property[0] )
{
$tmp = explode( ';', $string );
case 'VALUE':
$value = $_property[1];
break;
case 'TZID':
$tzid = $_property[1];
break;
}
}
}
/* Got a TZID? */
$tzid = ( count( $_key ) AND $_key[1] == 'TZID' ) ? $tmp[0] : '';
/* If the value is a date without a time, then type should be reset to date */
$type = ( mb_strlen( $tmp[1] ) === 8 ) ? 'DATE' : 'DATETIME';
$type = ( mb_strlen( $rawTime ) === 8 ) ? 'DATE' : 'DATETIME';
/* Format return array */
$return = array(
'type' => $type,
'raw' => $tmp[1],
'raw_ts' => strtotime( $tmp[1] ),
'tzid' => str_replace( '"', '', $tzid ),
'raw' => $rawTime,
'raw_ts' => strtotime( $rawTime ),
'tzid' => ( $tzid ) ? str_replace( '"', '', $tzid ) : '',
);
/* Is this the earliest or latest timestamp? */
if ( ( $this->_feedEarliest == 0 ) OR ( $return['raw_ts'] < $this->_feedEarliest ) )
{
@@ -1025,7 +1051,6 @@ class _ICSParser
*
* @param int $start Line number
* @return void
* @link http://community.invisionpower.com/resources/bugs.html/_/ip-calendar/recurring-events-can-sometimes-be-skipped-in-ics-r41033
*/
protected function _processEventObject( $start )
{
@@ -1070,7 +1095,6 @@ class _ICSParser
break;
case 'SUMMARY':
/* @link http://community.invisionpower.com/tracker/issue-32941-ical-summary/ */
if( mb_strpos( $_data, 'LANGUAGE=' ) === 0 )
{
$_data = preg_replace( "/^LANGUAGE=(.+?):(.+?)$/i", "\\2", $_data );
@@ -1290,7 +1314,7 @@ class _ICSParser
{
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'], new \DateTimeZone( $event[ $method ]['tzid'] ) );
}
else
elseif( isset( $event[ $method ]['raw'] ) )
{
$event[ $method ]['utc_time'] = new \IPS\DateTime( $event[ $method ]['raw'] );
}
@@ -1,13 +1,12 @@
<?php
/**
* @brief iCalendar active record
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar;
@@ -65,7 +64,7 @@ class _Icalendar extends \IPS\Patterns\ActiveRecord
$icsParser = new \IPS\calendar\Icalendar\ICSParser;
return $icsParser->parse( \IPS\Http\Url::external( str_replace( array( 'webcal://', 'webcals://' ), array( 'http://', 'https://' ), $this->url ) )->request()->get(), $this->calendar_id, $this->member_id, $this->id );
return $icsParser->parse( \IPS\Http\Url::external( str_replace( array( 'webcal://', 'webcals://' ), array( 'http://', 'https://' ), $this->url ) )->request()->get(), $this->calendar_id, $this->member_id, $this->id, $this->venue_id );
}
/**
@@ -0,0 +1,219 @@
<?php
/**
* @brief Venue Node
*/
namespace IPS\calendar;
/* 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;
}
/**
* Calendar Node
*/
class _Venue extends \IPS\Node\Model
{
/**
* @brief [ActiveRecord] Multiton Store
*/
protected static $multitons;
/**
* @brief [ActiveRecord] Database Table
*/
public static $databaseTable = 'calendar_venues';
/**
* @brief [ActiveRecord] Database Prefix
*/
public static $databasePrefix = 'venue_';
/**
* @brief [Node] Order Database Column
*/
public static $databaseColumnOrder = 'position';
/**
* @brief [Node] Node Title
*/
public static $nodeTitle = 'venues';
/**
* @brief URL Base
*/
public static $urlTemplate = 'calendar_venue';
/**
* @brief URL Base
*/
public static $urlBase = 'app=calendar&module=calendar&controller=venue&id=';
/**
* @brief [Node] ACP Restrictions
* @code
array(
'app' => 'core', // The application key which holds the restrictrions
'module' => 'foo', // The module key which holds the restrictions
'map' => array( // [Optional] The key for each restriction - can alternatively use "prefix"
'add' => 'foo_add',
'edit' => 'foo_edit',
'permissions' => 'foo_perms',
'delete' => 'foo_delete'
),
'all' => 'foo_manage', // [Optional] The key to use for any restriction not provided in the map (only needed if not providing all 4)
'prefix' => 'foo_', // [Optional] Rather than specifying each key in the map, you can specify a prefix, and it will automatically look for restrictions with the key "[prefix]_add/edit/permissions/delete"
* @endcode
*/
protected static $restrictions = array(
'app' => 'calendar',
'module' => 'venues',
'prefix' => 'venues_'
);
/**
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
*/
public static $titleLangPrefix = 'calendar_venue_';
/**
* @brief [Node] Description suffix. If specified, will look for a language key with "{$titleLangPrefix}_{$id}_{$descriptionLangSuffix}" as the key
*/
public static $descriptionLangSuffix = '_desc';
/**
* @brief [Node] Moderator Permission
*/
public static $modPerm = 'calendar_venues';
/**
* [Node] Get whether or not this node is enabled
*
* @note Return value NULL indicates the node cannot be enabled/disabled
* @return bool|null
*/
protected function get__enabled()
{
return (bool) $this->enabled;
}
/**
* [Node] Set whether or not this node is enabled
*
* @param bool|int $enabled Whether to set it enabled or disabled
* @return void
*/
protected function set__enabled( $enabled )
{
$this->enabled = $enabled;
}
/**
* @brief Cached URL
*/
protected $_url = NULL;
/**
* Get SEO name
*
* @return string
*/
public function get_title_seo()
{
if( !$this->_data['title_seo'] )
{
$this->title_seo = \IPS\Http\Url\Friendly::seoTitle( \IPS\Lang::load( \IPS\Lang::defaultLanguage() )->get( 'calendar_venue_' . $this->id ) );
$this->save();
}
return $this->_data['title_seo'] ?: \IPS\Http\Url\Friendly::seoTitle( \IPS\Lang::load( \IPS\Lang::defaultLanguage() )->get( 'calendar_venue_' . $this->id ) );
}
/**
* [Node] Add/Edit Form
*
* @param \IPS\Helpers\Form $form The form
* @return void
*/
public function form( &$form )
{
$form->add( new \IPS\Helpers\Form\Translatable( 'venue_title', NULL, TRUE, array( 'app' => 'calendar', 'key' => ( $this->id ? "calendar_venue_{$this->id}" : NULL ) ) ) );
$form->add( new \IPS\Helpers\Form\Translatable( 'venue_description', NULL, FALSE, array( 'app' => 'calendar', 'key' => ( $this->id ? "calendar_venue_{$this->id}_desc" : NULL ), 'editor' => array( 'app' => 'calendar', 'key' => 'Venue', 'autoSaveKey' => ( $this->id ? "calendar-venue-{$this->id}" : "calendar-new-venue" ), 'attachIds' => $this->id ? array( $this->id, NULL, 'description' ) : NULL ) ) ) );
$form->add( new \IPS\Helpers\Form\Address( 'venue_address', $this->id ? \IPS\GeoLocation::buildFromJson( $this->address ) : NULL, TRUE, array( 'minimize' => FALSE, 'requireFullAddress' => TRUE ), NULL, NULL, NULL, 'venue_address' ) );
}
/**
* [Node] Format form values from add/edit form for save
*
* @param array $values Values from the form
* @return array
*/
public function formatFormValues( $values )
{
if ( !$this->id )
{
$this->save();
\IPS\File::claimAttachments( 'calendar-new-venue', $this->id, NULL, 'description', TRUE );
}
if( isset( $values['venue_title'] ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $this->id, $values['venue_title'] );
$values['title_seo'] = \IPS\Http\Url\Friendly::seoTitle( $values['venue_title'][ \IPS\Lang::defaultLanguage() ] );
unset( $values['venue_title'] );
}
if( isset( $values['venue_description'] ) )
{
\IPS\Lang::saveCustom( 'venues', 'calendar_venue_' . $this->id .'_desc', $values['venue_description'] );
unset( $values['venue_description'] );
}
$values['venue_address'] = ( $values['venue_address'] !== NULL ) ? json_encode( $values['venue_address'] ) : NULL;
return $values;
}
/**
* @brief SEO Title Column
*/
public static $seoTitleColumn = 'title_seo';
/**
* [ActiveRecord] Delete Record
*
* @return void
*/
public function delete()
{
\IPS\Lang::deleteCustom( 'calendar', 'calendar_venue_' . $this->id . '_desc' );
return parent::delete();
}
/**
* Return the map for the venue
*
* @param int $width Width
* @param int $height Height
* @return string
* @note \BadMethodCallException can be thrown if the google maps integration is shut off - don't show any error if that happens.
*/
public function map( $width, $height )
{
if( $this->address )
{
try
{
return \IPS\GeoLocation::buildFromJson( $this->address )->map()->render( $width, $height );
}
catch( \BadMethodCallException $e ){}
}
return '';
}
}
@@ -0,0 +1,88 @@
<?php
/**
* @brief eventreminders Task
* @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 14 Feb 2017
*/
namespace IPS\calendar\tasks;
/* 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;
}
/**
* eventreminders Task
*/
class _eventreminders extends \IPS\Task
{
/**
* Execute
*
* If ran successfully, should return anything worth logging. Only log something
* worth mentioning (don't log "task ran successfully"). Return NULL (actual NULL, not '' or 0) to not log (which will be most cases).
* If an error occurs which means the task could not finish running, throw an \IPS\Task\Exception - do not log an error as a normal log.
* Tasks should execute within the time of a normal HTTP request.
*
* @return mixed Message to log or NULL
* @throws \IPS\Task\Exception
*/
public function execute()
{
$reminderCount = \IPS\Db::i()->select( 'count(*)', 'calendar_event_reminders', array() )->first();
if( $reminderCount == 0 )
{
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( '`key`=?', 'eventreminders' ) );
/* Nothing to send */
return NULL;
}
$this->runUntilTimeout( function()
{
/* Grab some reminders */
$reminders = \IPS\Db::i()->select( '*', 'calendar_event_reminders', array( 'reminder_date <= ?', \IPS\DateTime::create()->getTimestamp() ), 'reminder_date ASC', array( 0, 20 ), NULL, NULL, \IPS\Db::SELECT_DISTINCT );
if ( !$reminders->count() )
{
return FALSE;
}
foreach( $reminders as $reminder )
{
$event = \IPS\calendar\Event::load( $reminder['reminder_event_id'] );
$member = \IPS\Member::load( $reminder['reminder_member_id'] );
$notification = new \IPS\Notification( \IPS\Application::load( 'calendar' ), 'event_reminder', $event, array( $event, $reminder['reminder_days_before'] ), array( 'daysToGo' => $reminder['reminder_days_before'] ) );
$notification->recipients->attach( $member );
$notification->send();
/* Delete the reminder now it has sent */
\IPS\Db::i()->delete( 'calendar_event_reminders', array( 'reminder_event_id=? AND reminder_member_id=?', $reminder['reminder_event_id'], $reminder['reminder_member_id'] ) );
}
});
return NULL;
}
/**
* Cleanup
*
* If your task takes longer than 15 minutes to run, this method
* will be called before execute(). Use it to clean up anything which
* may not have been done
*
* @return void
*/
public function cleanup()
{
}
}
+4 -5
View File
@@ -1,13 +1,12 @@
<?php
/**
* @brief icalendar Task
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\tasks;
@@ -1,13 +1,12 @@
<?php
/**
* @brief Recent event reviews Widget
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 Feb 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\widgets;
@@ -1,13 +1,12 @@
<?php
/**
* @brief todaysBirthdays Widget
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\widgets;
@@ -1,13 +1,12 @@
<?php
/**
* @brief upcomingEvents Widget
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @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 18 Dec 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\widgets;