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

+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' );
}
}