Version 4.7.6

This commit is contained in:
Neo committed 2025-12-19 16:05:19 -08:00
1 parent 8ba7d43898
commit 7b7404e741
1085 files changed
+30590 -7837

No files matched your search

+75 -82
View File
@@ -110,16 +110,30 @@ class _Member extends \IPS\Patterns\ActiveRecord
'created_externally' => 16384,
'is_support_account' => 32768, // Created by ACP support tool
'is_anon' => 65536, // Has chosen to log in anonymously
'has_new_acp_features' => 131072,
// 131072 (has_new_acp_features) is deprecated
'password_reset_forced' => 262144, // A password reset has been forced
'link_pref_unread' => 524288, // Take me to comments I haven't read
'link_pref_last' => 1048576, // Take me to the latest comment
'mobile_notifications' => 2097152, // Has the user has enabled push notifications on at least 1 mobile device?
'link_pref_first' => 4194304, // Take me to the first comment
'datalayer_event_fired' => 8388608,
'new_device_email' => 16777216, // Send an email when a new device is used to log in.
'no_solved_reenage' => 33554432, // User does not want to get topic re-engagement emails
)
)
);
/**
* Member Changes to skip for the member_edited webhook
*
* @var string[]
*/
public static $changesToSkipForMemberEditWebhooks = [
'last_visit',
'last_activity',
'profilesync_lastsync',
];
/* !Follow */
@@ -158,7 +172,14 @@ class _Member extends \IPS\Patterns\ActiveRecord
/* If we haven't loaded the member yet, or if the session member has changed since we last loaded the member, reload and cache */
if( static::$loggedInMember === NULL )
{
static::$loggedInMember = \IPS\Session::i()->member;
if( \IPS\Request::isCliEnvironment() )
{
static::$loggedInMember = new \IPS\Member;
}
else
{
static::$loggedInMember = \IPS\Session::i()->member;
}
if ( isset( $_SESSION['logged_in_as_key'] ) )
{
@@ -288,6 +309,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
$this->members_bitoptions['view_sigs'] = TRUE;
}
$this->members_bitoptions['new_device_email'] = TRUE;
$this->members_bitoptions['show_pm_popup'] = ( \IPS\Settings::i()->notification_prefs_popup ) ? TRUE : FALSE;
$this->members_bitoptions['email_notifications_once'] = ( \IPS\Settings::i()->notification_prefs_one_per_view ) ? TRUE : FALSE;
@@ -398,6 +420,8 @@ class _Member extends \IPS\Patterns\ActiveRecord
elseif( !$this->completed AND $this->name AND $this->email )
{
$this->completed = TRUE;
\IPS\Api\Webhook::fire( 'member_registration_complete', $this, $this->webhookFilters() );
}
}
@@ -1848,79 +1872,6 @@ class _Member extends \IPS\Patterns\ActiveRecord
{
return $this->acpRestrictions() !== FALSE;
}
/**
* @brief Feature highlight cache
*/
protected $_features = NULL;
/**
* Get unread feature highlights
*
* @param bool $markRead Mark returned features as read? Useful for debugging.
* @return array|NULL
*/
public function getFeatureHighlights( bool $markRead = TRUE ): ?array
{
if ( $this->members_bitoptions['is_support_account'] )
{
/* Support account doesn't need these. */
return NULL;
}
if ( !$this->members_bitoptions['has_new_acp_features'] )
{
/* No new features to see */
return NULL;
}
/* Compile all unread features */
if ( $this->_features === NULL )
{
$this->_features = array();
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members_features', array( \IPS\Db::i()->in( 'feature_id', $this->getFeatureReadIds(), true ) ) ), 'IPS\Application\Feature' ) AS $feature )
{
$this->_features[] = $feature;
}
}
if ( \count( $this->_features ) )
{
/* Mark them as read */
if ( $markRead === TRUE )
{
/* Only set the flag if we're actually marking them as read. */
$this->members_bitoptions['has_new_acp_features'] = FALSE;
$this->save();
\IPS\Application\Feature::markRead( $this, ...$this->_features );
}
return $this->_features;
}
else
{
/* Even if we aren't marking them as read, there are none anyway, so just reset the flag. */
$this->members_bitoptions['has_new_acp_features'] = FALSE;
$this->save();
return NULL;
}
}
/**
* Get read feature ID's
*
* @return array
*/
protected function getFeatureReadIds(): array
{
$return = array();
foreach( \IPS\Db::i()->select( 'feature_id', 'core_members_feature_seen', array( "member_id=?", $this->member_id ) ) AS $id )
{
$return[] = $id;
}
return $return;
}
/**
* @brief Cache the session data if we pull it for location, etc.
@@ -3101,7 +3052,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
/**
* Moderator Permissions
*
* @return array
* @return array|false
*/
public function modPermissions()
{
@@ -3210,18 +3161,16 @@ class _Member extends \IPS\Patterns\ActiveRecord
{
if ( $this->reportCount === NULL OR $force === TRUE )
{
if ( \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'core', 'modcp' ) ) )
if ( $this->canAccessModule( \IPS\Application\Module::get( 'core', 'modcp' ) ) )
{
if( !\IPS\Member::loggedIn()->members_bitoptions['no_report_count'] OR $force === TRUE )
if( !$this->members_bitoptions['no_report_count'] OR $force === TRUE )
{
$where = '( perm_id IN (?) OR perm_id IS NULL ) AND status IN( 1,2 )';
$where = [ \IPS\core\Reports\Report::where( $this ), [ 'status IN( 1,2 )' ] ];
/* fetch only reports for content of enabled applications */
$where .= " AND " . \IPS\Db::i()->in( 'class', array_merge( array( 'IPS\core\Messenger\Conversation', 'IPS\core\Messenger\Message' ), array_values( \IPS\Content::routedClasses( FALSE, TRUE ) ) ) );
$reportCount = \IPS\Db::i()->select(
'COUNT(*)',
'core_rc_index',
array( $where, \IPS\Db::i()->select( 'perm_id', 'core_permission_index', \IPS\Db::i()->findInSet( 'perm_view', $this->permissionArray() ) . " OR perm_view='*'" ) )
$where
)->first();
if( $force === FALSE )
@@ -3491,6 +3440,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
* @apiresponse [\IPS\core\Achievements\Rank] rank Rank
* @apiresponse int achievements_points Points
* @apiresponse bool allowAdminEmails Whether or not this member wants to receive admin emails
* @apiresponse bool completed Whether or not the registration is completed
*/
public function apiOutput( \IPS\Member $authorizedMember = NULL, $otherFields = NULL )
{
@@ -3592,6 +3542,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
$return['rank'] = $this->rank() ? $this->rank()->apiOutput( $authorizedMember ) : NULL;
$return['achievements_points'] = $this->achievements_points;
$return['allowAdminEmails'] = (bool) $this->allow_admin_emails;
$return['completed'] = (bool) $this->completed;
return $return;
}
@@ -4380,6 +4331,23 @@ class _Member extends \IPS\Patterns\ActiveRecord
return TRUE;
}
/**
* Can use the messenger system
*
* @return bool
*/
public function canUseMessenger(): bool
{
/* Test member */
if ( $this->members_disable_pm == 2 )
{
return false;
}
/* Test module permissions */
return $this->canAccessModule( \IPS\Application\Module::get( 'core', 'messaging' ) );
}
/**
* Get a unique member hash for use in RSS keys and such.
*
@@ -6051,6 +6019,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
'action_log'=> $logId,
'actor' => implode( ',', $actor ),
'new_rank' => $newRank ? $newRank->id : NULL,
'time_to_new_rank' => $newRank ? time() - $this->joined->getTimestamp() : NULL,
'recognize' => $recognize
], FALSE, TRUE );
@@ -6193,4 +6162,28 @@ class _Member extends \IPS\Patterns\ActiveRecord
}
catch( \Exception $e ) { }
}
/**
* Webhook filters
*
* @return array
*/
public function webhookFilters() : array
{
return [
'completed' => $this->completed,
'allowAdminEmails' => $this->allow_admin_emails,
];
}
/**
* Get unread feature highlights
*
* @param bool $markRead Mark returned features as read? Useful for debugging.
* @return array|NULL
*/
public function getFeatureHighlights( bool $markRead = TRUE ): ?array
{
return NULL;
}
}