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

+9 -8
View File
@@ -10,13 +10,13 @@
*/
namespace IPS\Api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Api\GraphQL\Queries\ModuleAccess;
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;
}
@@ -24,18 +24,19 @@ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
* Core controller for GraphQL API
* @todo maybe this shouldn't be a class since it only has a static method?
*/
abstract class _AppQueries
abstract class AppQueries
{
/**
* Get the supported query types in this app
*
* @return array
* @param string $app
* @return array
*/
public static function queries($app): array
public static function queries( string $app ): array
{
return [
'moduleAccess' => new \IPS\Api\GraphQL\Queries\ModuleAccess($app)
'moduleAccess' => new ModuleAccess($app)
];
}
}
@@ -12,25 +12,27 @@
namespace IPS\Api\GraphQL\Fields;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
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;
}
/**
* ForumType for GraphQL API
*/
abstract class _CoverPhotoField
abstract class CoverPhotoField
{
/**
* Get root type
*
* @return array
* @param string $name
* @return array
*/
public static function getDefinition($name): array
public static function getDefinition( string $name ): array
{
return [
'type' => new ObjectType([
@@ -45,11 +47,10 @@ abstract class _CoverPhotoField
{
case 'image':
return ( $value->file ) ? (string) $value->file->url : null;
break;
case 'offset':
return ( $value->file ) ? $value->offset : null;
break;
}
return null;
}
]),
'description' => 'Returns a cover photo',
+11 -8
View File
@@ -12,25 +12,28 @@
namespace IPS\Api\GraphQL\Fields;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\IPS;
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;
}
/**
* TagsEditField for GraphQL API
*/
abstract class _TagsEditField
abstract class TagsEditField
{
/**
* Get root type
*
* @return array
* @param string $name
* @return array
*/
public static function getDefinition($name): array
public static function getDefinition( string $name ): array
{
return [
'type' => new ObjectType([
@@ -41,7 +44,8 @@ abstract class _TagsEditField
'resolve' => function ($container, $args, $context) {
$contentClass = $container::$contentItemClass;
if( \in_array( 'IPS\Content\Tags', class_implements( $contentClass ) ) ){
if( IPS::classUsesTrait( $contentClass, 'IPS\Content\Taggable' ) )
{
return true;
}
@@ -52,8 +56,7 @@ abstract class _TagsEditField
'type' => TypeRegistry::listOf( TypeRegistry::string() ),
'resolve' => function ($container, $args, $context) {
$contentClass = $container::$contentItemClass;
$tags = array_unique( $contentClass::definedTags( $container ) );
$tags = array_unique( $contentClass::definedTags() );
return $tags;
}
]
+22 -13
View File
@@ -11,16 +11,26 @@
namespace IPS\Api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use GraphQL\Error\DebugFlag;
use GraphQL\GraphQL as _GraphQL;
use GraphQL\Type\Schema;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\IPS;
use IPS\Member;
use function defined;
use const IPS\DEBUG_GRAPHQL;
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;
}
/**
* Base API Controller
*/
class _GraphQL
class GraphQL
{
public function __construct()
@@ -33,20 +43,20 @@ class _GraphQL
*
* @param string $query The query to execute
* @param array $variables Variables to include in query
* @param \IPS\Member|NULL $member Member to check or NULL for currently logged in member.
* @param Member|null $member Member to check or NULL for currently logged in member.
* @return array GraphQL response
*/
public static function execute( string $query, array $variables = [], ?\IPS\Member $member = NULL )
public static function execute( string $query, array $variables = [], ?Member $member = NULL ) : array
{
$member = $member ?: \IPS\Member::loggedIn();
$member = $member ?: Member::loggedIn();
/* Register our GraphQL library */
\IPS\IPS::$PSR0Namespaces['GraphQL'] = \IPS\ROOT_PATH . "/system/3rd_party/graphql-php";
IPS::$PSR0Namespaces['GraphQL'] = \IPS\ROOT_PATH . "/system/3rd_party/graphql-php";
/* Execute! */
$result = \GraphQL\GraphQL::executeQuery(
new \GraphQL\Type\Schema([
'query' => \IPS\Api\GraphQL\TypeRegistry::query(),
'mutation' => \IPS\Api\GraphQL\TypeRegistry::mutation()
$result = _GraphQL::executeQuery(
new Schema([
'query' => TypeRegistry::query(),
'mutation' => TypeRegistry::mutation()
]),
$query,
NULL, // $rootValue
@@ -57,7 +67,6 @@ class _GraphQL
);
/* Convert result into JSON and send */
$output = $result->toArray( ( \IPS\IN_DEV OR \IPS\DEBUG_GRAPHQL ) ? \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\DebugFlag::INCLUDE_TRACE : false );
return $output;
return $result->toArray( ( \IPS\IN_DEV OR DEBUG_GRAPHQL ) ? DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::INCLUDE_TRACE : false );
}
}
+16 -12
View File
@@ -10,22 +10,26 @@
*/
namespace IPS\Api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Api\GraphQL\Types\ModuleAccessType;
use IPS\Application;
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;
}
/**
* ModuleAccess query for GraphQL API
*/
class _ModuleAccess
class ModuleAccess
{
public function __construct($app)
protected ?Application $app = null;
public function __construct( Application $app )
{
$this->app = $app;
}
@@ -33,7 +37,7 @@ class _ModuleAccess
/*
* @brief Query description
*/
public static $description = "Returns module view permissions";
public static string $description = "Returns module view permissions";
/*
* Query arguments
@@ -46,7 +50,7 @@ class _ModuleAccess
/**
* Return the query return type
*/
public function type()
public function type() : ModuleAccessType
{
return TypeRegistry::moduleAccess();
}
@@ -54,12 +58,12 @@ class _ModuleAccess
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\Application
* @param mixed $val Value passed into this resolver
* @param array $args Arguments
* @param array $context Context values
* @return Application
*/
public function resolve($val, $args, $context)
public function resolve( mixed $val, array $args, array $context ) : Application
{
return $this->app;
}
+11 -10
View File
@@ -11,28 +11,30 @@
namespace IPS\Api\GraphQL;
/* 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;
}
use Exception;
use GraphQL\Error\ClientAware;
use function defined;
/**
* API Exception
*/
class _SafeException extends \Exception implements ClientAware
class SafeException extends Exception implements ClientAware
{
/**
* @brief Exception code
*/
public $exceptionCode;
public ?string $exceptionCode = null;
/**
* @brief OAUth Error
*/
public $oauthError;
public ?string $oauthError = null;
/**
* Constructor
@@ -40,21 +42,20 @@ class _SafeException extends \Exception implements ClientAware
* @param string $message Error Message
* @param string $code Code
* @param int $httpCode HTTP Error code
* @param string $oauthError Error Message for OAuth
* @return void
*/
public function __construct( $message, $code, $httpCode )
public function __construct( string $message, string $code, int $httpCode )
{
$this->exceptionCode = $code;
return parent::__construct( $message, $httpCode );
parent::__construct( $message, $httpCode );
}
public function getCategory()
public function getCategory() : string
{
return 'clienterror';
}
public function isClientSafe()
public function isClientSafe() : bool
{
return true;
}
+74 -56
View File
@@ -10,33 +10,49 @@
*/
namespace IPS\Api\GraphQL;
use GraphQL\Type\Definition\BooleanType;
use GraphQL\Type\Definition\FloatType;
use GraphQL\Type\Definition\IDType;
use GraphQL\Type\Definition\IntType;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\StringType;
use GraphQL\Type\Definition\Type;
use IPS\Api\GraphQL\Types\FollowType;
use IPS\Api\GraphQL\Types\ImageType;
use IPS\Api\GraphQL\Types\ItemStateType;
use IPS\Api\GraphQL\Types\ModuleAccessType;
use IPS\Api\GraphQL\Types\MutationType;
use IPS\Api\GraphQL\Types\QueryType;
use IPS\Api\GraphQL\Types\ReputationType;
use IPS\Api\GraphQL\Types\RichTextType;
use IPS\Api\GraphQL\Types\UrlType;
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;
}
/**
* Type registry
*/
class _TypeRegistry
class TypeRegistry
{
protected static $query;
protected static $mutation;
protected static $itemState;
protected static $image;
protected static $reputation;
protected static $richText;
protected static $url;
protected static $follow;
protected static $moduleAccess;
protected static ?QueryType $query = null;
protected static ?MutationType $mutation = null;
protected static ?ItemStateType $itemState = null;
protected static ?ImageType $image = null;
protected static ?ReputationType $reputation = null;
protected static ?RichTextType $richText = null;
protected static ?UrlType $url = null;
protected static ?FollowType $follow = null;
protected static ?ModuleAccessType $moduleAccess = null;
/**
* Constructor
@@ -47,134 +63,136 @@ class _TypeRegistry
}
/**
* @return \IPS\Api\GraphQL\Types\QueryType
* @return QueryType
*/
public static function query(): \IPS\Api\GraphQL\Types\QueryType
public static function query(): QueryType
{
return self::$query ?: (self::$query = new \IPS\Api\GraphQL\Types\QueryType());
return self::$query ?: (self::$query = new QueryType());
}
/**
* @return \IPS\Api\GraphQL\Types\MutationType
* @return MutationType
*/
public static function mutation(): \IPS\Api\GraphQL\Types\MutationType
public static function mutation(): MutationType
{
return self::$mutation ?: (self::$mutation = new \IPS\Api\GraphQL\Types\MutationType());
return self::$mutation ?: (self::$mutation = new MutationType());
}
/**
* @return \IPS\Api\GraphQL\Types\ItemStateType
* @return ItemStateType
*/
public static function itemState(): \IPS\Api\GraphQL\Types\ItemStateType
public static function itemState(): ItemStateType
{
return self::$itemState ?: (self::$itemState = new \IPS\Api\GraphQL\Types\ItemStateType());
return self::$itemState ?: (self::$itemState = new ItemStateType());
}
/**
* @return ImageType
*/
public static function image(): \IPS\Api\GraphQL\Types\ImageType
public static function image(): ImageType
{
return self::$image ?: (self::$image = new \IPS\Api\GraphQL\Types\ImageType());
return self::$image ?: (self::$image = new ImageType());
}
/**
* @return \IPS\Api\GraphQL\Types\ReputationType
* @return ReputationType
*/
public static function reputation(): \IPS\Api\GraphQL\Types\ReputationType
public static function reputation(): ReputationType
{
return self::$reputation ?: (self::$reputation = new \IPS\Api\GraphQL\Types\ReputationType());
return self::$reputation ?: (self::$reputation = new ReputationType());
}
/**
* @return \IPS\Api\GraphQL\Types\RichTextType
* @return RichTextType
*/
public static function richText(): \IPS\Api\GraphQL\Types\RichTextType
public static function richText(): RichTextType
{
return self::$richText ?: (self::$richText = new \IPS\Api\GraphQL\Types\RichTextType());
return self::$richText ?: (self::$richText = new RichTextType());
}
/**
* @return \IPS\Api\GraphQL\Types\UrlType
* @return UrlType
*/
public static function url(): \IPS\Api\GraphQL\Types\UrlType
public static function url(): UrlType
{
return self::$url ?: (self::$url = new \IPS\Api\GraphQL\Types\UrlType());
return self::$url ?: (self::$url = new UrlType());
}
/**
* @return \IPS\Api\GraphQL\Types\FollowType
* @return FollowType
*/
public static function follow(): \IPS\Api\GraphQL\Types\FollowType
public static function follow(): FollowType
{
return self::$follow ?: (self::$follow = new \IPS\Api\GraphQL\Types\FollowType());
return self::$follow ?: (self::$follow = new FollowType());
}
/**
* @return \IPS\Api\GraphQL\Types\ModuleAccessType
* @return ModuleAccessType
*/
public static function moduleAccess(): \IPS\Api\GraphQL\Types\ModuleAccessType
public static function moduleAccess(): ModuleAccessType
{
return self::$moduleAccess ?: (self::$moduleAccess = new \IPS\Api\GraphQL\Types\ModuleAccessType());
return self::$moduleAccess ?: (self::$moduleAccess = new ModuleAccessType());
}
/**
* @return \GraphQL\Type\Definition\IDType
* @return ScalarType
*/
public static function id(): \GraphQL\Type\Definition\IDType
public static function id(): IDType
{
return Type::id();
}
/**
* @return \GraphQL\Type\Definition\StringType
* @return ScalarType
*/
public static function string(): \GraphQL\Type\Definition\StringType
public static function string(): StringType
{
return Type::string();
}
/**
* @return \GraphQL\Type\Definition\IntType
* @return ScalarType
*/
public static function int(): \GraphQL\Type\Definition\IntType
public static function int(): IntType
{
return Type::int();
}
/**
* @return \GraphQL\Type\Definition\FloatType
* @return ScalarType
*/
public static function float(): \GraphQL\Type\Definition\FloatType
public static function float(): FloatType
{
return Type::float();
}
/**
* @return \GraphQL\Type\Definition\BooleanType
* @return ScalarType
*/
public static function boolean(): \GraphQL\Type\Definition\BooleanType
public static function boolean(): BooleanType
{
return Type::boolean();
}
/**
* @return \GraphQL\Type\Definition\ListOfType
*/
public static function listOf($type): \GraphQL\Type\Definition\ListOfType
* @param mixed $type
* @return ListOfType
*/
public static function listOf( mixed $type): ListOfType
{
return new ListOfType($type);
}
/**
* @return \GraphQL\Type\Definition\EnumType
*/
public static function eNum($config): \GraphQL\Type\Definition\EnumType
* @param array $config
* @return EnumType
*/
public static function eNum( array $config): EnumType
{
return new EnumType($config);
}
public static function inputObjectType($config): \GraphQL\Type\Definition\InputObjectType
public static function inputObjectType( array $config): InputObjectType
{
return new InputObjectType($config);
}
@@ -183,7 +201,7 @@ class _TypeRegistry
* @param Type $type
* @return NonNull
*/
public static function nonNull($type): \GraphQL\Type\Definition\NonNull
public static function nonNull( mixed $type): NonNull
{
return new NonNull($type);
}
+22 -18
View File
@@ -12,23 +12,27 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Content;
use IPS\Db;
use IPS\Member;
use UnderflowException;
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;
}
/**
* FollowType for GraphQL API
*/
class _FollowType extends ObjectType
class FollowType extends ObjectType
{
/**
* Get root type
*
* @return array
*/
public function __construct()
{
@@ -47,13 +51,13 @@ class _FollowType extends ObjectType
'followID' => [
'type' => TypeRegistry::id(),
'resolve' => function ($followData) {
return md5( $followData['app'] . ';' . $followData['area'] . ';' . $followData['id'] . ';' . \IPS\Member::loggedIn()->member_id );
return md5( $followData['app'] . ';' . $followData['area'] . ';' . $followData['id'] . ';' . Member::loggedIn()->member_id );
}
],
'isFollowing' => [
'type' => TypeRegistry::boolean(),
'resolve' => function ($followData) {
return \IPS\Member::loggedIn()->following( $followData['app'], $followData['area'], $followData['id'] );
return Member::loggedIn()->following( $followData['app'], $followData['area'], $followData['id'] );
}
],
'followType' => [
@@ -62,18 +66,18 @@ class _FollowType extends ObjectType
'values' => ['NOT_FOLLOWING', 'PUBLIC', 'ANONYMOUS']
]),
'resolve' => function ($followData) {
if( !\IPS\Member::loggedIn()->following( $followData['app'], $followData['area'], $followData['id'] ) )
if( !Member::loggedIn()->following( $followData['app'], $followData['area'], $followData['id'] ) )
{
return 'NOT_FOLLOWING';
}
try
{
$current = \IPS\Db::i()->select( 'follow_is_anon', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=? AND follow_member_id=?', $followData['app'], $followData['area'], $followData['id'], \IPS\Member::loggedIn()->member_id ), NULL, array(), NULL, NULL )->first();
$current = Db::i()->select( 'follow_is_anon', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=? AND follow_member_id=?', $followData['app'], $followData['area'], $followData['id'], Member::loggedIn()->member_id ), NULL, array() )->first();
return $current['follow_is_anon'] ? 'ANONYMOUS' : 'PUBLIC';
}
catch ( \UnderflowException $e )
catch ( UnderflowException $e )
{
return 'NOT_FOLLOWING';
}
@@ -107,11 +111,11 @@ class _FollowType extends ObjectType
}
elseif( isset( $followData['member'] ) )
{
return $followData['member']->followersCount( \IPS\Member::FOLLOW_ANONYMOUS );
return $followData['member']->followersCount( Content::FOLLOW_ANONYMOUS );
}
else
{
return $followData['item']->followersCount( $followData['itemClass']::FOLLOW_ANONYMOUS );
return $followData['item']->followersCount( Content::FOLLOW_ANONYMOUS );
}
}
],
@@ -138,7 +142,7 @@ class _FollowType extends ObjectType
}
elseif( isset( $followData['member'] ) )
{
$_followers = $followData['member']->followers( \IPS\Member::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( $offset, $limit ), 'name' );
$_followers = $followData['member']->followers( Content::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( $offset, $limit ), 'name' );
}
else
{
@@ -155,7 +159,7 @@ class _FollowType extends ObjectType
foreach( $_followers as $followerRow )
{
$followers[] = \IPS\Member::load( $followerRow['follow_member_id'] );
$followers[] = Member::load( $followerRow['follow_member_id'] );
}
return $followers;
@@ -176,7 +180,7 @@ class _FollowType extends ObjectType
]) ),
'resolve' => function ($followData, $args) {
// No options if we're a guest
if( !\IPS\Member::loggedIn()->member_id )
if( !Member::loggedIn()->member_id )
{
return array();
}
@@ -184,9 +188,9 @@ class _FollowType extends ObjectType
/* Do we follow it? */
try
{
$current = \IPS\Db::i()->select( '*', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=? AND follow_member_id=?', $followData['app'], $followData['area'], $followData['id'], \IPS\Member::loggedIn()->member_id ), NULL, array(), NULL, NULL )->first();
$current = Db::i()->select( '*', 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=? AND follow_member_id=?', $followData['app'], $followData['area'], $followData['id'], Member::loggedIn()->member_id ), NULL, array() )->first();
}
catch ( \UnderflowException $e )
catch ( UnderflowException $e )
{
$current = FALSE;
}
@@ -205,8 +209,8 @@ class _FollowType extends ObjectType
$followType = 'new_comment';
}
$notificationConfiguration = \IPS\Member::loggedIn()->notificationsConfiguration();
$notificationConfiguration = isset( $notificationConfiguration[ $followType ] ) ? $notificationConfiguration[ $followType ] : array();
$notificationConfiguration = Member::loggedIn()->notificationsConfiguration();
$notificationConfiguration = $notificationConfiguration[$followType] ?? array();
// Now figure out which options we can have
$options = array( array(
+4 -4
View File
@@ -12,23 +12,23 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
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;
}
/**
* ImageType for GraphQL API
*/
class _ImageType extends ObjectType
class ImageType extends ObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
+4 -4
View File
@@ -12,23 +12,23 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\InputObjectType;
use IPS\Api\GraphQL\TypeRegistry;
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;
}
/**
* ItemStateType for GraphQL API
*/
class _ItemStateType extends InputObjectType
class ItemStateType extends InputObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
@@ -10,25 +10,28 @@
*/
namespace IPS\Api\GraphQL\Types;
use Exception;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Application\Module;
use IPS\Member;
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;
}
/**
* ModuleAccessType for GraphQL API
*/
class _ModuleAccessType extends ObjectType
class ModuleAccessType extends ObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
@@ -47,9 +50,9 @@ class _ModuleAccessType extends ObjectType
$canAccess = FALSE;
try
{
$canAccess = \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( $app, $args['module'], 'front' ) );
$canAccess = Member::loggedIn()->canAccessModule( Module::get( $app, $args['module'], 'front' ) );
}
catch (\Exception $e)
catch (Exception $e)
{
// Just fall through so we return false
}
+9 -7
View File
@@ -11,19 +11,21 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Api\Exception;
use IPS\Application;
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;
}
/**
* API Exception
*/
class _MutationType extends ObjectType
class MutationType extends ObjectType
{
public function __construct()
{
@@ -32,7 +34,7 @@ class _MutationType extends ObjectType
'fields' => function () {
$_fields = array();
foreach( \IPS\Application::enabledApplications() as $key => $app )
foreach( Application::enabledApplications() as $key => $app )
{
try
{
@@ -55,7 +57,7 @@ class _MutationType extends ObjectType
);
}
$_fields[ 'mutate' . ucfirst($app->directory) ] = new \GraphQL\Type\Definition\ObjectType( array(
$_fields[ 'mutate' . ucfirst($app->directory) ] = new ObjectType( array(
'name' => 'mutate_' . ucfirst($app->directory),
'fields' => $mutationFields
) );
@@ -87,7 +89,7 @@ class _MutationType extends ObjectType
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'NO_RESOLVE', '3S291/2_graphl', 405 );
throw new Exception( 'NO_RESOLVE', '3S291/2_graphl', 405 );
}
}
];
+12 -9
View File
@@ -11,19 +11,22 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Api\Exception;
use IPS\Api\GraphQL\AppQueries;
use IPS\Application;
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;
}
/**
* API Exception
*/
class _QueryType extends ObjectType
class QueryType extends ObjectType
{
public function __construct()
{
@@ -32,11 +35,11 @@ class _QueryType extends ObjectType
'fields' => function () {
$_fields = array();
foreach( \IPS\Application::enabledApplications() as $key => $app )
foreach( Application::enabledApplications() as $key => $app )
{
try
{
$globalAppQueries = \IPS\Api\GraphQL\AppQueries::queries($app->directory);
$globalAppQueries = AppQueries::queries($app->directory);
$appQueryClass = "\\IPS\\" . $app->directory . "\\api\\GraphQL\\Query";
if( !class_exists( $appQueryClass ) )
@@ -67,7 +70,7 @@ class _QueryType extends ObjectType
);
}
$_fields[ $app->directory ] = new \GraphQL\Type\Definition\ObjectType( array(
$_fields[ $app->directory ] = new ObjectType( array(
'name' => $app->directory,
'fields' => $queryFields
) );
@@ -84,7 +87,7 @@ class _QueryType extends ObjectType
'resolveField' => function ($val, $args, $context, $info) {
try
{
$globalAppQueries = \IPS\Api\GraphQL\AppQueries::queries($info->fieldName);
$globalAppQueries = AppQueries::queries($info->fieldName);
$appQueryClass = '\\IPS\\' . $info->fieldName . '\\api\\GraphQL\\Query';
$queryResolvers = array();
$queryTypes = $appQueryClass::queries();
@@ -111,7 +114,7 @@ class _QueryType extends ObjectType
}
catch ( \Exception $e )
{
throw new \IPS\Api\Exception( 'NO_RESOLVE', '3S291/2', 405 );
throw new Exception( 'NO_RESOLVE', '3S291/2', 405 );
}
}
];
+29 -21
View File
@@ -12,23 +12,29 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Content;
use IPS\Db;
use IPS\Member;
use IPS\Settings;
use function defined;
use function get_class;
use function intval;
/* 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;
}
/**
* ReputationType for GraphQL API
*/
class _ReputationType extends ObjectType
class ReputationType extends ObjectType
{
/**
* Get root type
*
* @return array
*/
public function __construct()
{
@@ -39,7 +45,7 @@ class _ReputationType extends ObjectType
'reactionCount' => [
'type' => TypeRegistry::int(),
'resolve' => function ($content, $args) {
if( !\IPS\Settings::i()->reputation_enabled )
if( !Settings::i()->reputation_enabled )
{
return 0;
}
@@ -50,13 +56,13 @@ class _ReputationType extends ObjectType
'canViewReps' => [
'type' => TypeRegistry::boolean(),
'resolve' => function ($content, $args) {
return \IPS\Settings::i()->reputation_enabled && \IPS\Member::loggedIn()->group['gbw_view_reps'];
return Settings::i()->reputation_enabled && Member::loggedIn()->group['gbw_view_reps'];
}
],
'canReact' => [
'type' => TypeRegistry::boolean(),
'resolve' => function ($content, $args) {
return \IPS\Settings::i()->reputation_enabled && $content->canReact();
return Settings::i()->reputation_enabled && $content->canReact();
}
],
'hasReacted' => [
@@ -65,7 +71,7 @@ class _ReputationType extends ObjectType
'isLikeMode' => [
'type' => TypeRegistry::boolean(),
'resolve' => function ($content, $args) {
return \IPS\Settings::i()->reputation_enabled && \IPS\Content\Reaction::isLikeMode();
return Settings::i()->reputation_enabled && Content\Reaction::isLikeMode();
}
],
'givenReaction' => [
@@ -80,7 +86,7 @@ class _ReputationType extends ObjectType
'reactions' => [
'type' => TypeRegistry::listOf( \IPS\core\api\GraphQL\TypeRegistry::contentReaction() ),
'resolve' => function ($content) {
if( !\IPS\Settings::i()->reputation_enabled )
if( !Settings::i()->reputation_enabled )
{
return NULL;
}
@@ -90,7 +96,7 @@ class _ReputationType extends ObjectType
foreach( $content->reactBlurb() as $key => $count )
{
$return[] = array( 'id' => md5( \get_class( $content ) . '-' . $content->$idColumn ) . '-' . $key, 'reactionId' => $key, 'count' => $count );
$return[] = array( 'id' => md5( get_class( $content ) . '-' . $content->$idColumn ) . '-' . $key, 'reactionId' => $key, 'count' => $count );
}
return $return;
@@ -110,7 +116,7 @@ class _ReputationType extends ObjectType
]
],
'resolve' => function ($content, $args) {
if( !\IPS\Settings::i()->reputation_enabled || !\IPS\Member::loggedIn()->group['gbw_view_reps'] )
if( !Settings::i()->reputation_enabled || !Member::loggedIn()->group['gbw_view_reps'] )
{
return NULL;
}
@@ -122,12 +128,12 @@ class _ReputationType extends ObjectType
if( isset( $args['id'] ) )
{
$reaction = \intval( $args['id']);
$reaction = intval( $args['id']);
}
foreach( \IPS\Db::i()->select( '*', 'core_reputation_index', $content->getReactionWhereClause( $reaction ), 'rep_date desc', array( $offset, $limit ) )->join( 'core_reactions', 'reaction=reaction_id' ) AS $reaction )
foreach( Db::i()->select( '*', 'core_reputation_index', $content->getReactionWhereClause( $reaction ), 'rep_date desc', array( $offset, $limit ) )->join( 'core_reactions', 'reaction=reaction_id' ) AS $reaction )
{
$members[] = \IPS\Member::load( $reaction['member_id'] );
$members[] = Member::load( $reaction['member_id'] );
}
return $members;
@@ -135,12 +141,12 @@ class _ReputationType extends ObjectType
]
],
'resolveField' => function ($content, $args, $context, $info) {
if( !\IPS\Settings::i()->reputation_enabled )
if( !Settings::i()->reputation_enabled )
{
return NULL;
}
$enabledReactions = \IPS\Content\Reaction::enabledReactions();
$enabledReactions = Content\Reaction::enabledReactions();
$defaultReaction = reset( $enabledReactions );
$reacted = $content->reacted();
@@ -148,25 +154,25 @@ class _ReputationType extends ObjectType
{
case 'hasReacted':
return ( $reacted and isset( $enabledReactions[ $reacted->id ] ) );
break;
case 'givenReaction':
if( !$reacted )
{
return NULL;
}
$reaction = isset( $enabledReactions[ $reacted->id ] ) ? $enabledReactions[ $reacted->id ] : $defaultReaction;
$reaction = $enabledReactions[$reacted->id] ?? $defaultReaction;
return array(
'id' => $reaction->id,
'reaction' => $reaction
);
break;
case 'defaultReaction':
return array(
'id' => $defaultReaction->id,
'reaction' => $defaultReaction
);
break;
case 'availableReactions':
$reactions = array();
@@ -179,8 +185,10 @@ class _ReputationType extends ObjectType
}
return $reactions;
break;
}
return null;
}
];
+9 -18
View File
@@ -12,23 +12,25 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Output;
use IPS\Text\Parser;
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;
}
/**
* RichTextType for GraphQL API
*/
class _RichTextType extends ObjectType
class RichTextType extends ObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
@@ -54,7 +56,7 @@ class _RichTextType extends ObjectType
'resolve' => function ($string, $args) {
/* Remove stuff we don't want to include (quotes, spoilers, scripts) */
$string = \IPS\Text\Parser::removeElements( $string, array( 'blockquote', 'script', 'div[class=ipsSpoiler]' ) );
$string = Parser::removeElements( $string, array( 'blockquote', 'script', 'div[class=ipsSpoiler]' ) );
/* Put a break in places where we actually want one */
$string = str_replace( array( '</p>', '</h1>', '</h2>', '</h3>', '</h4>', '</h5>', '</h6>', '</li>' ), '<br>', $string );
@@ -83,20 +85,9 @@ class _RichTextType extends ObjectType
'original' => [
'type' => TypeRegistry::string(),
'description' => "Returns original rich text (i.e. containing full rich markup)",
'args' => [
'removeLazyLoad' => [
'type' => TypeRegistry::boolean(),
'description' => "Remove lazy-load placeholders?",
'defaultValue' => TRUE
]
],
'args' => [ ],
'resolve' => function ($string, $args) {
if( $args['removeLazyLoad'] )
{
$string = \IPS\Text\Parser::removeLazyLoad( $string );
}
\IPS\Output::i()->parseFileObjectUrls( $string );
Output::i()->parseFileObjectUrls( $string );
return $string;
}
]
+11 -9
View File
@@ -12,23 +12,25 @@
namespace IPS\Api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
use IPS\Http\Url;
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;
}
/**
* URLType for GraphQL API
*/
class _UrlType extends ObjectType
class UrlType extends ObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
@@ -68,9 +70,9 @@ class _UrlType extends ObjectType
}
])),
'resolve' => function ($url) {
if( !( $url instanceof \IPS\Http\Url ) )
if( !( $url instanceof Url ) )
{
$url = \IPS\Http\Url::createFromString( $url );
$url = Url::createFromString( $url );
}
$pieces = array();
@@ -89,13 +91,13 @@ class _UrlType extends ObjectType
];
},
'resolveField' => function ($url, $args, $context, $info) {
if( !( $url instanceof \IPS\Http\Url ) )
if( !( $url instanceof Url ) )
{
$url = \IPS\Http\Url::createFromString( $url );
$url = Url::createFromString( $url );
}
$urlPieces = $url->hiddenQueryString;
if( \in_array( $info->fieldName, array('app', 'module', 'controller') ) )
if( in_array( $info->fieldName, array('app', 'module', 'controller') ) )
{
return $urlPieces[ $info->fieldName ];
}