Version 5.0.0 beta 1

This commit is contained in:
Neo committed 2025-12-19 16:27:35 -08:00
1 parent 25ddeb65d6
commit 15c7beabc5
6736 files changed
+627902 -497943

No files matched your search

@@ -10,20 +10,20 @@
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
use IPS\calendar\api\GraphQL\Mutations\CreateEvent;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog mutationss GraphQL API
*/
abstract class _Mutation
abstract class Mutation
{
/**
* Get the supported query types in this app
@@ -32,9 +32,8 @@ abstract class _Mutation
*/
public static function mutations(): array
{
$return = [
'createEvent' => new \IPS\calendar\api\GraphQL\Mutations\CreateEvent(),
return [
'createEvent' => new CreateEvent(),
];
return $return;
}
}
@@ -10,30 +10,38 @@
*/
namespace IPS\calendar\api\GraphQL\Mutations;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\SafeException;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\Types\EventType;
use IPS\calendar\Calendar;
use IPS\calendar\Event;
use IPS\Content\Api\GraphQL\ItemMutator;
use IPS\Content\Item;
use IPS\Member;
use OutOfRangeException;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Create Event mutation for GraphQL API
*/
class _CreateEvent extends \IPS\Content\Api\GraphQL\ItemMutator
class CreateEvent extends ItemMutator
{
/**
* Class
*/
protected $class = \IPS\calendar\Event::class;
protected string $class = Event::class;
/*
* @brief Query description
*/
public static $description = "Create a new calendar event";
public static string $description = "Create a new calendar event";
/*
* Mutation arguments
@@ -48,7 +56,7 @@ class _CreateEvent extends \IPS\Content\Api\GraphQL\ItemMutator
/**
* Return the mutation return type
*/
public function type()
public function type(): EventType
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
}
@@ -56,42 +64,43 @@ class _CreateEvent extends \IPS\Content\Api\GraphQL\ItemMutator
/**
* Resolves this mutation
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @param array $info
* @return Event
*/
public function resolve($val, $args, $context, $info)
public function resolve( mixed $val, array $args, array $context, array $info): Item
{
/* Get calendar */
try
{
$calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $args['calendarID'] );
$calendar = Calendar::loadAndCheckPerms( $args['calendarID'] );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_CALENDAR', '1L296/6_graphql', 400 );
throw new SafeException( 'NO_CALENDAR', '1L296/6_graphql', 400 );
}
/* Check permission */
if ( !$calendar->can( 'add', \IPS\Member::loggedIn() ) )
if ( !$calendar->can( 'add', Member::loggedIn() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_PERMISSION', '1L296/7_graphql', 403 );
throw new SafeException( 'NO_PERMISSION', '1L296/7_graphql', 403 );
}
/* Check we have a title and a post */
if ( !$args['title'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_TITLE', '1L296/8_graphql', 400 );
throw new SafeException( 'NO_TITLE', '1L296/8_graphql', 400 );
}
if ( !$args['content'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_POST', '1L296/9_grapqhl', 400 );
throw new SafeException( 'NO_POST', '1L296/9_grapqhl', 400 );
}
if ( !$args['start'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'INVALID_START', '1L296/A_grapqhl', 400 );
throw new SafeException( 'INVALID_START', '1L296/A_grapqhl', 400 );
}
return $this->_create( $args, $calendar, $args['postKey'] ?? NULL );
@@ -10,25 +10,28 @@
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\Types\CalendarType;
use IPS\calendar\Calendar as CalendarClass;
use OutOfRangeException;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Calendar query for GraphQL API
*/
class _calendar
class Calendar
{
/*
* @brief Query description
*/
public static $description = "Returns a calendar";
public static string $description = "Returns a calendar";
/*
* Query arguments
@@ -43,7 +46,7 @@ class _calendar
/**
* Return the query return type
*/
public function type()
public function type(): CalendarType
{
return \IPS\calendar\api\GraphQL\TypeRegistry::calendar();
}
@@ -51,18 +54,19 @@ class _calendar
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Calendar
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @param array $info
* @return CalendarClass
*/
public function resolve($val, $args, $context, $info)
public function resolve( mixed $val, array$args, array $context, array $info): CalendarClass
{
$calendar = \IPS\calendar\Calendar::load( $args['id'] );
$calendar = CalendarClass::load( $args['id'] );
if( !$calendar->can( 'view', $context['member'] ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
return $calendar;
}
@@ -10,25 +10,27 @@
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ListOfType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\Calendar;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Forums query for GraphQL API
*/
class _Calendars
class Calendars
{
/*
* @brief Query description
*/
public static $description = "Returns a list of calendars";
public static string $description = "Returns a list of calendars";
/*
* Query arguments
@@ -43,7 +45,7 @@ class _Calendars
/**
* Return the query return type
*/
public function type()
public function type(): ListOfType
{
return TypeRegistry::listOf( \IPS\calendar\api\GraphQL\TypeRegistry::calendar() );
}
@@ -51,14 +53,15 @@ class _Calendars
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @param array $info
* @return array
*/
public function resolve($val, $args, $context, $info)
public function resolve( mixed $val, array $args, array $context, array $info): array
{
\IPS\calendar\Calendar::loadIntoMemory('view', $context['member']);
return \IPS\calendar\Calendar::roots();
Calendar::loadIntoMemory('view', $context['member']);
return Calendar::roots();
}
}
@@ -10,25 +10,29 @@
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\SafeException;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\Types\EventType;
use IPS\calendar\Event as EventClass;
use OutOfRangeException;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Event query for GraphQL API
*/
class _Event
class Event
{
/*
* @brief Query description
*/
public static $description = "Returns an event";
public static string $description = "Returns an event";
/*
* Query arguments
@@ -43,7 +47,7 @@ class _Event
/**
* Return the query return type
*/
public function type()
public function type(): EventType
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
}
@@ -51,25 +55,26 @@ class _Event
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @param array $info
* @return EventClass
*/
public function resolve($val, $args, $context, $info)
public function resolve( mixed $val, array $args, array $context, array $info): EventClass
{
try
{
$event = \IPS\calendar\Event::loadAndCheckPerms( $args['id'] );
$event = EventClass::loadAndCheckPerms( $args['id'] );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_EVENT', '1F294/2_graphql', 400 );
throw new SafeException( 'NO_EVENT', '1F294/2_graphql', 400 );
}
if( !$event->can('read') )
{
throw new \IPS\Api\GraphQL\SafeException( 'INVALID_ID', '2F294/9_graphql', 403 );
throw new SafeException( 'INVALID_ID', '2F294/9_graphql', 403 );
}
return $event;
@@ -11,25 +11,34 @@
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ListOfType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\Types\EventType;
use IPS\calendar\Calendar;
use IPS\calendar\Event;
use IPS\Db;
use IPS\Member;
use IPS\Patterns\ActiveRecordIterator;
use function count;
use function defined;
use function in_array;
/* To prevent PHP errors (extending class does not exist) revealing path */
if( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER[ 'SERVER_PROTOCOL' ] ) ? $_SERVER[ 'SERVER_PROTOCOL' ] : 'HTTP/1.0' ).' 403 Forbidden' );
header( ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0').' 403 Forbidden' );
exit;
}
/**
* Calendar Events query for GraphQL API
*/
class _Events
class Events
{
/*
* @brief Query description
*/
public static $description = "Returns a list of events";
public static string $description = "Returns a list of events";
/*
* Query arguments
@@ -50,7 +59,7 @@ class _Events
'type' => TypeRegistry::eNum( [
'name' => 'events_order_by',
'description' => 'Fields on which events can be sorted',
'values' => \IPS\calendar\api\GraphQL\Types\EventType::getOrderByOptions(),
'values' => EventType::getOrderByOptions(),
] ),
'defaultValue' => NULL, // will use default sort option
],
@@ -72,7 +81,7 @@ class _Events
/**
* Return the query return type
*/
public function type()
public function type(): ListOfType
{
return TypeRegistry::listOf( \IPS\calendar\api\GraphQL\TypeRegistry::event() );
}
@@ -80,30 +89,31 @@ class _Events
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @param array $info
* @return ActiveRecordIterator
*/
public function resolve( $val, $args, $context, $info )
public function resolve( mixed $val, array $args, array $context, array $info ): ActiveRecordIterator
{
$where = [];
\IPS\calendar\Calendar::loadIntoMemory( 'view', \IPS\Member::loggedIn() );
Calendar::loadIntoMemory( 'view', Member::loggedIn() );
$calendarIDs = [];
/* Are we filtering by calendards? */
if( isset( $args[ 'calendars' ] ) && \count( $args[ 'calendars' ] ) )
if( isset( $args[ 'calendars' ] ) && count( $args[ 'calendars' ] ) )
{
foreach( $args[ 'calendars' ] as $id )
{
$calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $id );
$calendar = Calendar::loadAndCheckPerms( $id );
$calendarIDs[] = $calendar->id;
}
if( \count( $calendarIDs ) )
if( count( $calendarIDs ) )
{
$where[ 'container' ][] = [ \IPS\Db::i()->in( 'calendar_events.event_calendar_id', array_filter( $calendarIDs ) ) ];
$where[ 'container' ][] = [ Db::i()->in( 'calendar_events.event_calendar_id', array_filter( $calendarIDs ) ) ];
}
}
@@ -113,15 +123,15 @@ class _Events
{
$orderBy = 'saved';
}
else if( \in_array( $args[ 'orderBy' ], \IPS\calendar\api\GraphQL\Types\EventType::getOrderByOptions() ) )
else if( in_array( $args[ 'orderBy' ], EventType::getOrderByOptions() ) )
{
$orderBy = $args[ 'orderBy' ];
}
$sortBy = \IPS\calendar\Event::$databaseTable.'.'.\IPS\calendar\Event::$databasePrefix."{$orderBy} {$args['orderDir']}";
$sortBy = Event::$databaseTable.'.'. Event::$databasePrefix."{$orderBy} {$args['orderDir']}";
$offset = max( $args[ 'offset' ], 0 );
$limit = min( $args[ 'limit' ], 50 );
return \IPS\calendar\Event::getItemsWithPermission( $where, $sortBy, [ $offset, $limit ], 'read' );
return Event::getItemsWithPermission( $where, $sortBy, [ $offset, $limit ] );
}
}
+13 -10
View File
@@ -10,33 +10,36 @@
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
use IPS\calendar\api\GraphQL\Queries\Calendar;
use IPS\calendar\api\GraphQL\Queries\Calendars;
use IPS\calendar\api\GraphQL\Queries\Event;
use IPS\calendar\api\GraphQL\Queries\Events;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog queries for GraphQL API
*/
abstract class _Query
abstract class Query
{
/**
* Get the supported query types in this app
*
* @return array
*/
public static function queries()
public static function queries(): array
{
return [
'calendar' => new \IPS\calendar\api\GraphQL\Queries\Calendar(),
'calendars' => new \IPS\calendar\api\GraphQL\Queries\Calendars(),
'events' => new \IPS\calendar\api\GraphQL\Queries\Events(),
'event' => new \IPS\calendar\api\GraphQL\Queries\Event(),
'calendar' => new Calendar(),
'calendars' => new Calendars(),
'events' => new Events(),
'event' => new Event(),
];
}
}
@@ -10,36 +10,38 @@
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
use IPS\calendar\api\GraphQL\Types\CalendarType;
use IPS\calendar\api\GraphQL\Types\CommentType;
use IPS\calendar\api\GraphQL\Types\EventType;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
class _TypeRegistry
class TypeRegistry
{
/**
* The calendar type instance
* @var \IPS\calendar\api\GraphQL\Types\CalendarType
* @var CalendarType
*/
protected static $calendar;
protected static CalendarType $calendar;
/**
* The event type instance
* @var \IPS\calendar\api\GraphQL\Types\EventType
* @var EventType
*/
protected static $event;
protected static EventType $event;
/**
* The event comment instance
* @var \IPS\calendar\api\GraphQL\Types\CalendarType
* @var CommentType
*/
protected static $comment;
protected static CommentType $comment;
/**
* Constructor
@@ -52,21 +54,21 @@ class _TypeRegistry
/**
* @return CalendarType
*/
public static function calendar() : \IPS\calendar\api\GraphQL\Types\CalendarType
public static function calendar() : CalendarType
{
return self::$calendar ?: (self::$calendar = new \IPS\calendar\api\GraphQL\Types\CalendarType());
return self::$calendar ?? (self::$calendar = new CalendarType());
}
/**
* @return EventType
*/
public static function event() : \IPS\calendar\api\GraphQL\Types\EventType
public static function event() : EventType
{
return self::$event ?: (self::$event = new \IPS\calendar\api\GraphQL\Types\EventType());
return self::$event ?? (self::$event = new EventType());
}
public static function comment() : \IPS\calendar\api\GraphQL\Types\CommentType
public static function comment() : CommentType
{
return self::$comment ?: ( self::$comment = new \IPS\calendar\api\GraphQL\Types\CommentType() );
return self::$comment ?? ( self::$comment = new CommentType() );
}
}
@@ -11,39 +11,42 @@
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\TypeRegistry;
use IPS\calendar\Calendar;
use IPS\Node\Api\GraphQL\NodeType;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* CalendarType for GraphQL API
*/
class _CalendarType extends \IPS\Node\Api\GraphQL\NodeType
class CalendarType extends NodeType
{
/*
* @brief The item classname we use for this type
*/
protected static $nodeClass = \IPS\calendar\Calendar::class;
protected static string $nodeClass = Calendar::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Calendar';
protected static string $typeName = 'calendar_Calendar';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar';
protected static string $typeDescription = 'A calendar';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array('app' => 'calendar', 'area' => 'calendar');
protected static array $followData = array('app' => 'calendar', 'area' => 'calendar');
/**
@@ -51,9 +54,9 @@ class _CalendarType extends \IPS\Node\Api\GraphQL\NodeType
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
public static function getItemType(): ObjectType
{
return TypeRegistry::event();
}
}
@@ -11,43 +11,46 @@
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\api\GraphQL\TypeRegistry;
use IPS\calendar\Event\Comment;
use IPS\Content\Api\GraphQL\CommentType as ApiCommentType;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* PostType for GraphQL API
*/
class _CommentType extends \IPS\Content\Api\GraphQL\CommentType
class CommentType extends ApiCommentType
{
/*
* @brief The item classname we use for this type
*/
protected static $commentClass = \IPS\calendar\Event\Comment::class;
protected static string $commentClass = Comment::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Comment';
protected static string $typeName = 'calendar_Comment';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar event comment';
protected static string $typeDescription = 'A calendar event comment';
/**
* Get the item type that goes with this item type
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::comment();
public static function getItemType(): ObjectType
{
return TypeRegistry::comment();
}
/**
@@ -55,12 +58,12 @@ class _CommentType extends \IPS\Content\Api\GraphQL\CommentType
*
* @return array
*/
public function fields()
{
public function fields(): array
{
$defaultFields = parent::fields();
$postFields = array(
'event' => [
'type' => \IPS\calendar\api\GraphQL\TypeRegistry::event(),
'type' => TypeRegistry::event(),
'resolve' => function ($comment) {
return $comment->item();
}
@@ -12,47 +12,49 @@
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\_TypeRegistry;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\calendar\Event;
use IPS\Content\Api\GraphQL\ItemType;
use function defined;
/* To prevent PHP errors (extending class does not exist) revealing path */
if( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER[ 'SERVER_PROTOCOL' ] ) ? $_SERVER[ 'SERVER_PROTOCOL' ] : 'HTTP/1.0' ).' 403 Forbidden' );
header( ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0').' 403 Forbidden' );
exit;
}
/**
* Entry for GraphQL API
*/
class _EventType extends \IPS\Content\Api\GraphQL\ItemType
class EventType extends ItemType
{
/*
* @brief The item classname we use for this type
*/
protected static $itemClass = \IPS\calendar\Event::class;
protected static string $itemClass = Event::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Event';
protected static string $typeName = 'calendar_Event';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar event';
protected static string $typeDescription = 'A calendar event';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array( 'app' => 'calendar', 'area' => 'event' );
protected static array $followData = array( 'app' => 'calendar', 'area' => 'event' );
/**
* Get the comment type that goes with this item type
*
* @return ObjectType
*/
protected static function getCommentType()
protected static function getCommentType(): ObjectType
{
return \IPS\calendar\api\GraphQL\TypeRegistry::comment();
}
@@ -62,7 +64,7 @@ class _EventType extends \IPS\Content\Api\GraphQL\ItemType
*
* @return array
*/
public function fields()
public function fields(): array
{
// Extend our fields with image-specific stuff
$defaultFields = parent::fields();
+52 -33
View File
@@ -12,21 +12,34 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use IPS\Api\Exception;
use IPS\Api\PaginatedResponse;
use IPS\Api\Response;
use IPS\calendar\Calendar;
use IPS\Http\Url\Friendly;
use IPS\Lang;
use IPS\Node\Api\NodeController;
use IPS\Node\Model;
use IPS\Request;
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 Calendars API
*/
class _calendars extends \IPS\Node\Api\NodeController
class calendars extends NodeController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Calendar';
protected string $class = 'IPS\calendar\Calendar';
/**
* GET /calendar/calendars
@@ -36,9 +49,10 @@ class _calendars extends \IPS\Node\Api\NodeController
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @note For requests using an OAuth Access Token for a particular member, only calendars the authorized user can view will be included
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Calendar>
* @apireturn PaginatedResponse<IPS\calendar\Calendar>
* @return PaginatedResponse<Calendar>
*/
public function GETindex()
public function GETindex(): PaginatedResponse
{
/* Return */
return $this->_list();
@@ -50,17 +64,18 @@ class _calendars extends \IPS\Node\Api\NodeController
*
* @param int $id ID Number
* @throws 1L364/1 INVALID_ID The calendar does not exist or the authorized user does not have permission to view it
* @return \IPS\calendar\Calendar
* @apireturn \IPS\calendar\Calendar
* @return Response
*/
public function GETitem( $id )
public function GETitem( int $id ): Response
{
try
{
return $this->_view( $id );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '1L364/1', 404 );
throw new Exception( 'INVALID_ID', '1L364/1', 404 );
}
}
@@ -77,17 +92,18 @@ class _calendars extends \IPS\Node\Api\NodeController
* @apiparam int allow_reviews 0|1 Allow reviews
* @apiparam int approve_reviews 0|1 Reviews must be approved
* @apiparam object permissions An object with the keys as permission options (view, read, add, reply, review, askrsvp, rsvp) and values as permissions to use (which may be * to grant access to all groups, or an array of group IDs to permit access to)
* @return \IPS\calendar\Calendar
* @apireturn \IPS\calendar\Calendar
* @throws 1L364/2 NO_TITLE A title for the calendar must be supplied
* @return Response
*/
public function POSTindex()
public function POSTindex(): Response
{
if ( !\IPS\Request::i()->title )
if ( !Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1L364/2', 400 );
throw new Exception( 'NO_TITLE', '1L364/2', 400 );
}
return new \IPS\Api\Response( 201, $this->_create()->apiOutput( $this->member ) );
return new Response( 201, $this->_create()->apiOutput( $this->member ) );
}
/**
@@ -104,14 +120,16 @@ class _calendars extends \IPS\Node\Api\NodeController
* @apiparam int approve_reviews 0|1 Reviews must be approved
* @apiparam object permissions An object with the keys as permission options (view, read, add, reply, review, askrsvp, rsvp) and values as permissions to use (which may be * to grant access to all groups, or an array of group IDs to permit access to)
* @param int $id ID Number
* @return \IPS\calendar\Calendar
* @apireturn \IPS\calendar\Calendar
* @return Response
*/
public function POSTitem( $id )
public function POSTitem( int $id ): Response
{
/* @var Calendar $class */
$class = $this->class;
$calendar = $class::load( $id );
return new \IPS\Api\Response( 200, $this->_createOrUpdate( $calendar )->apiOutput( $this->member ) );
return new Response( 200, $this->_createOrUpdate( $calendar )->apiOutput( $this->member ) );
}
/**
@@ -120,9 +138,10 @@ class _calendars extends \IPS\Node\Api\NodeController
*
* @apiclientonly
* @param int $id ID Number
* @return void
* @apireturn void
* @return Response
*/
public function DELETEitem( $id )
public function DELETEitem( int $id ): Response
{
return $this->_delete( $id );
}
@@ -130,27 +149,27 @@ class _calendars extends \IPS\Node\Api\NodeController
/**
* Create or update node
*
* @param \IPS\node\Model $calendar The node
* @return \IPS\node\Model
* @param Model $calendar The node
* @return Model
*/
protected function _createOrUpdate( \IPS\Node\Model $calendar )
protected function _createOrUpdate( Model $calendar ): Model
{
if ( \IPS\Request::i()->title )
if ( 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 );
Lang::saveCustom( 'calendar', 'calendar_calendar_' . $calendar->id, Request::i()->title );
$calendar->title_seo = Friendly::seoTitle( Request::i()->title );
}
if ( isset( \IPS\Request::i()->color ) )
if ( isset( Request::i()->color ) )
{
$calendar->color = \IPS\Request::i()->color;
$calendar->color = 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;
$calendar->moderate = (int) isset( Request::i()->approve_events ) ? Request::i()->approve_events : 0;
$calendar->allow_comments = (int) isset( Request::i()->allow_comments ) ? Request::i()->allow_comments : 0;
$calendar->comment_moderate = (int) isset( Request::i()->approve_comments ) ? Request::i()->approve_comments : 0;
$calendar->allow_reviews = (int) isset( Request::i()->allow_reviews ) ? Request::i()->allow_reviews : 0;
$calendar->review_moderate = (int) isset( Request::i()->approve_reviews ) ? Request::i()->approve_reviews : 0;
return parent::_createOrUpdate( $calendar );
}
+71 -48
View File
@@ -12,21 +12,34 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use InvalidArgumentException;
use IPS\Api\Exception;
use IPS\Api\PaginatedResponse;
use IPS\Api\Response;
use IPS\calendar\Event;
use IPS\calendar\Event\Comment;
use IPS\Content\Api\CommentController;
use IPS\Member;
use IPS\Request;
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 Calendar Events Comments API
*/
class _comments extends \IPS\Content\Api\CommentController
class comments extends CommentController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Event\Comment';
protected string $class = 'IPS\calendar\Event\Comment';
/**
* GET /calendar/comments
@@ -42,9 +55,10 @@ class _comments extends \IPS\Content\Api\CommentController
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event\Comment>
* @apireturn PaginatedResponse<IPS\calendar\Event\Comment>
* @return PaginatedResponse<Comment>
*/
public function GETindex()
public function GETindex(): PaginatedResponse
{
return $this->_list( array(), 'calendars' );
}
@@ -55,12 +69,14 @@ class _comments extends \IPS\Content\Api\CommentController
*
* @param int $id ID Number
* @throws 2L297/1 INVALID_ID The comment ID does not exist or the authorized user does not have permission to view it
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @return Response
*/
public function GETitem( $id )
public function GETitem( int $id ): Response
{
try
{
/* @var Comment $class */
$class = $this->class;
if ( $this->member )
{
@@ -71,11 +87,11 @@ class _comments extends \IPS\Content\Api\CommentController
$object = $class::load( $id );
}
return new \IPS\Api\Response( 200, $object->apiOutput( $this->member ) );
return new Response( 200, $object->apiOutput( $this->member ) );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L297/1', 404 );
throw new Exception( 'INVALID_ID', '2L297/1', 404 );
}
}
@@ -96,18 +112,19 @@ class _comments extends \IPS\Content\Api\CommentController
* @throws 1L297/4 NO_AUTHOR The author ID does not exist
* @throws 1L297/5 NO_CONTENT No content was supplied
* @throws 2L297/8 NO_PERMISSION The authorized user does not have permission to comment on that event
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @return Response
*/
public function POSTindex()
public function POSTindex(): Response
{
/* Get event */
try
{
$event = \IPS\calendar\Event::load( \IPS\Request::i()->event );
$event = Event::load( Request::i()->event );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L297/3', 403 );
throw new Exception( 'INVALID_ID', '2L297/3', 403 );
}
/* Get author */
@@ -115,38 +132,38 @@ class _comments extends \IPS\Content\Api\CommentController
{
if ( !$event->canComment( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L297/8', 403 );
throw new Exception( 'NO_PERMISSION', '2L297/8', 403 );
}
$author = $this->member;
}
else
{
if ( \IPS\Request::i()->author )
if ( Request::i()->author )
{
$author = \IPS\Member::load( \IPS\Request::i()->author );
$author = Member::load( Request::i()->author );
if ( !$author->member_id )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L297/4', 404 );
throw new Exception( 'NO_AUTHOR', '1L297/4', 404 );
}
}
else
{
if ( (int) \IPS\Request::i()->author === 0 )
if ( Request::i()->author === 0 )
{
$author = new \IPS\Member;
$author->name = \IPS\Request::i()->author_name;
$author = new Member;
$author->name = Request::i()->author_name;
}
else
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L297/4', 400 );
throw new Exception( 'NO_AUTHOR', '1L297/4', 400 );
}
}
}
/* Check we have a post */
if ( !\IPS\Request::i()->content )
if ( !Request::i()->content )
{
throw new \IPS\Api\Exception( 'NO_CONTENT', '1L297/5', 403 );
throw new Exception( 'NO_CONTENT', '1L297/5', 403 );
}
/* Do it */
@@ -167,21 +184,22 @@ class _comments extends \IPS\Content\Api\CommentController
* @throws 2L297/6 INVALID_ID The comment ID does not exist or the authorized user does not have permission to view it
* @throws 1L297/7 NO_AUTHOR The author ID does not exist
* @throws 2L297/9 NO_PERMISSION The authorized user does not have permission to edit the comment
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @return Response
*/
public function POSTitem( $id )
public function POSTitem( int $id ): Response
{
try
{
/* Load */
$comment = \IPS\calendar\Event\Comment::load( $id );
$comment = Comment::load( $id );
if ( $this->member and !$comment->canView( $this->member ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
if ( $this->member and !$comment->canEdit( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L297/9', 403 );
throw new Exception( 'NO_PERMISSION', '2L297/9', 403 );
}
/* Do it */
@@ -189,14 +207,14 @@ class _comments extends \IPS\Content\Api\CommentController
{
return $this->_edit( $comment );
}
catch ( \InvalidArgumentException $e )
catch ( InvalidArgumentException $e )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L297/7', 400 );
throw new Exception( 'NO_AUTHOR', '1L297/7', 400 );
}
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L297/6', 404 );
throw new Exception( 'INVALID_ID', '2L297/6', 404 );
}
}
@@ -207,25 +225,27 @@ class _comments extends \IPS\Content\Api\CommentController
* @param int $id ID Number
* @throws 2L297/2 INVALID_ID The comment ID does not exist
* @throws 2L297/A NO_PERMISSION The authorized user does not have permission to delete the comment
* @return void
* @apireturn void
* @return Response
*/
public function DELETEitem( $id )
public function DELETEitem( int $id ): Response
{
try
{
{
/* @var Comment $class */
$class = $this->class;
$object = $class::load( $id );
if ( $this->member and !$object->canDelete( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L297/A', 403 );
throw new Exception( 'NO_PERMISSION', '2L297/A', 403 );
}
$object->delete();
return new \IPS\Api\Response( 200, NULL );
return new Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L297/2', 404 );
throw new Exception( 'INVALID_ID', '2L297/2', 404 );
}
}
@@ -236,14 +256,15 @@ class _comments extends \IPS\Content\Api\CommentController
* @param int $id ID Number
* @apiparam int id ID of the reaction to add
* @apiparam int author ID of the member reacting
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @throws 1S425/2 NO_REACTION The reaction ID does not exist
* @throws 1S425/3 NO_AUTHOR The author ID does not exist
* @throws 1S425/4 REACT_ERROR Error adding the reaction
* @throws 1S425/5 INVALID_ID Object ID does not exist
* @note If the author has already reacted to this content, any existing reaction will be removed first
* @return Response
*/
public function POSTitem_react( $id )
public function POSTitem_react( int $id ): Response
{
return $this->_reactAdd( $id );
}
@@ -254,13 +275,14 @@ class _comments extends \IPS\Content\Api\CommentController
*
* @param int $id ID Number
* @apiparam int author ID of the member who reacted
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @throws 1S425/6 NO_AUTHOR The author ID does not exist
* @throws 1S425/7 REACT_ERROR Error adding the reaction
* @throws 1S425/8 INVALID_ID Object ID does not exist
* @note If the author has already reacted to this content, any existing reaction will be removed first
* @return Response
*/
public function DELETEitem_react( $id )
public function DELETEitem_react( int $id ): Response
{
return $this->_reactRemove( $id );
}
@@ -275,9 +297,10 @@ class _comments extends \IPS\Content\Api\CommentController
* @apiparam string message Optional message
* @throws 1S425/B NO_AUTHOR The author ID does not exist
* @throws 1S425/C REPORTED_ALREADY The member has reported this item in the past 24 hours
* @return \IPS\calendar\Event\Comment
* @apireturn \IPS\calendar\Event\Comment
* @return Response
*/
public function POSTitem_report( $id )
public function POSTitem_report( int $id ): Response
{
return $this->_report( $id );
}
+172 -127
View File
@@ -12,21 +12,46 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use IPS\Api\Exception;
use IPS\Api\PaginatedResponse;
use IPS\Api\Response;
use IPS\Api\Webhook;
use IPS\calendar\Calendar;
use IPS\calendar\Date;
use IPS\calendar\Event;
use IPS\calendar\Event\Comment;
use IPS\calendar\Event\Review;
use IPS\Content\Api\ItemController;
use IPS\Content\Item;
use IPS\DateTime;
use IPS\Db;
use IPS\GeoLocation;
use IPS\IPS;
use IPS\Member;
use IPS\Request;
use IPS\Text\Parser;
use OutOfRangeException;
use function count;
use function defined;
use function in_array;
use function intval;
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 Calendar Events API
*/
class _events extends \IPS\Content\Api\ItemController
class events extends ItemController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Event';
protected string $class = 'IPS\calendar\Event';
/**
* GET /calendar/events
@@ -45,50 +70,51 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event>
* @apireturn PaginatedResponse<IPS\calendar\Event>
* @throws 1L296/M INVALID_DATE The rangeStart and/or rangeEnd value was not a valid date in YYYY-MM-DD format
* @return PaginatedResponse<Event>
*/
public function GETindex()
public function GETindex(): PaginatedResponse
{
/* Where clause */
$where = array();
/* Are we limiting to a date range? */
if( isset( \IPS\Request::i()->rangeStart ) OR isset( \IPS\Request::i()->rangeEnd ) )
if( isset( Request::i()->rangeStart ) OR isset( Request::i()->rangeEnd ) )
{
$startDate = $endDate = NULL;
foreach( array( 'start', 'end' ) as $limiter )
{
$inputKey = 'range' . mb_ucfirst( $limiter );
$inputKey = 'range' . IPS::mb_ucfirst( $limiter );
if( \IPS\Request::i()->$inputKey )
if( Request::i()->$inputKey )
{
$datePieces = explode( '-', \IPS\Request::i()->$inputKey );
$datePieces = explode( '-', Request::i()->$inputKey );
/* Let's make sure the date is valid... */
if( @checkdate( $datePieces[1], $datePieces[2], $datePieces[0] ) )
{
if( $limiter === 'start' )
{
$startDate = \IPS\calendar\Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2] );
$startDate = Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2] );
}
else
{
$endDate = \IPS\calendar\Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2], 23, 59, 59 );
$endDate = Date::getDate( $datePieces[0], $datePieces[1], $datePieces[2], 23, 59, 59 );
}
}
else
{
throw new \IPS\Api\Exception( 'INVALID_DATE', '1L296/M', 403 );
throw new Exception( 'INVALID_DATE', '1L296/M', 403 );
}
}
}
/* Get the events within this range */
$events = \IPS\calendar\Event::retrieveEvents( $startDate, $endDate, NULL, NULL, FALSE, new \IPS\Member, NULL, TRUE );
$events = Event::retrieveEvents( $startDate, $endDate, NULL, NULL, FALSE, new Member, NULL, TRUE );
if( !\count( $events ) )
if( !count( $events ) )
{
/* Force no results */
$where[] = array( '0=1' );
@@ -102,9 +128,9 @@ class _events extends \IPS\Content\Api\ItemController
/* Sort by */
$sortBy = NULL;
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'start', 'end' ) ) )
if ( isset( Request::i()->sortBy ) and in_array( Request::i()->sortBy, array( 'start', 'end' ) ) )
{
$sortBy = 'event_' . \IPS\Request::i()->sortBy . '_date';
$sortBy = 'event_' . Request::i()->sortBy . '_date';
}
/* Return */
@@ -117,17 +143,18 @@ class _events extends \IPS\Content\Api\ItemController
*
* @param int $id ID Number
* @throws 1F294/1 INVALID_ID The event ID does not exist or the authorized user does not have permission to view it
* @return \IPS\calendar\Event
* @apireturn \IPS\calendar\Event
* @return Response
*/
public function GETitem( $id )
public function GETitem( int $id ): Response
{
try
{
return $this->_view( $id );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L296/1', 404 );
throw new Exception( 'INVALID_ID', '2L296/1', 404 );
}
}
@@ -161,18 +188,19 @@ class _events extends \IPS\Content\Api\ItemController
* @throws 1L296/A INVALID_START The start date is invalid
* @throws 1L296/B INVALID_END The end date is invalid
* @throws 2L296/C NO_PERMISSION The authorized user does not have permission to create an event in that calendar
* @return \IPS\calendar\Event
* @apireturn \IPS\calendar\Event
* @return Response
*/
public function POSTindex()
public function POSTindex(): Response
{
/* Get calendar */
try
{
$calendar = \IPS\calendar\Calendar::load( \IPS\Request::i()->calendar );
$calendar = Calendar::load( Request::i()->calendar );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'NO_CALENDAR', '1L296/6', 400 );
throw new Exception( 'NO_CALENDAR', '1L296/6', 400 );
}
/* Get author */
@@ -180,66 +208,66 @@ class _events extends \IPS\Content\Api\ItemController
{
if ( !$calendar->can( 'add', $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L296/C', 403 );
throw new Exception( 'NO_PERMISSION', '2L296/C', 403 );
}
$author = $this->member;
}
else
{
if ( \IPS\Request::i()->author )
if ( Request::i()->author )
{
$author = \IPS\Member::load( \IPS\Request::i()->author );
$author = Member::load( Request::i()->author );
if ( !$author->member_id )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L296/7', 400 );
throw new Exception( 'NO_AUTHOR', '1L296/7', 400 );
}
}
else
{
if ( (int) \IPS\Request::i()->author === 0 )
if ( Request::i()->author === 0 )
{
$author = new \IPS\Member;
$author = new Member;
}
else
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L296/7', 400 );
throw new Exception( 'NO_AUTHOR', '1L296/7', 400 );
}
}
}
/* Check we have a title and a description */
if ( !\IPS\Request::i()->title )
if ( !Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1L296/8', 400 );
throw new Exception( 'NO_TITLE', '1L296/8', 400 );
}
if ( !\IPS\Request::i()->description )
if ( !Request::i()->description )
{
throw new \IPS\Api\Exception( 'NO_DESC', '1L296/9', 400 );
throw new Exception( 'NO_DESC', '1L296/9', 400 );
}
/* Validate dates */
try
{
new \IPS\DateTime( \IPS\Request::i()->start );
new DateTime( Request::i()->start );
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'INVALID_START', '1L296/A', 400 );
throw new Exception( 'INVALID_START', '1L296/A', 400 );
}
if ( isset( \IPS\Request::i()->end ) )
if ( isset( Request::i()->end ) )
{
try
{
new \IPS\DateTime( \IPS\Request::i()->end );
new DateTime( Request::i()->end );
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'INVALID_END', '1L296/B', 400 );
throw new Exception( 'INVALID_END', '1L296/B', 400 );
}
}
/* Do it */
return new \IPS\Api\Response( 201, $this->_create( $calendar, $author )->apiOutput( $this->member ) );
return new Response( 201, $this->_create( $calendar, $author )->apiOutput( $this->member ) );
}
/**
@@ -264,87 +292,89 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam int hidden 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
* @apiparam int featured 1/0 indicating if the event should be featured
* @apiparam bool anonymous If 1, the item will be posted anonymously.
* @param int $id
* @throws 1L296/I INVALID_ID The event ID is invalid or the authorized user does not have permission to view it
* @throws 1L296/D NO_CALENDAR The calendar ID does not exist or the authorized user does not have permission to post in it
* @throws 1L296/E NO_AUTHOR The author ID does not exist
* @throws 1L296/G INVALID_START The start date is invalid
* @throws 1L296/H INVALID_END The end date is invalid
* @throws 2L296/D NO_PERMISSION The authorized user does not have permission to edit the topic
* @return \IPS\calendar\Event
* @apireturn \IPS\calendar\Event
* @return Response
*/
public function POSTitem( $id )
public function POSTitem( int $id ): Response
{
try
{
$event = \IPS\calendar\Event::load( $id );
$event = Event::load( $id );
if ( $this->member and !$event->can( 'read', $this->member ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
if ( $this->member and !$event->canEdit( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L296/D', 403 );
throw new Exception( 'NO_PERMISSION', '2L296/D', 403 );
}
/* New calendar */
if ( isset( \IPS\Request::i()->calendar ) and \IPS\Request::i()->calendar != $event->calendar_id and ( !$this->member or $event->canMove( $this->member ) ) )
if ( isset( Request::i()->calendar ) and Request::i()->calendar != $event->calendar_id and ( !$this->member or $event->canMove( $this->member ) ) )
{
try
{
$newCalendar = \IPS\calendar\Calendar::load( \IPS\Request::i()->calendar );
$newCalendar = Calendar::load( Request::i()->calendar );
if ( $this->member and !$newCalendar->can( 'add', $this->member ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
$event->move( $newCalendar );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'NO_CALENDAR', '1L296/D', 400 );
throw new Exception( 'NO_CALENDAR', '1L296/D', 400 );
}
}
/* New author */
if ( !$this->member and isset( \IPS\Request::i()->author ) )
if ( !$this->member and isset( Request::i()->author ) )
{
try
{
$member = \IPS\Member::load( \IPS\Request::i()->author );
$member = Member::load( Request::i()->author );
if ( !$member->member_id )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
$event->changeAuthor( $member );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L296/E', 400 );
throw new Exception( 'NO_AUTHOR', '1L296/E', 400 );
}
}
/* Validate dates */
if ( isset( \IPS\Request::i()->start ) )
if ( isset( Request::i()->start ) )
{
try
{
new \IPS\DateTime( \IPS\Request::i()->start );
new DateTime( Request::i()->start );
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'INVALID_START', '1L296/G', 400 );
throw new Exception( 'INVALID_START', '1L296/G', 400 );
}
}
if ( isset( \IPS\Request::i()->end ) )
if ( isset( Request::i()->end ) )
{
try
{
new \IPS\DateTime( \IPS\Request::i()->end );
new DateTime( Request::i()->end );
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'INVALID_END', '1L296/H', 400 );
throw new Exception( 'INVALID_END', '1L296/H', 400 );
}
}
@@ -353,11 +383,11 @@ class _events extends \IPS\Content\Api\ItemController
/* Save and return */
$event->save();
return new \IPS\Api\Response( 200, $event->apiOutput( $this->member ) );
return new Response( 200, $event->apiOutput( $this->member ) );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '1L296/D', 404 );
throw new Exception( 'INVALID_ID', '1L296/D', 404 );
}
}
@@ -371,17 +401,18 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @throws 2L296/2 INVALID_ID The event ID does not exist or the authorized user does not have permission to view it
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event\Comment>
* @apireturn PaginatedResponse<IPS\calendar\Event\Comment>
* @return PaginatedResponse<Comment>
*/
public function GETitem_comments( $id )
public function GETitem_comments( int $id ): PaginatedResponse
{
try
{
return $this->_comments( $id, 'IPS\calendar\Event\Comment' );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L296/2', 404 );
throw new Exception( 'INVALID_ID', '2L296/2', 404 );
}
}
@@ -395,17 +426,18 @@ class _events extends \IPS\Content\Api\ItemController
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @throws 2L296/3 INVALID_ID The event ID does not exist or the authorized user does not have permission to view it
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event\Review>
* @apireturn PaginatedResponse<IPS\calendar\Event\Review>
* @return PaginatedResponse<Review>
*/
public function GETitem_reviews( $id )
public function GETitem_reviews( int $id ): PaginatedResponse
{
try
{
return $this->_comments( $id, 'IPS\calendar\Event\Review' );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L296/3', 404 );
throw new Exception( 'INVALID_ID', '2L296/3', 404 );
}
}
@@ -415,23 +447,24 @@ class _events extends \IPS\Content\Api\ItemController
*
* @param int $id ID Number
* @throws 2L296/3 INVALID_ID The event ID does not exist or the authorized user does not have permission to view it
* @return array
* @apireturn array
* @apiresponse [\IPS\Member] attending Members that have confirmed they are attending the event
* @apiresponse [\IPS\Member] notAttending Members that have confirmed they are not attending the event
* @apiresponse [\IPS\Member] maybeAttending Members that have said they may attend the event
* @return Response
*/
public function GETitem_rsvps( $id )
public function GETitem_rsvps( int $id ): Response
{
try
{
$event = \IPS\calendar\Event::load( $id );
$event = Event::load( $id );
if ( $this->member and !$event->can( 'read', $this->member ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
$attendees = $event->attendees();
return new \IPS\Api\Response( 200, array(
return new Response( 200, array(
'attending' => array_values( array_map( function( $member ) {
return $member->apiOutput( $this->member );
}, $attendees[1] ) ),
@@ -443,9 +476,9 @@ class _events extends \IPS\Content\Api\ItemController
}, $attendees[2] ) ),
) );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L296/4', 404 );
throw new Exception( 'INVALID_ID', '2L296/4', 404 );
}
}
@@ -459,53 +492,63 @@ class _events extends \IPS\Content\Api\ItemController
* @param int $memberId Member ID NUmber
* @throws 2L296/J INVALID_ID The event ID does not exist
* @throws 2L296/K INVALID_MEMBER The member ID was not valid
* @return void
* @apireturn void
* @return Response
*/
public function PUTitem_rsvps( $id, $memberId )
public function PUTitem_rsvps( int $id, int $memberId ): Response
{
if ( !isset( \IPS\Request::i()->response ) or !\in_array( (int) \IPS\Request::i()->response, range( 0, 2 ) ) )
if ( !isset( Request::i()->response ) or !in_array( (int) Request::i()->response, range( 0, 2 ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RESPONSE', '1L296/L', 400 );
throw new Exception( 'INVALID_RESPONSE', '1L296/L', 400 );
}
if ( $this->member and $memberId != $this->member->member_id )
{
throw new \IPS\Api\Exception( 'INVALID_MEMBER', '2L296/K', 404 );
throw new Exception( 'INVALID_MEMBER', '2L296/K', 404 );
}
try
{
$event = \IPS\calendar\Event::load( $id );
$event = Event::load( $id );
try
{
$member = \IPS\Member::load( $memberId );
$member = Member::load( $memberId );
if ( !$member->member_id )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_MEMBER', '2L296/K', 404 );
throw new Exception( 'INVALID_MEMBER', '2L296/K', 404 );
}
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', $event->id, $member->member_id ) );
Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', $event->id, $member->member_id ) );
\IPS\Db::i()->insert( 'calendar_event_rsvp', array(
Db::i()->insert( 'calendar_event_rsvp', array(
'rsvp_event_id' => $event->id,
'rsvp_member_id' => $member->member_id,
'rsvp_date' => time(),
'rsvp_response' => (int) \IPS\Request::i()->response
'rsvp_response' => (int) Request::i()->response
) );
$webhookData = [
'event' => $event->apiOutput(),
'action' => (int) Request::i()->response,
'attendee' => $member->apiOutput(),
];
Webhook::fire( 'calendarEvent_rsvp', $webhookData );
$member->achievementAction( 'calendar', 'Rsvp', $event );
return new \IPS\Api\Response( 200, NULL );
return new Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_EVENT', '2L296/J', 404 );
throw new Exception( 'INVALID_EVENT', '2L296/J', 404 );
}
}
@@ -516,36 +559,37 @@ class _events extends \IPS\Content\Api\ItemController
* @note For requests using an OAuth Access Token for a particular member, the member ID must be the authorized member's ID
* @param int $id Event ID NUmber
* @param int $memberId Member ID NUmber
* @return void
* @apireturn void
* @throws 2L296/K INVALID_MEMBER The member ID was not valid
* @return Response
*/
public function DELETEitem_rsvps( $id, $memberId )
public function DELETEitem_rsvps( int $id, int $memberId ): Response
{
if ( $this->member and $memberId != $this->member->member_id )
{
throw new \IPS\Api\Exception( 'INVALID_MEMBER', '2L296/K', 404 );
throw new Exception( 'INVALID_MEMBER', '2L296/K', 404 );
}
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', \intval( $id ), \intval( $memberId ) ) );
return new \IPS\Api\Response( 200, NULL );
Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', $id, $memberId ) );
return new Response( 200, NULL );
}
/**
* Create or update event
*
* @param \IPS\Content\Item $item The item
* @param Item $item The item
* @param string $type add or edit
* @return \IPS\Content\Item
* @return Item
*/
protected function _createOrUpdate( \IPS\Content\Item $item, $type='add' )
protected function _createOrUpdate( Item $item, string $type='add' ): Item
{
/* Start/End date */
$startDate = new \IPS\DateTime( \IPS\Request::i()->start );
$startDate = new DateTime( Request::i()->start );
$item->start_date = $startDate->format( 'Y-m-d H:i' );
$item->end_date = NULL;
if ( isset( \IPS\Request::i()->end ) )
if ( isset( Request::i()->end ) )
{
$endDate = new \IPS\DateTime( \IPS\Request::i()->end );
$endDate = new DateTime( Request::i()->end );
$item->end_date = $endDate->format( 'Y-m-d H:i' );
}
else
@@ -554,26 +598,26 @@ class _events extends \IPS\Content\Api\ItemController
}
/* Recurrence */
if ( isset( \IPS\Request::i()->recurrence ) )
if ( isset( Request::i()->recurrence ) )
{
$item->recurring = \IPS\Request::i()->recurrence;
$item->recurring = Request::i()->recurrence;
}
/* Description */
$descriptionContents = \IPS\Request::i()->description;
$descriptionContents = Request::i()->description;
if ( $this->member )
{
$descriptionContents = \IPS\Text\Parser::parseStatic( $descriptionContents, TRUE, NULL, $this->member, 'calendar_Calendar' );
$descriptionContents = Parser::parseStatic( $descriptionContents, NULL, $this->member, 'calendar_Calendar' );
}
$item->content = $descriptionContents;
/* RSVP */
if ( isset( \IPS\Request::i()->rsvp ) and ( !$this->member or $item->container()->can( 'askrsvp', $this->member ) ) )
if ( isset( Request::i()->rsvp ) and ( !$this->member or $item->container()->can( 'askrsvp', $this->member ) ) )
{
$item->rsvp = \intval( \IPS\Request::i()->rsvp );
if ( $item->rsvp and isset( \IPS\Request::i()->rsvpLimit ) and \IPS\Request::i()->rsvpLimit )
$item->rsvp = intval( Request::i()->rsvp );
if ( $item->rsvp and isset( Request::i()->rsvpLimit ) and Request::i()->rsvpLimit )
{
$item->rsvp_limit = \IPS\Request::i()->rsvpLimit;
$item->rsvp_limit = Request::i()->rsvpLimit;
}
else
{
@@ -582,11 +626,11 @@ class _events extends \IPS\Content\Api\ItemController
}
/* Location */
if ( isset( \IPS\Request::i()->location ) )
if ( isset( Request::i()->location ) )
{
if ( \IPS\Request::i()->location )
if ( Request::i()->location )
{
$location = \IPS\GeoLocation::buildFromJson( json_encode( \IPS\Request::i()->location ) );
$location = GeoLocation::buildFromJson( json_encode( Request::i()->location ) );
if ( !$location->lat or !$location->long )
{
try
@@ -609,25 +653,26 @@ class _events extends \IPS\Content\Api\ItemController
*
* @param int $id ID Number
* @throws 2L296/5 INVALID_ID The event ID does not exist
* @return void
* @apireturn void
* @return Response
*/
public function DELETEitem( $id )
public function DELETEitem( int $id ): Response
{
try
{
$item = \IPS\calendar\Event::load( $id );
$item = Event::load( $id );
if ( $this->member and !$item->canDelete( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2F294/B', 404 );
throw new Exception( 'NO_PERMISSION', '2F294/B', 404 );
}
$item->delete();
return new \IPS\Api\Response( 200, NULL );
return new Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L296/5', 404 );
throw new Exception( 'INVALID_ID', '2L296/5', 404 );
}
}
}
+77 -52
View File
@@ -12,21 +12,36 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use InvalidArgumentException;
use IPS\Api\Exception;
use IPS\Api\PaginatedResponse;
use IPS\Api\Response;
use IPS\calendar\Event;
use IPS\calendar\Event\Review;
use IPS\Content\Api\CommentController;
use IPS\Member;
use IPS\Request;
use IPS\Settings;
use OutOfRangeException;
use function defined;
use function in_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;
}
/**
* @brief Calendar Events Reviews API
*/
class _reviews extends \IPS\Content\Api\CommentController
class reviews extends CommentController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Event\Review';
protected string $class = 'IPS\calendar\Event\Review';
/**
* GET /calendar/reviews
@@ -42,9 +57,10 @@ class _reviews extends \IPS\Content\Api\CommentController
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Event\Review>
* @apireturn PaginatedResponse<IPS\calendar\Event\Review>
* @return PaginatedResponse<Review>
*/
public function GETindex()
public function GETindex(): PaginatedResponse
{
return $this->_list( array(), 'calendars' );
}
@@ -55,12 +71,14 @@ class _reviews extends \IPS\Content\Api\CommentController
*
* @param int $id ID Number
* @throws 2L298/1 INVALID_ID The review ID does not exist or the authorized user does not have permission to view it
* @return \IPS\calendar\Event\Review
* @apireturn \IPS\calendar\Event\Review
* @return Response
*/
public function GETitem( $id )
public function GETitem( int $id ): Response
{
try
{
/* @var Review $class */
$class = $this->class;
if ( $this->member )
{
@@ -71,11 +89,11 @@ class _reviews extends \IPS\Content\Api\CommentController
$object = $class::load( $id );
}
return new \IPS\Api\Response( 200, $object->apiOutput( $this->member ) );
return new Response( 200, $object->apiOutput( $this->member ) );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L298/1', 404 );
throw new Exception( 'INVALID_ID', '2L298/1', 404 );
}
}
@@ -98,18 +116,19 @@ class _reviews extends \IPS\Content\Api\CommentController
* @throws 1L298/4 NO_CONTENT No content was supplied
* @throws 1L298/8 INVALID_RATING The rating is not a valid number up to the maximum rating
* @throws 2L298/A NO_PERMISSION The authorized user does not have permission to review that event
* @return \IPS\calendar\Event\Review
* @apireturn \IPS\calendar\Event\Review
* @return Response
*/
public function POSTindex()
public function POSTindex(): Response
{
/* Get event */
try
{
$event = \IPS\calendar\Event::load( \IPS\Request::i()->event );
$event = Event::load( Request::i()->event );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L298/2', 403 );
throw new Exception( 'INVALID_ID', '2L298/2', 403 );
}
/* Get author */
@@ -117,44 +136,44 @@ class _reviews extends \IPS\Content\Api\CommentController
{
if ( !$event->canReview( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L298/A', 403 );
throw new Exception( 'NO_PERMISSION', '2L298/A', 403 );
}
$author = $this->member;
}
else
{
if ( \IPS\Request::i()->author )
if ( Request::i()->author )
{
$author = \IPS\Member::load( \IPS\Request::i()->author );
$author = Member::load( Request::i()->author );
if ( !$author->member_id )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L298/3', 404 );
throw new Exception( 'NO_AUTHOR', '1L298/3', 404 );
}
}
else
{
if ( (int) \IPS\Request::i()->author === 0 )
if ( Request::i()->author === 0 )
{
$author = new \IPS\Member;
$author->name = \IPS\Request::i()->author_name;
$author = new Member;
$author->name = Request::i()->author_name;
}
else
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L298/3', 400 );
throw new Exception( 'NO_AUTHOR', '1L298/3', 400 );
}
}
}
/* Check we have a post */
if ( !\IPS\Request::i()->content )
if ( !Request::i()->content )
{
throw new \IPS\Api\Exception( 'NO_CONTENT', '1L298/4', 403 );
throw new Exception( 'NO_CONTENT', '1L298/4', 403 );
}
/* Check we have a rating */
if ( !\IPS\Request::i()->rating or !\in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
if ( !Request::i()->rating or !in_array( (int) Request::i()->rating, range( 1, Settings::i()->reviews_rating_out_of ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RATING', '1L298/8', 403 );
throw new Exception( 'INVALID_RATING', '1L298/8', 403 );
}
/* Do it */
@@ -177,41 +196,42 @@ class _reviews extends \IPS\Content\Api\CommentController
* @throws 1L298/6 NO_AUTHOR The author ID does not exist
* @throws 1L298/9 INVALID_RATING The rating is not a valid number up to the maximum rating
* @throws 2L298/B NO_PERMISSION The authorized user does not have permission to edit the review
* @return \IPS\calendar\Event\Review
* @apireturn \IPS\calendar\Event\Review
* @return Response
*/
public function POSTitem( $id )
public function POSTitem( int $id ): Response
{
try
{
/* Load */
$comment = \IPS\calendar\Event\Review::load( $id );
$comment = Review::load( $id );
if ( $this->member and !$comment->canView( $this->member ) )
{
throw new \OutOfRangeException;
throw new OutOfRangeException;
}
if ( $this->member and !$comment->canEdit( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L298/B', 403 );
throw new Exception( 'NO_PERMISSION', '2L298/B', 403 );
}
/* Check */
if ( isset( \IPS\Request::i()->rating ) and !\in_array( (int) \IPS\Request::i()->rating, range( 1, \IPS\Settings::i()->reviews_rating_out_of ) ) )
if ( isset( Request::i()->rating ) and !in_array( (int) Request::i()->rating, range( 1, Settings::i()->reviews_rating_out_of ) ) )
{
throw new \IPS\Api\Exception( 'INVALID_RATING', '1L298/9', 403 );
throw new Exception( 'INVALID_RATING', '1L298/9', 403 );
}
/* Do it */
try
{
return $this->_edit( $comment );
}
catch ( \InvalidArgumentException $e )
catch ( InvalidArgumentException $e )
{
throw new \IPS\Api\Exception( 'NO_AUTHOR', '1L298/6', 400 );
throw new Exception( 'NO_AUTHOR', '1L298/6', 400 );
}
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L298/5', 404 );
throw new Exception( 'INVALID_ID', '2L298/5', 404 );
}
}
@@ -222,25 +242,27 @@ class _reviews extends \IPS\Content\Api\CommentController
* @param int $id ID Number
* @throws 2L298/7 INVALID_ID The review ID does not exist
* @throws 2L298/C NO_PERMISSION The authorized user does not have permission to delete the comment
* @return void
* @apireturn void
* @return Response
*/
public function DELETEitem( $id )
public function DELETEitem( int $id ): Response
{
try
{
{
/* @var Review $class */
$class = $this->class;
$object = $class::load( $id );
if ( $this->member and !$object->canDelete( $this->member ) )
{
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2L298/C', 403 );
throw new Exception( 'NO_PERMISSION', '2L298/C', 403 );
}
$object->delete();
return new \IPS\Api\Response( 200, NULL );
return new Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2L298/7', 404 );
throw new Exception( 'INVALID_ID', '2L298/7', 404 );
}
}
@@ -251,14 +273,15 @@ class _reviews extends \IPS\Content\Api\CommentController
* @param int $id ID Number
* @apiparam int id ID of the reaction to add
* @apiparam int author ID of the member reacting
* @return \IPS\calendar\Event\Review
* @apireturn \IPS\calendar\Event\Review
* @throws 1S425/2 NO_REACTION The reaction ID does not exist
* @throws 1S425/3 NO_AUTHOR The author ID does not exist
* @throws 1S425/4 REACT_ERROR Error adding the reaction
* @throws 1S425/5 INVALID_ID Object ID does not exist
* @note If the author has already reacted to this content, any existing reaction will be removed first
* @return Response
*/
public function POSTitem_react( $id )
public function POSTitem_react( int $id ): Response
{
return $this->_reactAdd( $id );
}
@@ -269,13 +292,14 @@ class _reviews extends \IPS\Content\Api\CommentController
*
* @param int $id ID Number
* @apiparam int author ID of the member who reacted
* @return \IPS\calendar\Event\Review
* @apireturn Review
* @throws 1S425/6 NO_AUTHOR The author ID does not exist
* @throws 1S425/7 REACT_ERROR Error adding the reaction
* @throws 1S425/8 INVALID_ID Object ID does not exist
* @note If the author has already reacted to this content, any existing reaction will be removed first
* @return Response
*/
public function DELETEitem_react( $id )
public function DELETEitem_react( int $id ): Response
{
return $this->_reactRemove( $id );
}
@@ -289,9 +313,10 @@ class _reviews extends \IPS\Content\Api\CommentController
* @apiparam string message Optional message
* @throws 1S425/B NO_AUTHOR The author ID does not exist
* @throws 1S425/C REPORTED_ALREADY The member has reported this item in the past 24 hours
* @return \IPS\calendar\Event\Review
* @apireturn \IPS\calendar\Event\Review
* @return Response
*/
public function POSTitem_report( $id )
public function POSTitem_report( int $id ): Response
{
return $this->_report( $id );
}
+61 -38
View File
@@ -12,21 +12,38 @@
namespace IPS\calendar\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use BadMethodCallException;
use IPS\Api\Exception;
use IPS\Api\PaginatedResponse;
use IPS\Api\Response;
use IPS\calendar\Venue;
use IPS\GeoLocation;
use IPS\Http\Url\Friendly;
use IPS\Lang;
use IPS\Node\Api\NodeController;
use IPS\Node\Model;
use IPS\Request;
use OutOfRangeException;
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;
}
/**
* @brief Calendar Venues API
*/
class _venues extends \IPS\Node\Api\NodeController
class venues extends NodeController
{
/**
* Class
*/
protected $class = 'IPS\calendar\Venue';
protected string $class = 'IPS\calendar\Venue';
/**
* GET /calendar/venues
@@ -34,9 +51,10 @@ class _venues extends \IPS\Node\Api\NodeController
*
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\calendar\Venue>
* @apireturn PaginatedResponse<IPS\calendar\Venue>
* @return PaginatedResponse<Venue>
*/
public function GETindex()
public function GETindex(): PaginatedResponse
{
/* Return */
return $this->_list();
@@ -48,17 +66,18 @@ class _venues extends \IPS\Node\Api\NodeController
*
* @param int $id ID Number
* @throws 1L384/1 INVALID_ID The venue does not exist
* @return \IPS\calendar\Venue
* @apireturn \IPS\calendar\Venue
* @return Response
*/
public function GETitem( $id )
public function GETitem( int $id ): Response
{
try
{
return $this->_view( $id );
}
catch ( \OutOfRangeException $e )
catch ( OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '1L384/1', 404 );
throw new Exception( 'INVALID_ID', '1L384/1', 404 );
}
}
@@ -70,16 +89,17 @@ class _venues extends \IPS\Node\Api\NodeController
* @reqapiparam string title The venue title
* @reqapiparam \IPS\GeoLocation address The venue address (latitude and longitude do not need to be supplied and will be ignored)
* @apiparam string description The venue description
* @return \IPS\calendar\Venue
* @apireturn \IPS\calendar\Venue
* @throws 1L384/2 NO_ADDRESS An address is required for the venue but was not supplied
* @throws 1L384/3 INVALID_ADDRESS An invalid address was supplied
* @throws 1L384/4 NO_TITLE No title was supplied for the venue
* @return Response
*/
public function POSTindex()
public function POSTindex(): Response
{
if( !\IPS\Request::i()->address OR !\is_array( \IPS\Request::i()->address ) )
if( !Request::i()->address OR !is_array( Request::i()->address ) )
{
throw new \IPS\Api\Exception( 'NO_ADDRESS', '1L384/2', 400 );
throw new Exception( 'NO_ADDRESS', '1L384/2', 400 );
}
else
{
@@ -87,12 +107,12 @@ class _venues extends \IPS\Node\Api\NodeController
$this->_getGeoLocationObject();
}
if ( !\IPS\Request::i()->title )
if ( !Request::i()->title )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1L384/4', 400 );
throw new Exception( 'NO_TITLE', '1L384/4', 400 );
}
return new \IPS\Api\Response( 201, $this->_create()->apiOutput( $this->member ) );
return new Response( 201, $this->_create()->apiOutput( $this->member ) );
}
/**
@@ -104,17 +124,19 @@ class _venues extends \IPS\Node\Api\NodeController
* @reqapiparam \IPS\GeoLocation address The venue address (latitude and longitude do not need to be supplied and will be ignored)
* @apiparam string description The venue description
* @param int $id ID Number
* @return \IPS\calendar\Venue
* @apireturn \IPS\calendar\Venue
* @throws 1L384/2 NO_ADDRESS An address is required for the venue but was not supplied
* @throws 1L384/3 INVALID_ADDRESS An invalid address was supplied
* @throws 1L384/4 NO_TITLE No title was supplied for the venue
* @return Response
*/
public function POSTitem( $id )
public function POSTitem( int $id ): Response
{
/* @var Venue $class */
$class = $this->class;
$venue = $class::load( $id );
return new \IPS\Api\Response( 200, $this->_createOrUpdate( $venue )->apiOutput( $this->member ) );
return new Response( 200, $this->_createOrUpdate( $venue )->apiOutput( $this->member ) );
}
/**
@@ -123,9 +145,10 @@ class _venues extends \IPS\Node\Api\NodeController
*
* @apiclientonly
* @param int $id ID Number
* @return void
* @apireturn void
* @return Response
*/
public function DELETEitem( $id )
public function DELETEitem( int $id ): Response
{
return $this->_delete( $id );
}
@@ -133,27 +156,27 @@ class _venues extends \IPS\Node\Api\NodeController
/**
* Create or update node
*
* @param \IPS\node\Model $venue The node
* @return \IPS\node\Model
* @param Model $venue The node
* @return Model
*/
protected function _createOrUpdate( \IPS\Node\Model $venue )
protected function _createOrUpdate( Model $venue ): Model
{
if( \IPS\Request::i()->address AND \is_array( \IPS\Request::i()->address ) )
if( Request::i()->address AND is_array( Request::i()->address ) )
{
$geoLocation = $this->_getGeoLocationObject();
$venue->address = json_encode( $geoLocation );
}
if ( isset( \IPS\Request::i()->title ) )
if ( isset( Request::i()->title ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id, \IPS\Request::i()->title );
$venue->title_seo = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->title );
Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id, Request::i()->title );
$venue->title_seo = Friendly::seoTitle( Request::i()->title );
}
if( isset( \IPS\Request::i()->description ) )
if( isset( Request::i()->description ) )
{
\IPS\Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id .'_desc', \IPS\Request::i()->description );
Lang::saveCustom( 'calendar', 'calendar_venue_' . $venue->id .'_desc', Request::i()->description );
}
return parent::_createOrUpdate( $venue );
@@ -162,16 +185,16 @@ class _venues extends \IPS\Node\Api\NodeController
/**
* Get geolocation object
*
* @return array
* @return GeoLocation
*/
protected function _getGeoLocationObject()
protected function _getGeoLocationObject(): GeoLocation
{
$geoLocation = new \IPS\GeoLocation;
$geoLocation = new GeoLocation;
$geoLocation->addressLines = array();
foreach( \IPS\Request::i()->address as $k => $v )
foreach( Request::i()->address as $k => $v )
{
if( \in_array( $k, array( 'city', 'postalCode', 'region', 'addressLines', 'country' ) ) )
if( in_array( $k, array( 'city', 'postalCode', 'region', 'addressLines', 'country' ) ) )
{
$geoLocation->$k = $v;
}
@@ -181,9 +204,9 @@ class _venues extends \IPS\Node\Api\NodeController
{
$geoLocation->getLatLong();
}
catch( \BadMethodCallException $e )
catch( BadMethodCallException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ADDRESS', '1L384/3', 400 );
throw new Exception( 'INVALID_ADDRESS', '1L384/3', 400 );
}
return $geoLocation;