Version 4.6.0

This commit is contained in:
Neo committed 2025-12-19 05:55:31 -08:00
1 parent f79dcf067a
commit 517a5e1f70
2036 files changed
+110041 -26162

No files matched your search

@@ -132,7 +132,7 @@ class _Follow
$class = 'IPS\Member\Club';
}
if ( !$class )
if ( !$class or !array_key_exists( $args['app'], \IPS\Application::applications() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NOT_FOUND', 'GQL/0001/4', 404 );
}
@@ -150,19 +150,23 @@ class _Follow
{
if ( \in_array( 'IPS\Node\Model', class_parents( $class ) ) )
{
$thing = $class::loadAndCheckPerms( $args['id'] );
$thing = $class::loadAndCheckPerms( (int) $args['id'] );
}
elseif ( $class == 'IPS\Member\Club' )
{
$thing = $class::loadAndCheckPerms( $args['id'] );
$thing = $class::loadAndCheckPerms( (int) $args['id'] );
}
elseif ( $class != "IPS\Member" )
{
$thing = $class::loadAndCheckPerms( $args['id'] );
$thing = $class::loadAndCheckPerms( (int) $args['id'] );
}
else
{
$thing = $class::load( $args['id'] );
if( !$class instanceof \IPS\Content\Followable )
{
throw new \OutOfRangeException;
}
$thing = $class::load( (int) $args['id'] );
}
}
catch ( \OutOfRangeException $e )
@@ -65,10 +65,10 @@ class _SessionEnd
throw new \IPS\Api\GraphQL\SafeException( 'NOT_LOGGED_IN', 'GQL/0001/6', 403 );
}
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'member_id=? AND access_token=?', \IPS\Member::loggedIn()->member_id, \IPS\Dispatcher::i()->accessToken['access_token'] ) );
\IPS\Db::i()->update( 'core_oauth_server_access_tokens', array( 'status' => 'revoked' ), array( 'member_id=? AND access_token=?', \IPS\Member::loggedIn()->member_id, \IPS\Dispatcher::i()->accessToken['access_token'] ) );
if ( isset( \IPS\Dispatcher::i()->accessToken['device_key'] ) )
{
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'member_id=? AND device_key=?', \IPS\Member::loggedIn()->member_id, \IPS\Dispatcher::i()->accessToken['device_key'] ) );
\IPS\Db::i()->update( 'core_oauth_server_access_tokens', array( 'status' => 'revoked' ), array( 'member_id=? AND device_key=?', \IPS\Member::loggedIn()->member_id, \IPS\Dispatcher::i()->accessToken['device_key'] ) );
}
if ( isset( $args['token'] ) and $args['token'] )
@@ -116,6 +116,11 @@ class _Unfollow
}
}
}
if ( !$class or !array_key_exists( $args['app'], \IPS\Application::applications() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NOT_FOUND', 'GQL/0001/7', 404 );
}
/* Get our return info ready */
$return = array(
@@ -131,11 +136,11 @@ class _Unfollow
{
if ( $class != "IPS\Member" )
{
$thing = $class::loadAndCheckPerms( $follow['follow_rel_id'] );
$thing = $class::loadAndCheckPerms( (int) $follow['follow_rel_id'] );
}
else
{
$thing = $class::load( $follow['follow_rel_id'] );
$thing = $class::load( (int) $follow['follow_rel_id'] );
}
/* Unfollow club areas */
@@ -116,7 +116,7 @@ class _UploadAttachment
$file = \IPS\File::get( 'core_Attachment', $url );
/* If it's got an image extension, check it's actually a valid image */
if ( \in_array( $ext, \IPS\Image::$imageExtensions ) )
if ( \in_array( $ext, \IPS\Image::supportedExtensions() ) )
{
try
{
@@ -142,7 +142,7 @@ class _UploadAttachment
else
{
/* If it's got an image extension, check it's actually a valid image */
if ( \in_array( $ext, \IPS\Image::$imageExtensions ) )
if ( \in_array( $ext, \IPS\Image::supportedExtensions() ) )
{
try
{
@@ -0,0 +1,61 @@
<?php
/**
* @brief GraphQL: Stats query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 21 Sept 2020
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Stats query for GraphQL API
*/
class _Stats
{
/*
* @brief Query description
*/
public static $description = "Returns community stats";
/*
* Query arguments
*/
public function args()
{
return array();
}
/**
* Return the query return type
*/
public function type()
{
return \IPS\core\api\GraphQL\TypeRegistry::stats();
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\core\Stream
*/
public function resolve($val, $args, $context)
{
return $val;
}
}
+1
View File
@@ -52,6 +52,7 @@ abstract class _Query
'popularContributors' => new \IPS\core\api\GraphQL\Queries\PopularContributors(),
'search' => new \IPS\core\api\GraphQL\Queries\Search(),
'settings' => new \IPS\core\api\GraphQL\Queries\Settings(),
'stats' => new \IPS\core\api\GraphQL\Queries\Stats(),
'stream' => new \IPS\core\api\GraphQL\Queries\Stream(),
'streams' => new \IPS\core\api\GraphQL\Queries\Streams(),
];
@@ -58,6 +58,7 @@ class _TypeRegistry
protected static $reportReason;
protected static $search;
protected static $searchResult;
protected static $stats;
protected static $stream;
protected static $tag;
protected static $settings;
@@ -319,6 +320,14 @@ class _TypeRegistry
return self::$search ?: (self::$search = new \IPS\core\api\GraphQL\Types\SearchType());
}
/**
* @return StatsType
*/
public static function stats()
{
return self::$stats ?: (self::$stats = new \IPS\core\api\GraphQL\Types\StatsType());
}
/**
* @return StreamType
*/
@@ -79,7 +79,7 @@ class _MemberType extends ObjectType
'type' => TypeRegistry::string(),
'description' => "Returns the member's title",
'resolve' => function( $member, $args, $context, $info ) {
return $member->member_title;
return null;
}
],
'timezone' => [
@@ -97,9 +97,6 @@ class _SettingsType extends ObjectType
'allow_reg_target' => [
'type' => TypeRegistry::string()
],
'disable_anonymous' => [
'type' => TypeRegistry::boolean()
],
'allow_result_view' => [
'type' => TypeRegistry::boolean()
],
@@ -0,0 +1,148 @@
<?php
/**
* @brief GraphQL: Stats Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 21 Sep 2020
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* StatsType for GraphQL API
*/
class _StatsType extends ObjectType
{
/**
* Get object type
*
* @return ObjectType
*/
public function __construct()
{
$config = [
'name' => 'core_Stats',
'description' => 'Statistics',
'fields' => function () {
return [
'contentCount' => [
'type' => TypeRegistry::int(),
'description' => "Content count",
'resolve' => function () {
return ( isset( \IPS\Settings::i()->mobile_app_hide_stats ) && \IPS\Settings::i()->mobile_app_hide_stats ) ? NULL : static::getContentCount();
}
],
'memberCount' => [
'type' => TypeRegistry::int(),
'description' => 'Member count',
'resolve' => function () {
return ( isset( \IPS\Settings::i()->mobile_app_hide_stats ) && \IPS\Settings::i()->mobile_app_hide_stats ) ? NULL : static::getMemberCount();
}
]
];
}
];
parent::__construct($config);
}
protected static function getContentCount()
{
$cacheKey = 'content_count';
$total = 0;
try
{
return \IPS\Data\Cache::i()->getWithExpire( $cacheKey, TRUE );
}
catch( \OutOfRangeException $e ){}
foreach( \IPS\Application::enabledApplications() as $app )
{
foreach( $app->extensions( 'core', 'ContentRouter', TRUE, TRUE ) as $object )
{
foreach( $object->classes as $itemClass )
{
foreach( array( 'items', 'comments', 'reviews' ) as $type )
{
try
{
$classes = [];
switch ( $type )
{
case 'items':
$classes[] = $itemClass;
break;
case 'comments':
if ( isset( $itemClass::$commentClass ) )
{
$classes[] = $itemClass::$commentClass;
}
if ( isset( $itemClass::$archiveClass ) )
{
$classes[] = $itemClass::$archiveClass;
}
break;
case 'reviews':
if ( isset( $itemClass::$reviewClass ) )
{
$classes[] = $itemClass::$reviewClass;
}
break;
}
if ( $classes )
{
foreach ( $classes as $class )
{
$where = method_exists( $class, 'digestWhere' ) ? $class::digestWhere() : [];
if ( isset( $class::$databaseColumnMap['approved'] ) )
{
$where[] = [ $class::$databasePrefix . $class::$databaseColumnMap['approved'] . '=1' ];
}
if ( isset( $class::$databaseColumnMap['hidden'] ) )
{
$where[] = [ $class::$databasePrefix . $class::$databaseColumnMap['hidden'] . '=0' ];
}
$total += $class::db()->select( 'COUNT(*)', $class::$databaseTable, $where )->first();
}
}
}
catch( \Exception $e ){}
}
}
}
}
\IPS\Data\Cache::i()->storeWithExpire( $cacheKey, $total, \IPS\DateTime::create()->add( new \DateInterval('P1W') ), TRUE );
return $total;
}
protected static function getMemberCount()
{
try
{
$memberCount = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'completed=?', true ) )->first();
return $memberCount;
}
catch ( \Exception $e )
{
return NULL;
}
}
}