Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -11,41 +11,59 @@
|
||||
namespace IPS\calendar\extensions\core\AchievementAction;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Calendar;
|
||||
use IPS\calendar\Event;
|
||||
use IPS\core\Achievements\Actions\AchievementActionAbstract;
|
||||
use IPS\core\Achievements\Rule;
|
||||
use IPS\Db;
|
||||
use IPS\Db\Select;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Achievement Action Extension
|
||||
*/
|
||||
class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction // NOTE: Other classes exist to provided bases for common situations, like where node-based filters will be required
|
||||
class Rsvp extends AchievementActionAbstract // NOTE: Other classes exist to provided bases for common situations, like where node-based filters will be required
|
||||
{
|
||||
/**
|
||||
* Get filter form elements
|
||||
*
|
||||
* @param array|NULL $filters Current filter values (if editing)
|
||||
* @param \IPS\Http\Url $url The URL the form is being shown on
|
||||
* @param Url $url The URL the form is being shown on
|
||||
* @return array
|
||||
*/
|
||||
public function filters( ?array $filters, \IPS\Http\Url $url ): array
|
||||
public function filters( ?array $filters, Url $url ): array
|
||||
{
|
||||
$return = array();
|
||||
|
||||
$return['nodes'] = new \IPS\Helpers\Form\Node( 'achievement_filter_Rsvp_nodes', ( $filters and isset( $filters['nodes'] ) and $filters['nodes'] ) ? $filters['nodes'] : 0, FALSE, [
|
||||
$return['nodes'] = new Node( 'achievement_filter_Rsvp_nodes', ( $filters and isset( $filters['nodes'] ) and $filters['nodes'] ) ? $filters['nodes'] : 0, FALSE, [
|
||||
'url' => $url,
|
||||
'class' => 'IPS\calendar\Calendar',
|
||||
'showAllNodes' => TRUE,
|
||||
'multiple' => TRUE,
|
||||
], NULL, \IPS\Member::loggedIn()->language()->addToStack( 'achievement_filter_NewContentItem_node_prefix', FALSE, [ 'sprintf' => [
|
||||
\IPS\Member::loggedIn()->language()->addToStack( 'rsvp', FALSE ),
|
||||
\IPS\Member::loggedIn()->language()->addToStack( 'calendars_sg', FALSE, [ 'strtolower' => TRUE ] )
|
||||
], NULL, Member::loggedIn()->language()->addToStack( 'achievement_filter_NewContentItem_node_prefix', FALSE, [ 'sprintf' => [
|
||||
Member::loggedIn()->language()->addToStack( 'rsvp', FALSE ),
|
||||
Member::loggedIn()->language()->addToStack( 'calendars', FALSE, [ 'strtolower' => TRUE ] )
|
||||
] ] ) );
|
||||
$return['nodes']->label = \IPS\Member::loggedIn()->language()->addToStack( 'achievement_filter_NewContentItem_node', FALSE, [ 'sprintf' => [ \IPS\Member::loggedIn()->language()->addToStack( 'calendars_sg', FALSE, [ 'strtolower' => TRUE ] ) ] ] );
|
||||
$return['nodes']->label = Member::loggedIn()->language()->addToStack( 'achievement_filter_NewContentItem_node', FALSE, [ 'sprintf' => [ Member::loggedIn()->language()->addToStack( 'calendars', FALSE, [ 'strtolower' => TRUE ] ) ] ] );
|
||||
|
||||
$return['milestone'] = new \IPS\Helpers\Form\Number( 'achievement_filter_Rsvp_nth', ( $filters and isset( $filters['milestone'] ) and $filters['milestone'] ) ? $filters['milestone'] : 0, FALSE, [], NULL, \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_nth_their'), \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_Rsvp_nth_suffix') );
|
||||
$return['milestone']->label = \IPS\Member::loggedIn()->language()->addToStack('achievement_filter_NewContentItem_nth');
|
||||
$return['milestone'] = new Number( 'achievement_filter_Rsvp_nth', ( $filters and isset( $filters['milestone'] ) and $filters['milestone'] ) ? $filters['milestone'] : 0, FALSE, [], NULL, Member::loggedIn()->language()->addToStack('achievement_filter_nth_their'), Member::loggedIn()->language()->addToStack('achievement_filter_Rsvp_nth_suffix') );
|
||||
$return['milestone']->label = Member::loggedIn()->language()->addToStack('achievement_filter_NewContentItem_nth');
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -77,16 +95,16 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
* calls that BEFORE making its change in the database (or there is read/write separation), you will need to add
|
||||
* 1 to the value being considered for milestones
|
||||
*
|
||||
* @param \IPS\Member $subject The subject member
|
||||
* @param Member $subject The subject member
|
||||
* @param array $filters The value returned by formatFilterValues()
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @param mixed|null $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @return bool
|
||||
*/
|
||||
public function filtersMatch( \IPS\Member $subject, array $filters, $extra = NULL ): bool
|
||||
public function filtersMatch( Member $subject, array $filters, mixed $extra = NULL ): bool
|
||||
{
|
||||
if ( isset( $filters['nodes'] ) )
|
||||
{
|
||||
if ( !\in_array( $extra->container()->_id, $filters['nodes'] ) )
|
||||
if ( !in_array( $extra->container()->_id, $filters['nodes'] ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -123,11 +141,11 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
/**
|
||||
* Get the "other" people we need to award =stuff to
|
||||
*
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @param mixed|null $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @param array|NULL $filters Current filter values
|
||||
* @return array
|
||||
*/
|
||||
public function awardOther( $extra = NULL, ?array $filters = NULL ): array
|
||||
public function awardOther( mixed $extra = NULL, ?array $filters = NULL ): array
|
||||
{
|
||||
return [ $extra->author() ];
|
||||
}
|
||||
@@ -136,11 +154,11 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
* Get identifier to prevent the member being awarded points for the same action twice
|
||||
* Must be unique within within of this domain, must not exceed 32 chars.
|
||||
*
|
||||
* @param \IPS\Member $subject The subject member
|
||||
* @param mixed $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @param Member $subject The subject member
|
||||
* @param mixed|null $extra Any additional information about what is happening (e.g. if a post is being made: the post object)
|
||||
* @return string
|
||||
*/
|
||||
public function identifier( \IPS\Member $subject, $extra = NULL ): string
|
||||
public function identifier( Member $subject, mixed $extra = NULL ): string
|
||||
{
|
||||
return 'Rsvp:' . $extra->id . ':' . $subject->member_id;
|
||||
}
|
||||
@@ -156,38 +174,37 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
{
|
||||
$exploded = explode( ':', $identifier );
|
||||
|
||||
$sprintf = [];
|
||||
try
|
||||
{
|
||||
$item = \IPS\calendar\Event::load( $exploded[1] );
|
||||
$item = Event::load( $exploded[1] );
|
||||
$sprintf = [ 'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $item->url(), TRUE, $item->mapped('title') ?: $item->indefiniteArticle(), FALSE )
|
||||
Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $item->url(), TRUE, $item->mapped('title') ?: $item->indefiniteArticle(), FALSE )
|
||||
] ];
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException $e )
|
||||
{
|
||||
$sprintf = [ 'sprintf' => [ \IPS\Member::loggedIn()->language()->addToStack('modcp_deleted') ] ];
|
||||
$sprintf = [ 'sprintf' => [ Member::loggedIn()->language()->addToStack('modcp_deleted') ] ];
|
||||
}
|
||||
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'AchievementAction__Rsvp_log', FALSE, $sprintf );
|
||||
return Member::loggedIn()->language()->addToStack( 'AchievementAction__Rsvp_log', FALSE, $sprintf );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "description" for rule
|
||||
*
|
||||
* @param \IPS\core\Achievements\Rule $rule The rule
|
||||
* @param Rule $rule The rule
|
||||
* @return string|NULL
|
||||
*/
|
||||
public function ruleDescription( \IPS\core\Achievements\Rule $rule ): ?string
|
||||
public function ruleDescription( Rule $rule ): ?string
|
||||
{
|
||||
$conditions = [];
|
||||
if ( isset( $rule->filters['milestone'] ) )
|
||||
{
|
||||
$conditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone', FALSE, [
|
||||
$conditions[] = Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone', FALSE, [
|
||||
'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'milestone', \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone_nth', FALSE, [ 'pluralize' => [ $rule->filters['milestone'] ] ] ) )
|
||||
Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'milestone', Member::loggedIn()->language()->addToStack( 'achievements_title_filter_milestone_nth', FALSE, [ 'pluralize' => [ $rule->filters['milestone'] ] ] ) )
|
||||
],
|
||||
'sprintf' => [ \IPS\Member::loggedIn()->language()->addToStack('rsvp') ]
|
||||
'sprintf' => [ Member::loggedIn()->language()->addToStack('rsvp') ]
|
||||
] );
|
||||
}
|
||||
if ( $nodeCondition = $this->_nodeFilterDescription( $rule ) )
|
||||
@@ -195,8 +212,8 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
$conditions[] = $nodeCondition;
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescription(
|
||||
\IPS\Member::loggedIn()->language()->addToStack( 'AchievementAction__Rsvp_title' ),
|
||||
return Theme::i()->getTemplate( 'achievements' )->ruleDescription(
|
||||
Member::loggedIn()->language()->addToStack( 'AchievementAction__Rsvp_title' ),
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
@@ -204,10 +221,10 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
/**
|
||||
* Get "description" for rule (usually a description of the rule's filters)
|
||||
*
|
||||
* @param \IPS\core\Achievements\Rule $rule The rule
|
||||
* @param Rule $rule The rule
|
||||
* @return string|NULL
|
||||
*/
|
||||
protected function _nodeFilterDescription( \IPS\core\Achievements\Rule $rule ): ?string
|
||||
protected function _nodeFilterDescription( Rule $rule ): ?string
|
||||
{
|
||||
if ( isset( $rule->filters['nodes'] ) )
|
||||
{
|
||||
@@ -216,20 +233,20 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
{
|
||||
try
|
||||
{
|
||||
$nodeNames[] = \IPS\calendar\Calendar::load( $id )->_title;
|
||||
$nodeNames[] = Calendar::load( $id )->_title;
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
catch ( OutOfRangeException $e ) {}
|
||||
}
|
||||
if ( $nodeNames )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location', FALSE, [
|
||||
return Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location', FALSE, [
|
||||
'htmlsprintf' => [
|
||||
\IPS\Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'location',
|
||||
\count( $nodeNames ) === 1 ? $nodeNames[0] : \IPS\Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location_val', FALSE, [ 'sprintf' => [
|
||||
\count( $nodeNames ),
|
||||
\IPS\Member::loggedIn()->language()->addToStack( 'calendars', FALSE, [ 'strtolower' => TRUE ] )
|
||||
Theme::i()->getTemplate( 'achievements' )->ruleDescriptionBadge( 'location',
|
||||
count( $nodeNames ) === 1 ? $nodeNames[0] : Member::loggedIn()->language()->addToStack( 'achievements_title_filter_location_val', FALSE, [ 'sprintf' => [
|
||||
count( $nodeNames ),
|
||||
Member::loggedIn()->language()->addToStack( 'calendars', FALSE, [ 'strtolower' => TRUE ] )
|
||||
] ] ),
|
||||
\count( $nodeNames ) === 1 ? NULL : $nodeNames
|
||||
count( $nodeNames ) === 1 ? NULL : $nodeNames
|
||||
)
|
||||
],
|
||||
] );
|
||||
@@ -239,74 +256,29 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild points and badges based on the content this rule manages
|
||||
*
|
||||
* @param array $data The rebuild data
|
||||
* @param array $filters The value returned by formatFilterValues()
|
||||
* @param int $lastId The last ID returned by a previous iteration
|
||||
* @param int $limit The limit of how many to rebuild
|
||||
* @param \IPS\DataTime|null $time Any time limit to add
|
||||
* @return array
|
||||
*/
|
||||
public function processRebuild( $data, $filters, $lastId, $limit, \IPS\DateTime $time = NULL ): array
|
||||
{
|
||||
$where = ( $time ? [ ['rsvp_id > ? and rsvp_date >= ?', $lastId, $time->getTimestamp() ] ] : [ [ 'rsvp_id > ?', $lastId ] ] );
|
||||
|
||||
/* Try and limit the number of rows for the good of humanity */
|
||||
$query = $this->getQuery( '*', $where, $limit, 'rsvp_id ASC', $filters );
|
||||
$done = 0;
|
||||
foreach( $query as $row )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\Member::load( $row['rsvp_member_id'] )->achievementAction( 'calendar', 'Rsvp', [ \IPS\calendar\Event::load( $row['rsvp_event_id'] ) ] );
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
|
||||
$done++;
|
||||
$lastId = $row['rsvp_id'];
|
||||
}
|
||||
|
||||
return [ 'processed' => $done, 'lastId' => $lastId ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rebuild data
|
||||
*
|
||||
* @param array $data Data stored with the queue item
|
||||
* @param array $filters The value returned by formatFilterValues()
|
||||
* @param \IPS\DataTime|null $time Any time limit to add
|
||||
* @return void
|
||||
*/
|
||||
public function preRebuildData( &$data, $filters, \IPS\DateTime $time = NULL )
|
||||
{
|
||||
$data['count'] = $this->getQuery( 'COUNT(*)', ( $time ? [ ['rsvp_date >= ?', $time->getTimestamp() ] ] : [] ), NULL, NULL, $filters )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a query to use for multiple methods within this extension
|
||||
* @param string $select Select for the query
|
||||
* @param array|NULL $where Where for the query
|
||||
* @param int|NULL $limit Limit for the query
|
||||
* @param string|NULL $order Order by for the query
|
||||
* @param array $filters Rule filters
|
||||
* @return \IPS\Db\Select
|
||||
* @param string $select Select for the query
|
||||
* @param array|null $where Where for the query
|
||||
* @param int|null $limit Limit for the query
|
||||
* @param string|null $order Order by for the query
|
||||
* @param array $filters Rule filters
|
||||
* @return Select
|
||||
*/
|
||||
public function getQuery( $select, $where, $limit, $order, $filters ): \IPS\Db\Select
|
||||
public function getQuery( string $select, ?array $where, ?int $limit, ?string $order, array $filters ): Select
|
||||
{
|
||||
$joinContainers = FALSE;
|
||||
$extraJoinCondition = NULL;
|
||||
$where = \is_array( $where ) ? $where : array();
|
||||
$where = is_array( $where ) ? $where : array();
|
||||
|
||||
/* Limit by node */
|
||||
if ( isset( $filters['nodes'] ) )
|
||||
{
|
||||
$joinContainers = TRUE;
|
||||
$extraJoinCondition = ' AND ' . \IPS\Db::i()->in( 'calendar_events.event_calendar_id', $filters['nodes'] );
|
||||
$extraJoinCondition = ' AND ' . Db::i()->in( 'calendar_events.event_calendar_id', $filters['nodes'] );
|
||||
}
|
||||
|
||||
$query = \IPS\Db::i()->select( $select, 'calendar_event_rsvp', $where, $order, $limit );
|
||||
$query = Db::i()->select( $select, 'calendar_event_rsvp', $where, $order, $limit );
|
||||
|
||||
if ( $joinContainers )
|
||||
{
|
||||
@@ -315,4 +287,32 @@ class _Rsvp extends \IPS\core\Achievements\Actions\AbstractAchievementAction //
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rebuild data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function rebuildData(): array
|
||||
{
|
||||
return [ [
|
||||
'table' => 'calendar_event_rsvp',
|
||||
'pkey' => 'rsvp_id',
|
||||
'where' => [ [ 'status=?', Event::RSVP_YES ] ],
|
||||
] ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the rebuild row
|
||||
*
|
||||
* @param array $row Row from database
|
||||
* @param array $data Data collected when starting rebuild [table, pkey...]
|
||||
* @return void
|
||||
*/
|
||||
public static function rebuildRow( array $row, array $data ) : void
|
||||
{
|
||||
$event = Event::load( $row['rsvp_event_id'] );
|
||||
$member = Member::load( $row['rsvp_member_id'] );
|
||||
$member->achievementAction( 'calendar', 'Rsvp', $event );
|
||||
}
|
||||
}
|
||||
@@ -12,35 +12,42 @@
|
||||
namespace IPS\calendar\extensions\core\Announcements;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\core\Announcements\Announcement;
|
||||
use IPS\Extensions\AnnouncementsAbstract;
|
||||
use IPS\Helpers\Form\FormAbstract;
|
||||
use IPS\Helpers\Form\Node;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Announcements Extension
|
||||
*/
|
||||
class _Calendars
|
||||
class Calendars extends AnnouncementsAbstract
|
||||
{
|
||||
/**
|
||||
* @brief ID Field
|
||||
*/
|
||||
public static $idField = "id";
|
||||
public static string $idField = "id";
|
||||
|
||||
/**
|
||||
* @brief Controller classes
|
||||
*/
|
||||
public static $controllers = array( "IPS\\calendar\\modules\\front\\calendar\\view" );
|
||||
public static array $controllers = array( "IPS\\calendar\\modules\\front\\calendar\\view" );
|
||||
|
||||
/**
|
||||
* Get Setting Field
|
||||
*
|
||||
* @param \IPS\core\Announcements\Announcement $announcement
|
||||
* @return Form element
|
||||
* @param Announcement|null $announcement
|
||||
* @return FormAbstract Form element
|
||||
*/
|
||||
public function getSettingField( $announcement )
|
||||
public function getSettingField( ?Announcement $announcement ): FormAbstract
|
||||
{
|
||||
return new \IPS\Helpers\Form\Node( 'announce_calendars', ( $announcement AND $announcement->ids ) ? explode( ",", $announcement->ids ) : 0, FALSE, array( 'class' => 'IPS\calendar\Calendar', 'zeroVal' => 'any', 'multiple' => TRUE ), NULL, NULL, NULL, 'announce_calendars' );
|
||||
return new Node( 'announce_calendars', ( $announcement AND $announcement->ids ) ? explode( ",", $announcement->ids ) : 0, FALSE, array( 'class' => 'IPS\calendar\Calendar', 'zeroVal' => 'any', 'multiple' => TRUE ), NULL, NULL, NULL, 'announce_calendars' );
|
||||
}
|
||||
}
|
||||
@@ -12,36 +12,33 @@
|
||||
namespace IPS\calendar\extensions\core\ContentRouter;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Application\Module;
|
||||
use IPS\Extensions\ContentRouterAbstract;
|
||||
use IPS\Member;
|
||||
use IPS\Member\Group;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Content Router extension: Calendar
|
||||
*/
|
||||
class _Calendar
|
||||
class Calendar extends ContentRouterAbstract
|
||||
{
|
||||
/**
|
||||
* @brief Content Item Classes
|
||||
*/
|
||||
public $classes = array();
|
||||
|
||||
/**
|
||||
* @brief Can be shown in similar content
|
||||
*/
|
||||
public $similarContent = FALSE;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \IPS\Member|IPS\Member\Group|NULL $member If checking access, the member/group to check for, or NULL to not check access
|
||||
* @param Member|Group|NULL $member If checking access, the member/group to check for, or NULL to not check access
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $member = NULL )
|
||||
public function __construct( Group|Member $member = NULL )
|
||||
{
|
||||
if ( $member === NULL or $member->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar', 'front' ) ) )
|
||||
if ( $member === NULL or $member->canAccessModule( Module::get( 'calendar', 'calendar', 'front' ) ) )
|
||||
{
|
||||
$this->classes[] = 'IPS\calendar\Event';
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Create Menu Extension
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace IPS\calendar\extensions\core\CreateMenu;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Menu Extension
|
||||
*/
|
||||
class _Event
|
||||
{
|
||||
/**
|
||||
* Get Items
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
if ( \IPS\calendar\Calendar::canOnAny( 'add', NULL, \IPS\Settings::i()->club_nodes_in_apps ? array() : array( array( 'cal_club_id IS NULL' ) ) ) )
|
||||
{
|
||||
if ( !\IPS\Settings::i()->club_nodes_in_apps and $theOnlyNode = \IPS\calendar\Calendar::theOnlyNode() )
|
||||
{
|
||||
return array(
|
||||
'event' => array(
|
||||
'link' => \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=submit&do=submit&id=" . $theOnlyNode->_id, 'front', 'calendar_submit' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return array(
|
||||
'event' => array(
|
||||
'link' => \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=submit&_new=1", 'front', 'calendar_submit' ),
|
||||
'extraData' => array( 'data-ipsDialog' => true, 'data-ipsDialog-size' => "narrow", ),
|
||||
'title' => 'select_calendar'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -12,35 +12,40 @@
|
||||
namespace IPS\calendar\extensions\core\EditorLocations;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Event;
|
||||
use IPS\calendar\Event\Comment;
|
||||
use IPS\calendar\Event\Review;
|
||||
use IPS\Content;
|
||||
use IPS\Extensions\EditorLocationsAbstract;
|
||||
use IPS\Helpers\Form\Editor;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Node\Model;
|
||||
use LogicException;
|
||||
use OutOfRangeException;
|
||||
use RuntimeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor Extension: Calendar event text and comments
|
||||
*/
|
||||
class _Calendar
|
||||
class Calendar extends EditorLocationsAbstract
|
||||
{
|
||||
/**
|
||||
* 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 Member $member
|
||||
* @param 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 )
|
||||
public function canAttach( Member $member, Editor $field ): bool|null
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -49,11 +54,11 @@ class _Calendar
|
||||
* Can whatever is posted in this editor be moderated?
|
||||
* If this returns TRUE, we must ensure the content is ran through word, link and image filters
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param \IPS\Helpers\Form\Editor $field The editor field
|
||||
* @param Member $member The member
|
||||
* @param Editor $field The editor field
|
||||
* @return bool
|
||||
*/
|
||||
public function canBeModerated( $member, $field )
|
||||
public function canBeModerated( Member $member, Editor $field ): bool
|
||||
{
|
||||
/* Creating/editing an event */
|
||||
if ( preg_match( '/^calendar-event(?:\-\d+)?$/', $field->options['autoSaveKey'] ) )
|
||||
@@ -70,31 +75,32 @@ class _Calendar
|
||||
{
|
||||
if ( \IPS\IN_DEV )
|
||||
{
|
||||
throw new \RuntimeException( 'Unknown canBeModerated: ' . $field->options['autoSaveKey'] );
|
||||
throw new RuntimeException( 'Unknown canBeModerated: ' . $field->options['autoSaveKey'] );
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
return parent::canBeModerated( $member, $field );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
|
||||
* @param 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
|
||||
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
|
||||
* @return bool
|
||||
*/
|
||||
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
|
||||
public function attachmentPermissionCheck( Member $member, ?int $id1, ?int $id2, ?string $id3, array $attachment, bool $viewOnly=FALSE ): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$event = \IPS\calendar\Event::load( $id1 );
|
||||
$event = Event::load( $id1 );
|
||||
return $event->canView( $member );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException $e )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -103,28 +109,28 @@ class _Calendar
|
||||
/**
|
||||
* Attachment lookup
|
||||
*
|
||||
* @param int|null $id1 Primary ID
|
||||
* @param int|null $id2 Secondary ID
|
||||
* @param string|null $id3 Arbitrary data
|
||||
* @return \IPS\calendar\Event\Review|\IPS\calendar\Event\Comment|\IPS\calendar\Event
|
||||
* @throws \LogicException
|
||||
* @param int|null $id1 Primary ID
|
||||
* @param int|null $id2 Secondary ID
|
||||
* @param string|null $id3 Arbitrary data
|
||||
* @return Content|Member|Model|Url|null
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function attachmentLookup( $id1, $id2, $id3 )
|
||||
public function attachmentLookup( ?int $id1=null, ?int $id2=null, ?string $id3=null ): Model|Content|Url|Member|null
|
||||
{
|
||||
if ( $id2 )
|
||||
{
|
||||
if ( $id3 === 'review' )
|
||||
{
|
||||
return \IPS\calendar\Event\Review::load( $id2 );
|
||||
return Review::load( $id2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\calendar\Event\Comment::load( $id2 );
|
||||
return Comment::load( $id2 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\calendar\Event::load( $id1 );
|
||||
return Event::load( $id1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,36 +12,35 @@
|
||||
namespace IPS\calendar\extensions\core\EditorLocations;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Content;
|
||||
use IPS\Extensions\EditorLocationsAbstract;
|
||||
use IPS\Helpers\Form\Editor;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Node\Model;
|
||||
use LogicException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Editor Extension: Venue
|
||||
*/
|
||||
class _Venue
|
||||
class Venue extends EditorLocationsAbstract
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
* @param Member $member The member
|
||||
* @param 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 )
|
||||
public function canAttach( Member $member, Editor $field ): ?bool
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -49,7 +48,7 @@ class _Venue
|
||||
/**
|
||||
* Permission check for attachments
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param Member $member The member
|
||||
* @param int|null $id1 Primary ID
|
||||
* @param int|null $id2 Secondary ID
|
||||
* @param string|null $id3 Arbitrary data
|
||||
@@ -57,7 +56,7 @@ class _Venue
|
||||
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
|
||||
* @return bool
|
||||
*/
|
||||
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
|
||||
public function attachmentPermissionCheck( Member $member, ?int $id1, ?int $id2, ?string $id3, array $attachment, bool $viewOnly=FALSE ): bool
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -65,14 +64,14 @@ class _Venue
|
||||
/**
|
||||
* 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
|
||||
* @param int|null $id1 Primary ID
|
||||
* @param int|null $id2 Secondary ID
|
||||
* @param string|null $id3 Arbitrary data
|
||||
* @return Content|Member|Model|Url|null
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function attachmentLookup( $id1, $id2, $id3 )
|
||||
public function attachmentLookup( ?int $id1=null, ?int $id2=null, ?string $id3=null ): Model|Content|Url|Member|null
|
||||
{
|
||||
// return \IPS\Http\Url::internal( ... );
|
||||
throw new LogicException;
|
||||
}
|
||||
}
|
||||
@@ -12,86 +12,78 @@
|
||||
namespace IPS\calendar\extensions\core\FileStorage;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use Exception;
|
||||
use IPS\Db;
|
||||
use IPS\Extensions\FileStorageAbstract;
|
||||
use IPS\File;
|
||||
use UnderflowException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* File Storage Extension: Events
|
||||
*/
|
||||
class _Events
|
||||
class Events extends FileStorageAbstract
|
||||
{
|
||||
/**
|
||||
* Count stored files
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
public function count(): int
|
||||
{
|
||||
return \IPS\Db::i()->select( 'COUNT(*)', 'calendar_events', 'event_cover_photo IS NOT NULL' )->first();
|
||||
return Db::i()->select( 'COUNT(*)', 'calendar_events', 'event_cover_photo IS NOT NULL' )->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move stored files
|
||||
*
|
||||
* @param int $offset This will be sent starting with 0, increasing to get all files stored by this extension
|
||||
* @param int $storageConfiguration New storage configuration ID
|
||||
* @param int|NULL $oldConfiguration Old storage configuration ID
|
||||
* @throws \Underflowexception When file record doesn't exist. Indicating there are no more files to move
|
||||
* @param int $offset This will be sent starting with 0, increasing to get all files stored by this extension
|
||||
* @param int $storageConfiguration New storage configuration ID
|
||||
* @param int|null $oldConfiguration Old storage configuration ID
|
||||
* @return void
|
||||
*@throws Underflowexception When file record doesn't exist. Indicating there are no more files to move
|
||||
*/
|
||||
public function move( $offset, $storageConfiguration, $oldConfiguration=NULL )
|
||||
public function move( int $offset, int $storageConfiguration, int $oldConfiguration=NULL ) : void
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'calendar_events', 'event_cover_photo IS NOT NULL', 'event_id', array( $offset, 1 ) )->first();
|
||||
$record = Db::i()->select( '*', 'calendar_events', 'event_cover_photo IS NOT NULL', 'event_id', array( $offset, 1 ) )->first();
|
||||
|
||||
try
|
||||
{
|
||||
$file = \IPS\File::get( $oldConfiguration ?: 'calendar_Events', $record['event_cover_photo'] )->move( $storageConfiguration );
|
||||
$file = File::get( $oldConfiguration ?: 'calendar_Events', $record['event_cover_photo'] )->move( $storageConfiguration );
|
||||
|
||||
if ( (string) $file != $record['event_cover_photo'] )
|
||||
{
|
||||
\IPS\Db::i()->update( 'calendar_events', array( 'event_cover_photo' => (string) $file ), array( 'event_id=?', $record['event_id'] ) );
|
||||
Db::i()->update( 'calendar_events', array( 'event_cover_photo' => (string) $file ), array( 'event_id=?', $record['event_id'] ) );
|
||||
}
|
||||
}
|
||||
catch( \Exception $e )
|
||||
catch( Exception $e )
|
||||
{
|
||||
/* Any issues are logged and the \IPS\Db::i()->update not run as the exception is thrown */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix all URLs
|
||||
*
|
||||
* @param int $offset This will be sent starting with 0, increasing to get all files stored by this extension
|
||||
* @return void
|
||||
*/
|
||||
public function fixUrls( $offset )
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'calendar_events', 'event_cover_photo IS NOT NULL', 'event_id', array( $offset, 1 ) )->first();
|
||||
|
||||
if ( $new = \IPS\File::repairUrl( $record['event_cover_photo'] ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'calendar_events', array( 'event_cover_photo' => $new ), array( 'event_id=?', $record['event_id'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is valid
|
||||
*
|
||||
* @param string $file The file path to check
|
||||
* @param File|string $file The file path to check
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidFile( $file )
|
||||
public function isValidFile( File|string $file ): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'calendar_events', array( 'event_cover_photo=?', (string) $file ) )->first();
|
||||
$record = Db::i()->select( '*', 'calendar_events', array( 'event_cover_photo=?', (string) $file ) )->first();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
catch ( UnderflowException $e )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -102,15 +94,15 @@ class _Events
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
public function delete() : void
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'calendar_events', 'event_cover_photo IS NOT NULL' ) as $event )
|
||||
foreach( Db::i()->select( '*', 'calendar_events', 'event_cover_photo IS NOT NULL' ) as $event )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\File::get( 'calendar_Events', $event['event_cover_photo'] )->delete();
|
||||
File::get( 'calendar_Events', $event['event_cover_photo'] )->delete();
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
catch( Exception $e ){}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,64 +12,78 @@
|
||||
namespace IPS\calendar\extensions\core\FrontNavigation;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\Application\Module;
|
||||
use IPS\core\FrontNavigation;
|
||||
use IPS\core\FrontNavigation\FrontNavigationAbstract;
|
||||
use IPS\Dispatcher;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Front Navigation Extension: Calendar
|
||||
*/
|
||||
class _Calendar extends \IPS\core\FrontNavigation\FrontNavigationAbstract
|
||||
class Calendar extends FrontNavigationAbstract
|
||||
{
|
||||
/**
|
||||
* @var string Default icon
|
||||
*/
|
||||
public string $defaultIcon = '\f133';
|
||||
|
||||
/**
|
||||
* Get Type Title which will display in the AdminCP Menu Manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function typeTitle()
|
||||
public static function typeTitle(): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('frontnavigation_calendar');
|
||||
return Member::loggedIn()->language()->addToStack('frontnavigation_calendar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the currently logged in user access the content this item links to?
|
||||
*
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
public function canAccessContent()
|
||||
public function canAccessContent(): bool
|
||||
{
|
||||
return \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar' ) );
|
||||
return Member::loggedIn()->canAccessModule( Module::get( 'calendar', 'calendar' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title
|
||||
*
|
||||
* @return string
|
||||
* @return string
|
||||
*/
|
||||
public function title()
|
||||
public function title(): string
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('frontnavigation_calendar');
|
||||
return Member::loggedIn()->language()->addToStack('frontnavigation_calendar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Link
|
||||
*
|
||||
* @return \IPS\Http\Url
|
||||
* @return string|Url|null
|
||||
*/
|
||||
public function link()
|
||||
public function link(): Url|string|null
|
||||
{
|
||||
return \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=view", 'front', 'calendar' );
|
||||
return Url::internal( "app=calendar&module=calendar&controller=view", 'front', 'calendar' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Active?
|
||||
*
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
public function active()
|
||||
public function active(): bool
|
||||
{
|
||||
return !\IPS\core\FrontNavigation::$clubTabActive and \IPS\Dispatcher::i()->application->directory === 'calendar';
|
||||
return !FrontNavigation::$clubTabActive and !FrontNavigation::nodeExtensionIsActive( 'calendar' ) and Dispatcher::i()->application->directory === 'calendar';
|
||||
}
|
||||
}
|
||||
@@ -12,26 +12,35 @@
|
||||
namespace IPS\calendar\extensions\core\LiveSearch;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Calendar;
|
||||
use IPS\Db;
|
||||
use IPS\Dispatcher;
|
||||
use IPS\Extensions\LiveSearchAbstract;
|
||||
use IPS\Member;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ACP Live Search Extension
|
||||
*/
|
||||
class _Calendars
|
||||
class Calendars extends LiveSearchAbstract
|
||||
{
|
||||
/**
|
||||
* Check we have access
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess()
|
||||
public function hasAccess(): bool
|
||||
{
|
||||
/* Check Permissions */
|
||||
return \IPS\Member::loggedIn()->hasAcpRestriction( 'calendar', 'calendars', 'calendars_manage' );
|
||||
return Member::loggedIn()->hasAcpRestriction( 'calendar', 'calendars', 'calendars_manage' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,7 +49,7 @@ class _Calendars
|
||||
* @param string $searchTerm Search Term
|
||||
* @return array Array of results
|
||||
*/
|
||||
public function getResults( $searchTerm )
|
||||
public function getResults( string $searchTerm ): array
|
||||
{
|
||||
/* Init */
|
||||
$results = array();
|
||||
@@ -50,10 +59,10 @@ class _Calendars
|
||||
if( $this->hasAccess() )
|
||||
{
|
||||
/* Perform the search */
|
||||
$calendars = \IPS\Db::i()->select(
|
||||
$calendars = Db::i()->select(
|
||||
"*",
|
||||
'calendar_calendars',
|
||||
array( "cal_club_id IS NULL AND 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, Member::loggedIn()->language()->id ),
|
||||
NULL,
|
||||
NULL
|
||||
)->join(
|
||||
@@ -64,9 +73,9 @@ class _Calendars
|
||||
/* Format results */
|
||||
foreach ( $calendars as $calendar )
|
||||
{
|
||||
$calendar = \IPS\calendar\Calendar::constructFromData( $calendar );
|
||||
$calendar = Calendar::constructFromData( $calendar );
|
||||
|
||||
$results[] = \IPS\Theme::i()->getTemplate( 'livesearch', 'calendar', 'admin' )->calendar( $calendar );
|
||||
$results[] = Theme::i()->getTemplate( 'livesearch', 'calendar', 'admin' )->calendar( $calendar );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +87,8 @@ class _Calendars
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDefault()
|
||||
public function isDefault(): bool
|
||||
{
|
||||
return \IPS\Dispatcher::i()->application->directory == 'calendar';
|
||||
return Dispatcher::i()->application->directory == 'calendar';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Member Filter Extension
|
||||
* @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 Events
|
||||
* @since 30 Jan 2024
|
||||
*/
|
||||
|
||||
namespace IPS\calendar\extensions\core\MemberFilter;
|
||||
|
||||
use IPS\calendar\Event;
|
||||
use IPS\Db;
|
||||
use IPS\Db\Select;
|
||||
use IPS\Extensions\MemberFilterAbstract;
|
||||
use IPS\Helpers\Form\Item;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\Member;
|
||||
use LogicException;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Member Filter Extension
|
||||
*/
|
||||
class Rsvp extends MemberFilterAbstract
|
||||
{
|
||||
/**
|
||||
* Determine if the filter is available in a given area
|
||||
*
|
||||
* @param string $area Area to check (bulkmail, group_promotions, automatic_moderation, passwordreset)
|
||||
* @return bool
|
||||
*/
|
||||
public function availableIn( string $area ): bool
|
||||
{
|
||||
return in_array( $area, array( 'bulkmail', 'group_promotions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Setting Field
|
||||
*
|
||||
* @param array $criteria Value returned from the save() method
|
||||
* @return array Array of form elements
|
||||
*/
|
||||
public function getSettingField( array $criteria ): array
|
||||
{
|
||||
return array(
|
||||
new YesNo( 'mf_rsvp', $criteria['rsvp'] ?? null, false, array( 'togglesOn' => array( 'mf_rsvp_events' ) ) ),
|
||||
new Item( 'mf_rsvp_events', $criteria['rsvp_events'] ?? -1, false, array( 'class' => Event::class, 'maxItems' => null ), null, null, null, 'mf_rsvp_events' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the filter data
|
||||
*
|
||||
* @param array $post Form values
|
||||
* @return array|bool False, or an array of data to use later when filtering the members
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function save( array $post ) : array|bool
|
||||
{
|
||||
if( isset( $post['mf_rsvp'] ) and $post['mf_rsvp'] )
|
||||
{
|
||||
$events = [];
|
||||
if( is_array( $post['mf_rsvp_events'] ) )
|
||||
{
|
||||
foreach( $post['mf_rsvp_events'] as $event )
|
||||
{
|
||||
$events[] = $event->id;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'rsvp' => true,
|
||||
'rsvp_events' => count( $events ) ? $events : -1
|
||||
];
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get where clause to add to the member retrieval database query
|
||||
*
|
||||
* @param array $data The array returned from the save() method
|
||||
* @return array|NULL Where clause - must be a single array( "clause" )
|
||||
*/
|
||||
public function getQueryWhereClause( array $data ): ?array
|
||||
{
|
||||
if( isset( $data['rsvp'] ) and $data['rsvp'] )
|
||||
{
|
||||
$where = [
|
||||
[ 'rsvp_response<>?', Event::RSVP_NO ]
|
||||
];
|
||||
|
||||
if( isset( $data['events'] ) and $data['events'] != -1 )
|
||||
{
|
||||
$where[] = [ Db::i()->in( 'rsvp_event_id', $data['events'] ) ];
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for member retrieval database query
|
||||
* Can be used to set joins
|
||||
*
|
||||
* @param array $data The array returned from the save() method
|
||||
* @param Select $query The query
|
||||
* @return void
|
||||
*/
|
||||
public function queryCallback( array $data, Select $query ) : void
|
||||
{
|
||||
if( isset( $data['rsvp'] ) and $data['rsvp'] )
|
||||
{
|
||||
$query->join( 'calendar_event_rsvp', "core_members.member_id=calendar_event_rsvp.rsvp_member_id" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a member matches specified filters
|
||||
*
|
||||
* @note This is only necessary if availableIn() includes group_promotions
|
||||
* @param Member $member Member object to check
|
||||
* @param array $filters Previously defined filters
|
||||
* @param object|NULL $object Calling class
|
||||
* @return bool
|
||||
*/
|
||||
public function matches( Member $member, array $filters, ?object $object=NULL ): bool
|
||||
{
|
||||
if( !isset( $filters['rsvp'] ) or !$filters['rsvp'] )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$where = [
|
||||
[ 'rsvp_member_id=?', $member->member_id ]
|
||||
];
|
||||
|
||||
if( isset( $filters['events'] ) and $filters['events'] !== -1 )
|
||||
{
|
||||
$where[] = [ Db::i()->in( 'rsvp_event_id', $filters['events'] ) ];
|
||||
}
|
||||
|
||||
return (bool) Db::i()->select( 'count(rsvp_id)', 'calendar_event_rsvp', $where )->first();
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Member Sync
|
||||
* @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
|
||||
*/
|
||||
|
||||
namespace IPS\calendar\extensions\core\MemberSync;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Member Sync
|
||||
*/
|
||||
class _Calendar
|
||||
{
|
||||
/**
|
||||
* Member is merged with another member
|
||||
*
|
||||
* @param \IPS\Member $member Member being kept
|
||||
* @param \IPS\Member $member2 Member being removed
|
||||
* @return void
|
||||
*/
|
||||
public function onMerge( $member, $member2 )
|
||||
{
|
||||
\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 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Member is deleted
|
||||
*
|
||||
* @param $member \IPS\Member The member
|
||||
* @return void
|
||||
*/
|
||||
public function onDelete( $member )
|
||||
{
|
||||
\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 ) );
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -11,24 +11,33 @@
|
||||
namespace IPS\calendar\extensions\core\Notifications;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Event;
|
||||
use IPS\Extensions\NotificationsAbstract;
|
||||
use IPS\Lang;
|
||||
use IPS\Member;
|
||||
use IPS\Notification\Inline;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification Options
|
||||
*/
|
||||
class _Events
|
||||
class Events extends NotificationsAbstract
|
||||
{
|
||||
/**
|
||||
* Get fields for configuration
|
||||
*
|
||||
* @param \IPS\Member|null $member The member (to take out any notification types a given member will never see) or NULL if this is for the ACP
|
||||
* @param Member|null $member The member (to take out any notification types a given member will never see) or NULL if this is for the ACP
|
||||
* @return array
|
||||
*/
|
||||
public static function configurationOptions( \IPS\Member $member = NULL ): array
|
||||
public static function configurationOptions( Member $member = NULL ): array
|
||||
{
|
||||
return array(
|
||||
'event_reminder' => array(
|
||||
@@ -46,7 +55,7 @@ class _Events
|
||||
/**
|
||||
* Parse notification: new_content
|
||||
*
|
||||
* @param \IPS\Notification\Inline $notification The notification
|
||||
* @param Inline $notification The notification
|
||||
* @param bool $htmlEscape TRUE to escape HTML in title
|
||||
* @return array
|
||||
* @code
|
||||
@@ -60,22 +69,22 @@ class _Events
|
||||
);
|
||||
* @endcode
|
||||
*/
|
||||
public function parse_new_content( $notification, $htmlEscape=TRUE )
|
||||
public function parse_new_content( Inline $notification, bool $htmlEscape=TRUE ): array
|
||||
{
|
||||
$item = $notification->item;
|
||||
if ( !$item )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
throw new OutOfRangeException;
|
||||
}
|
||||
|
||||
$name = ( $item->isAnonymous() ) ? \IPS\Member::loggedIn()->language()->addToStack( 'post_anonymously_placename' ) : $item->author()->name;
|
||||
$name = ( $item->isAnonymous() ) ? Member::loggedIn()->language()->addToStack( 'post_anonymously_placename' ) : $item->author()->name;
|
||||
|
||||
return array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__new_content', FALSE, array(
|
||||
'title' => Member::loggedIn()->language()->addToStack( 'notification__new_content', FALSE, array(
|
||||
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array(
|
||||
$name,
|
||||
mb_strtolower( $item->indefiniteArticle() ),
|
||||
$item->container()->getTitleForLanguage( \IPS\Member::loggedIn()->language(), $htmlEscape ? array( 'escape' => TRUE ) : array() ),
|
||||
$item->container()->getTitleForLanguage( Member::loggedIn()->language(), $htmlEscape ? array( 'escape' => TRUE ) : array() ),
|
||||
$item->mapped('title')
|
||||
)
|
||||
) ),
|
||||
@@ -89,31 +98,31 @@ class _Events
|
||||
/**
|
||||
* Parse notification: Event reminder
|
||||
*
|
||||
* @param \IPS\Notification\Inline $notification The notification
|
||||
* @param bool $htmlEscape TRUE to escape HTML in title
|
||||
* @param Inline $notification The notification
|
||||
* @param bool $htmlEscape TRUE to escape HTML in title
|
||||
* @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
|
||||
);
|
||||
* 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, $htmlEscape=TRUE )
|
||||
public function parse_event_reminder( Inline $notification, bool $htmlEscape=TRUE ): array
|
||||
{
|
||||
$item = $notification->item;
|
||||
if ( !$item )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
throw new OutOfRangeException;
|
||||
}
|
||||
|
||||
return array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'notification__event_reminder', FALSE, array(
|
||||
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array( \IPS\Member::loggedIn()->language()->addToStack( "days_to_go", FALSE, array( 'pluralize' => array( $notification->extra['daysToGo'] ) ) ), $item->mapped('title') )
|
||||
'title' => Member::loggedIn()->language()->addToStack( 'notification__event_reminder', FALSE, array(
|
||||
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array( 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(),
|
||||
@@ -125,11 +134,12 @@ class _Events
|
||||
/**
|
||||
* Parse notification for mobile: event_reminder
|
||||
*
|
||||
* @param \IPS\Lang $language The language that the notification should be in
|
||||
* @param \IPS\Member $member The member that started following the recipient
|
||||
* @param Lang $language The language that the notification should be in
|
||||
* @param Event $event The event the notification refers to
|
||||
* @param int $daysToGo
|
||||
* @return array
|
||||
*/
|
||||
public static function parse_mobile_event_reminder( \IPS\Lang $language, \IPS\calendar\Event $event, $daysToGo )
|
||||
public static function parse_mobile_event_reminder( Lang $language, Event $event, int $daysToGo ): array
|
||||
{
|
||||
return array(
|
||||
'title' => $language->addToStack( 'notification__event_reminder_title', FALSE, array(
|
||||
|
||||
@@ -12,32 +12,37 @@
|
||||
namespace IPS\calendar\extensions\core\Permissions;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Calendar;
|
||||
use IPS\Extensions\PermissionsAbstract;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permissions
|
||||
*/
|
||||
class _Permissions
|
||||
class Permissions extends PermissionsAbstract
|
||||
{
|
||||
/**
|
||||
* Get node classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNodeClasses()
|
||||
public function getNodeClasses(): array
|
||||
{
|
||||
return array(
|
||||
'IPS\calendar\Calendar' => function( $current, $group )
|
||||
{
|
||||
$rows = array();
|
||||
|
||||
foreach( \IPS\calendar\Calendar::roots( NULL ) AS $calendar )
|
||||
foreach( Calendar::roots( NULL ) AS $calendar )
|
||||
{
|
||||
\IPS\calendar\Calendar::populatePermissionMatrix( $rows, $calendar, $group, $current );
|
||||
Calendar::populatePermissionMatrix( $rows, $calendar, $group, $current );
|
||||
}
|
||||
|
||||
return $rows;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief SearchContent extension: Events
|
||||
* @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 Events
|
||||
* @since 10 Jul 2023
|
||||
*/
|
||||
|
||||
namespace IPS\calendar\extensions\core\SearchContent;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
|
||||
use Exception;
|
||||
use IPS\calendar\Date;
|
||||
use IPS\calendar\Event;
|
||||
use IPS\calendar\Event\Comment;
|
||||
use IPS\calendar\Event\Review;
|
||||
use IPS\calendar\Icalendar\ICSParser;
|
||||
use IPS\Content\Search\SearchContentAbstract;
|
||||
use IPS\Theme;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SearchContent extension: Events
|
||||
*/
|
||||
class Events extends SearchContentAbstract
|
||||
{
|
||||
/**
|
||||
* Return all searchable classes in your application,
|
||||
* including comments and/or reviews
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function supportedClasses() : array
|
||||
{
|
||||
return array(
|
||||
Event::class,
|
||||
Comment::class,
|
||||
Review::class
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snippet HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the container. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @return callable
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function searchResultSnippet( array $indexData, array $authorData, array $itemData, array|null $containerData, array $reputationData, int|null $reviewRating, string $view ): string
|
||||
{
|
||||
$startDate = Date::parseTime( $itemData['event_start_date'], !$itemData['event_all_day']);
|
||||
$endDate = $itemData['event_end_date'] ? Date::parseTime( $itemData['event_end_date'], !$itemData['event_all_day']) : NULL;
|
||||
$nextOccurance = $startDate;
|
||||
if ( $itemData['event_recurring'] )
|
||||
{
|
||||
$occurances = Event::_findOccurances( $startDate, $endDate, $startDate->adjust( "-1 month" ), $startDate->adjust( "+2 years" ), ICSParser::parseRrule( $itemData['event_recurring'] ), NULL, $itemData['event_all_day'] );
|
||||
foreach( $occurances as $occurrence )
|
||||
{
|
||||
if ( $occurrence['startDate'] AND $occurrence['startDate']->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) )
|
||||
{
|
||||
$nextOccurance = $occurrence['startDate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( $indexData['index_class'] == Event::class )
|
||||
{
|
||||
return Theme::i()->getTemplate( 'global', 'calendar', 'front' )->searchResultEventSnippet( $indexData, $itemData, $nextOccurance, $startDate, $endDate, $itemData['event_all_day'], $view == 'condensed' );
|
||||
}
|
||||
else
|
||||
{
|
||||
return Theme::i()->getTemplate( 'global', 'calendar', 'front' )->searchResultCommentSnippet( $indexData, $nextOccurance, $startDate, $endDate, $itemData['event_all_day'], $reviewRating, $view == 'condensed' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,31 +11,38 @@
|
||||
namespace IPS\calendar\extensions\core\Statistics;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\core\Statistics\Chart;
|
||||
use IPS\Helpers\Chart\Database;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0') . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statistics Chart Extension
|
||||
*/
|
||||
class _Rsvp extends \IPS\core\Statistics\Chart
|
||||
class Rsvp extends Chart
|
||||
{
|
||||
/**
|
||||
* @brief Controller
|
||||
*/
|
||||
public $controller = 'calendar_stats_rsvp';
|
||||
public ?string $controller = 'calendar_stats_rsvp';
|
||||
|
||||
/**
|
||||
* Render Chart
|
||||
*
|
||||
* @param \IPS\Http\Url $url URL the chart is being shown on.
|
||||
* @param Url $url URL the chart is being shown on.
|
||||
* @return \IPS\Helpers\Chart
|
||||
*/
|
||||
public function getChart( \IPS\Http\Url $url ): \IPS\Helpers\Chart
|
||||
public function getChart( Url $url ): \IPS\Helpers\Chart
|
||||
{
|
||||
$chart = new \IPS\Helpers\Chart\Database( $url, 'calendar_event_rsvp', 'rsvp_date', '', array(
|
||||
$chart = new Database( $url, 'calendar_event_rsvp', 'rsvp_date', '', array(
|
||||
'isStacked' => FALSE,
|
||||
'backgroundColor' => '#ffffff',
|
||||
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
|
||||
@@ -48,10 +55,10 @@ class _Rsvp extends \IPS\core\Statistics\Chart
|
||||
|
||||
foreach( array( 0,1,2 ) as $response )
|
||||
{
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_response_' . $response ), 'number', 'COUNT(*)', FALSE, $response );
|
||||
$chart->addSeries( Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_response_' . $response ), 'number', 'COUNT(*)', FALSE, $response );
|
||||
|
||||
}
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_title');
|
||||
$chart->title = Member::loggedIn()->language()->addToStack('calendar_stats_rsvp_title');
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart' );
|
||||
|
||||
return $chart;
|
||||
|
||||
@@ -12,26 +12,37 @@
|
||||
namespace IPS\calendar\extensions\core\StreamItems;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use IPS\calendar\Event;
|
||||
use IPS\Content\Search\Result\Custom;
|
||||
use IPS\DateTime;
|
||||
use IPS\Db;
|
||||
use IPS\Extensions\StreamItemsAbstract;
|
||||
use IPS\Member;
|
||||
use IPS\Theme;
|
||||
use OutOfRangeException;
|
||||
use function defined;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activity stream items extension: StreamItems
|
||||
*/
|
||||
class _StreamItems
|
||||
class StreamItems extends StreamItemsAbstract
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
* @param Member|null $author The author to limit extra items to
|
||||
* @param int|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 int|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 )
|
||||
public function extraItems( Member $author=NULL, int $lastTime=NULL, int $firstTime=NULL ): array
|
||||
{
|
||||
$rsvps = array();
|
||||
|
||||
@@ -45,19 +56,19 @@ class _StreamItems
|
||||
{
|
||||
$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 )
|
||||
foreach ( Db::i()->select( '*', 'calendar_event_rsvp', $where, 'rsvp_date DESC', 10 ) as $rsvp )
|
||||
{
|
||||
try
|
||||
{
|
||||
$event = \IPS\calendar\Event::load( $rsvp[ 'rsvp_event_id' ] );
|
||||
$event = Event::load( $rsvp[ 'rsvp_event_id' ] );
|
||||
if( $event->canView() )
|
||||
{
|
||||
$member = \IPS\Member::load( $rsvp['rsvp_member_id'] );
|
||||
$member = Member::load( $rsvp['rsvp_member_id'] );
|
||||
$title = htmlspecialchars( $event->title, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
$rsvps[] = new \IPS\Content\Search\Result\Custom( \IPS\DateTime::ts( $rsvp[ 'rsvp_date' ] ), \IPS\Member::loggedIn()->language()->addToStack( 'calendar_activity_stream_rsvp', FALSE, array( 'htmlsprintf' => array( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( $member ), $event->url(), $title ) ) ) );
|
||||
$rsvps[] = new Custom( DateTime::ts( $rsvp[ 'rsvp_date' ] ), Member::loggedIn()->language()->addToStack( 'calendar_activity_stream_rsvp', FALSE, array( 'htmlsprintf' => array( Theme::i()->getTemplate( 'global', 'core', 'front' )->userLink( $member ), $event->url(), $title ) ) ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
catch ( OutOfRangeException $e )
|
||||
{
|
||||
/* Event doesn't exist */
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user