Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
+219
-38
@@ -115,7 +115,8 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
'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
|
||||
'link_pref_first' => 4194304, // Take me to the first comment
|
||||
'datalayer_event_fired' => 8388608,
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -289,7 +290,6 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
$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;
|
||||
$this->members_bitoptions['disable_notification_sounds'] = ( \IPS\Settings::i()->notification_prefs_sound ) ? FALSE : TRUE;
|
||||
|
||||
$this->_data['auto_track'] = json_encode( array(
|
||||
'content' => \IPS\Settings::i()->auto_follow_new_content ? 1 : 0,
|
||||
@@ -342,7 +342,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
\IPS\core\AdminNotification::remove( 'core', 'NewRegValidate' );
|
||||
}
|
||||
if ( $latestReg = \IPS\Db::i()->select( 'MAX(joined)', 'core_members', array( 'email<>?', '' ) )->first() )
|
||||
if ( $latestReg = \IPS\Db::i()->select( 'joined', 'core_members', array( 'email != ?', '' ), 'joined DESC', 1 )->first() )
|
||||
{
|
||||
\IPS\core\AdminNotification::remove( 'core', 'NewRegComplete', NULL, \IPS\DateTime::ts( $latestReg ) );
|
||||
}
|
||||
@@ -413,7 +413,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
else
|
||||
{
|
||||
/* Run member sync, but not if the only change is the last_activity timestamp */
|
||||
if( \count( $this->changedCustomFields ) > 0 or \count( $changes ) > 1 OR !isset( $changes['last_activity'] ) )
|
||||
if( \count( $this->changedCustomFields ) > 0 OR ( \count( $changes ) > 0 AND !( \count( $changes ) === 1 AND isset( $changes['last_activity'] ) ) ) )
|
||||
{
|
||||
$this->memberSync( 'onProfileUpdate', array( 'changes' => array_merge( $changes, $this->changedCustomFields ) ) );
|
||||
}
|
||||
@@ -513,7 +513,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('guest');
|
||||
}
|
||||
|
||||
return $this->member_id ? $this->_data['name'] : \IPS\Member::loggedIn()->language()->addToStack( 'guest_name_shown', NULL, array( 'sprintf' => array( $this->_data['name'] ) ) );
|
||||
return $this->member_id ? $this->_data['name'] : \IPS\Member::loggedIn()->language()->addToStack( 'guest_name_shown', FALSE, array( 'sprintf' => array( $this->_data['name'] ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1664,12 +1664,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
*/
|
||||
public function get_timezone()
|
||||
{
|
||||
if ( \in_array( $this->_data['timezone'], [ 'America/Buenos_Aires', 'America/Catamarca', 'America/Cordoba', 'America/Jujuy', 'America/La_Rioja', 'America/Mendoza', 'America/Rio_Gallegos', 'America/Salta', 'America/San_Juan', 'America/San_Luis', 'America/Tucuman', 'America/Ushuaia' ] ) ) // https://bugs.webkit.org/show_bug.cgi?id=218542
|
||||
{
|
||||
return 'America/Argentina/' . \substr( $this->_data['timezone'], 8 );
|
||||
}
|
||||
|
||||
return $this->_data['timezone'];
|
||||
return \IPS\DateTime::getFixedTimezone( $this->_data['timezone'] );
|
||||
}
|
||||
|
||||
/* !Photos */
|
||||
@@ -1974,6 +1969,13 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If the group is forced to be anonymous */
|
||||
if( $this->group['g_hide_online_list'] == 1 )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Anonymous status is not allowed */
|
||||
if( $this->group['g_hide_online_list'] == 2 )
|
||||
{
|
||||
return FALSE;
|
||||
@@ -2193,9 +2195,10 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
* Profile Fields
|
||||
*
|
||||
* @param int $location \IPS\core\ProfileFields\Field::PROFILE for profile, \IPS\core\ProfileFields\Field::REG for registration screen, \IPS\core\ProfileFields\Field::STAFF for ModCP/ACP, \IPS\core\ProfileFields\Field::EDIT for member editing
|
||||
* @param bool $raw Returns the raw value if true or the display value if false. Useful for comparisons for field types like Yes/NO to see if a value is set.
|
||||
* @return array
|
||||
*/
|
||||
public function profileFields( $location = 0 )
|
||||
public function profileFields( $location = 0, $raw = FALSE )
|
||||
{
|
||||
if ( !$this->member_id )
|
||||
{
|
||||
@@ -2218,7 +2221,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
if( !empty( $values ) )
|
||||
{
|
||||
foreach ( \IPS\core\ProfileFields\Field::values( $values, $location ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::values( $values, $location, $raw ) as $group => $fields )
|
||||
{
|
||||
$this->rawProfileFieldsData[ 'core_pfieldgroups_' . $group ] = $fields;
|
||||
}
|
||||
@@ -2784,7 +2787,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
*/
|
||||
public function passwordResetForced( ?\IPS\Http\Url $ref = NULL ): ?\IPS\Http\Url
|
||||
{
|
||||
if ( $this->members_bitoptions['password_reset_forced'] AND $this->members_pass_hash )
|
||||
if ( $this->members_bitoptions['password_reset_forced'] AND !$this->members_pass_hash )
|
||||
{
|
||||
return \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=password', 'front', 'settings_password' )->setQueryString( 'ref', base64_encode( $ref ) );
|
||||
}
|
||||
@@ -2797,6 +2800,8 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
* @note This property is public so it can be populated en-masse in areas that may benefit from doing so
|
||||
*/
|
||||
public $notificationsConfiguration = NULL;
|
||||
|
||||
static protected $extCache = [];
|
||||
|
||||
/**
|
||||
* Notifications Configuration
|
||||
@@ -2808,6 +2813,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
if( $this->notificationsConfiguration === NULL )
|
||||
{
|
||||
$this->notificationsConfiguration = array();
|
||||
$defaultNotifications = [];
|
||||
|
||||
foreach (
|
||||
\IPS\Db::i()->select(
|
||||
@@ -2821,13 +2827,52 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
) {
|
||||
if ( $row['preference'] === NULL or !$row['editable'] )
|
||||
{
|
||||
$this->notificationsConfiguration[ $row['notification_key'] ] = explode( ',', $row['default'] );
|
||||
$defaultNotifications[ $row['notification_key'] ] = explode( ',', $row['default'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->notificationsConfiguration[ $row['notification_key'] ] = array_diff( explode( ',', $row['preference'] ), explode( ',', $row['disabled'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Only cycle through if this member has any non-default notifications */
|
||||
if( \count( $this->notificationsConfiguration ) )
|
||||
{
|
||||
/* Cache extension references */
|
||||
if ( !\count( static::$extCache ) )
|
||||
{
|
||||
static::$extCache = \IPS\Application::allExtensions( 'core', 'Notifications' );
|
||||
}
|
||||
|
||||
foreach ( $defaultNotifications as $k => $v )
|
||||
{
|
||||
foreach ( static::$extCache as $extension )
|
||||
{
|
||||
if ( method_exists( $extension, 'configurationOptions' ) )
|
||||
{
|
||||
foreach ( $extension->configurationOptions( null ) as $optionKey => $option )
|
||||
{
|
||||
if ( $option['type'] == 'standard' and \in_array( $k, $option['notificationTypes'] ) and \count( $option['notificationTypes'] ) > 1 )
|
||||
{
|
||||
if ( !empty( $this->notificationsConfiguration[ $option['notificationTypes'][0] ] ) )
|
||||
{
|
||||
$defaultNotifications[ $k ] = $this->notificationsConfiguration[ $option['notificationTypes'][0] ];
|
||||
\IPS\Db::i()->insert( 'core_notification_preferences', [
|
||||
'member_id' => $this->member_id,
|
||||
'notification_key' => $k,
|
||||
'preference' => implode( ',', $this->notificationsConfiguration[ $option['notificationTypes'][0] ] )
|
||||
] );
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->notificationsConfiguration = array_merge( $this->notificationsConfiguration, $defaultNotifications );
|
||||
}
|
||||
|
||||
return $this->notificationsConfiguration;
|
||||
@@ -3027,7 +3072,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( ! \in_array( $this->member_id, static::$modBadge ) )
|
||||
if ( ! array_key_exists( $this->member_id, static::$modBadge ) )
|
||||
{
|
||||
static::$modBadge[ $this->member_id ] = false;
|
||||
|
||||
@@ -3445,6 +3490,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
* @apiresponse [\IPS\core\ProfileFields\Api\FieldGroup] customFields Custom profile fields. For requests using an OAuth Access Token for a particular member, only fields the authorized user can view will be included
|
||||
* @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
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL, $otherFields = NULL )
|
||||
{
|
||||
@@ -3545,6 +3591,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 $return;
|
||||
}
|
||||
@@ -3941,7 +3988,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'spam-service' );
|
||||
\IPS\Log::debug( $e, 'spam-service' );
|
||||
$spamCode = 0;
|
||||
}
|
||||
|
||||
@@ -4332,6 +4379,42 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a unique member hash for use in RSS keys and such.
|
||||
*
|
||||
* If the member has a current style password hash, the md5() of that value will be returned. Otherwise,
|
||||
* one will be generated, stored in a new column in the members table, and its md5() will be returned.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniqueMemberHash()
|
||||
{
|
||||
/* If this is a guest, just return a random string. */
|
||||
if ( !$this->member_id )
|
||||
{
|
||||
return \IPS\Login::generateRandomString();
|
||||
}
|
||||
|
||||
/* Return the password hash if we already have it */
|
||||
if ( !empty( $this->members_pass_hash ) )
|
||||
{
|
||||
return md5( ( $this->members_pass_hash ?: $this->email ) . $this->members_pass_salt );
|
||||
}
|
||||
|
||||
/* Do we already have one? */
|
||||
if ( !empty( $this->unique_hash ) )
|
||||
{
|
||||
return $this->unique_hash;
|
||||
}
|
||||
|
||||
/* Otherwise, generate one */
|
||||
$this->unique_hash = md5( \IPS\Login::generateRandomString(32) );
|
||||
|
||||
$this->save();
|
||||
|
||||
return $this->unique_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a database update on all members
|
||||
@@ -5135,11 +5218,11 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
if ( $item::$firstCommentRequired and isset( $commentClass::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$filters[ $commentClass ] = \IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_x', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$commentClass::$title}_pl_lc") ) ) );
|
||||
$filters[ $commentClass ] = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_tab_x', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$commentClass::$title}_pl_lc") ) ) );
|
||||
}
|
||||
elseif ( isset( $item::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$filters[ $item ] = \IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_x', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$item::$title}_pl_lc") ) ) );
|
||||
$filters[ $item ] = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_tab_x', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$item::$title}_pl_lc") ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5566,7 +5649,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\DateTime::ts( \IPS\Db::i()->select( 'datetime', 'core_points_log', [ 'member=? AND new_rank=?', $this->member_id, $rank->id ], 'datetime DESC', 1 )->first() );
|
||||
return \IPS\DateTime::ts( \IPS\Db::i()->select( 'datetime', 'core_points_log', [ '`member`=? AND new_rank=?', $this->member_id, $rank->id ], 'datetime DESC', 1 )->first() );
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
@@ -5602,7 +5685,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
if ( ! $this->rankHistory )
|
||||
{
|
||||
$return = [ 'earned' => NULL, 'not_earned' => NULL ];
|
||||
$query = iterator_to_array( \IPS\Db::i()->select( 'new_rank, datetime', 'core_points_log', ['member=? and new_rank IS NOT NULL', $this->member_id] )->setKeyField('new_rank')->setValueField('datetime') );
|
||||
$query = iterator_to_array( \IPS\Db::i()->select( 'new_rank, datetime', 'core_points_log', ['`member`=? and new_rank IS NOT NULL', $this->member_id] )->setKeyField('new_rank')->setValueField('datetime') );
|
||||
$currentRank = $this->rank();
|
||||
|
||||
foreach ( \IPS\core\Achievements\Rank::getStore() as $rank )
|
||||
@@ -5627,6 +5710,30 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return $this->rankHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of days since the last rank upgrade
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function daysSinceLastRank(): int
|
||||
{
|
||||
$history = $this->rankHistory();
|
||||
$lastRank = NULL;
|
||||
|
||||
foreach( $history['earned'] as $earned )
|
||||
{
|
||||
if ( $earned['rank']->id == $this->rank()->id )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$lastRank = $earned;
|
||||
}
|
||||
|
||||
$time = ( $lastRank and $lastRank['time'] ) ? $lastRank['time'] : $this->joined;
|
||||
return \intval( \IPS\DateTime::ts( time() )->diff( $time )->days );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief List of badge IDs that this member has earned
|
||||
*/
|
||||
@@ -5641,7 +5748,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
if ( $this->_badgeIds === NULL )
|
||||
{
|
||||
$this->_badgeIds = iterator_to_array( \IPS\Db::i()->select( 'badge', 'core_member_badges', [ 'member=?', $this->member_id ] ) );
|
||||
$this->_badgeIds = iterator_to_array( \IPS\Db::i()->select( 'badge', 'core_member_badges', [ '`member`=?', $this->member_id ] ) );
|
||||
}
|
||||
return $this->_badgeIds;
|
||||
}
|
||||
@@ -5660,7 +5767,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
if ( $this->_badgeCount === NULL )
|
||||
{
|
||||
$this->_badgeCount = \IPS\Db::i()->select( 'count(*)', 'core_member_badges', [ 'member=?', $this->member_id ] )->first();
|
||||
$this->_badgeCount = \IPS\Db::i()->select( 'count(*)', 'core_member_badges', [ '`member`=?', $this->member_id ] )->first();
|
||||
}
|
||||
return $this->_badgeCount;
|
||||
}
|
||||
@@ -5674,7 +5781,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
public function recentBadges( $numberToGet ): \IPS\Patterns\ActiveRecordIterator
|
||||
{
|
||||
return new \IPS\Patterns\ActiveRecordIterator(
|
||||
\IPS\Db::i()->select( 'core_badges.*, core_member_badges.member, core_member_badges.badge, core_member_badges.datetime, core_member_badges.rule, core_member_badges.action_log, core_member_badges.actor, core_member_badges.recognize', 'core_member_badges', [ 'member=?', $this->member_id ], 'datetime DESC', $numberToGet )
|
||||
\IPS\Db::i()->select( 'core_badges.*, core_member_badges.member, core_member_badges.badge, core_member_badges.datetime, core_member_badges.rule, core_member_badges.action_log, core_member_badges.actor, core_member_badges.recognize', 'core_member_badges', [ '`member`=?', $this->member_id ], 'datetime DESC', $numberToGet )
|
||||
->join( 'core_badges', 'core_member_badges.badge=core_badges.id' ),
|
||||
'IPS\core\Achievements\Badge'
|
||||
);
|
||||
@@ -5697,9 +5804,14 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( ! $this->member_id )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( static::$rulesExcluded === NULL )
|
||||
{
|
||||
static::$rulesExcluded = json_decode( \IPS\Settings::i()->rules_exclude_groups, TRUE );;
|
||||
static::$rulesExcluded = json_decode( \IPS\Settings::i()->rules_exclude_groups, TRUE );
|
||||
}
|
||||
|
||||
if ( ! \is_array( static::$rulesExcluded ) or ! \count( static::$rulesExcluded ) )
|
||||
@@ -5740,6 +5852,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
if ( $enabled === TRUE )
|
||||
{
|
||||
$extensionObject = \IPS\Application::load( $app )->extensions( 'core', 'AchievementAction' )[$extension];
|
||||
|
||||
/* Log it first, because doing so allows us to tell if we have already ran the rules
|
||||
for this action (e.g. if someone unlikes and relikes a post, we don't want to keep
|
||||
doing the actions for that every time: only once) */
|
||||
@@ -5753,9 +5866,15 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* There are no enabled rules with this extension */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Work out what we have to dish out */
|
||||
$awards = [];
|
||||
$milestoneHitWithRules = [];
|
||||
foreach ( \IPS\core\Achievements\Rule::getStore()["{$app}_{$extension}"] as $ruleId => $ruleData )
|
||||
{
|
||||
if ( ! $ruleData['enabled'] )
|
||||
@@ -5764,9 +5883,20 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
|
||||
if ( !$ruleData['filters'] or $extensionObject->filtersMatch( $this, $ruleData['filters'], $extra ) )
|
||||
{
|
||||
{
|
||||
/* Did we already award for this milestone? */
|
||||
if ( \IPS\core\Achievements\Rule::ruleHasMilestone( $ruleData['filters'] ) )
|
||||
{
|
||||
$milestoneHitWithRules[ $ruleId ] = [];
|
||||
}
|
||||
|
||||
if ( $ruleData['points_subject'] or $ruleData['badge_subject'] )
|
||||
{
|
||||
if ( array_key_exists( $ruleId, $milestoneHitWithRules ) )
|
||||
{
|
||||
$milestoneHitWithRules[ $ruleId ][ 'subject-' . $this->member_id ] = 'subject-' . $this->member_id;
|
||||
}
|
||||
|
||||
if ( !isset( $awards[ $this->member_id ] ) )
|
||||
{
|
||||
$awards[ $this->member_id ] = [ 'points' => [], 'badges' => [], 'actor' => [] ];
|
||||
@@ -5782,10 +5912,10 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
$awards[ $this->member_id ]['badges'][ $ruleId ] = $ruleData['badge_subject'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( $ruleData['points_other'] or $ruleData['badge_other'] )
|
||||
{
|
||||
foreach ( $extensionObject->awardOther( $extra ) as $member )
|
||||
foreach ( $extensionObject->awardOther( $extra, $ruleData['filters'] ) as $member )
|
||||
{
|
||||
/* If the "other" member is also the subject member (e.g. member is replying to their own topic), we
|
||||
only give them the "subject" points */
|
||||
@@ -5793,7 +5923,12 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if ( array_key_exists( $ruleId, $milestoneHitWithRules ) )
|
||||
{
|
||||
$milestoneHitWithRules[ $ruleId ][ 'other-' . $member->member_id ] = 'other-' . $member->member_id;
|
||||
}
|
||||
|
||||
/* Otherwise carry on as usual... */
|
||||
if ( !isset( $awards[ $member->member_id ] ) )
|
||||
{
|
||||
@@ -5804,7 +5939,7 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
$awards[ $member->member_id ]['actor']['other'] = 'other';
|
||||
$awards[ $member->member_id ]['points'][ $ruleId ] = $ruleData['points_other'];
|
||||
}
|
||||
if ( $ruleData['badge_subject'] and !\in_array( $ruleData['badge_subject'], $member->badgeIds() ) )
|
||||
if ( $ruleData['badge_other'] and !\in_array( $ruleData['badge_other'], $member->badgeIds() ) )
|
||||
{
|
||||
$awards[ $member->member_id ]['actor']['other'] = 'other';
|
||||
$awards[ $member->member_id ]['badges'][ $ruleId ] = $ruleData['badge_other'];
|
||||
@@ -5813,25 +5948,61 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If we have stuff to dish out... */
|
||||
if ( $awards )
|
||||
{
|
||||
$alreadyHitMilestone = [];
|
||||
|
||||
/* Insert these milestone maps */
|
||||
foreach( $milestoneHitWithRules as $ruleId => $members )
|
||||
{
|
||||
foreach( $members as $data )
|
||||
{
|
||||
list( $type, $memberId ) = explode( '-', $data );
|
||||
$insertId = \IPS\Db::i()->insert( 'core_achievements_log_milestones', [
|
||||
'milestone_member_id' => $memberId,
|
||||
'milestone_rule' => $ruleId,
|
||||
'milestone_log_id' => $logId,
|
||||
'milestone_type' => $type,
|
||||
], FALSE, TRUE );
|
||||
|
||||
if ( ! $insertId )
|
||||
{
|
||||
$alreadyHitMilestone[ $memberId ][] = $ruleId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $awards as $memberId => $memberAwards )
|
||||
{
|
||||
if ( $memberAwards['points'] )
|
||||
{
|
||||
\IPS\Member::load( $memberId )->awardPoints( array_sum( $memberAwards['points'] ), $logId, array_keys( $memberAwards['points'] ), $memberAwards['actor'], 0, $date );
|
||||
foreach( $memberAwards['points'] as $ruleId => $data )
|
||||
{
|
||||
if ( isset( $alreadyHitMilestone[ $memberId ] ) and \in_array( $ruleId, $alreadyHitMilestone[ $memberId ] ) )
|
||||
{
|
||||
unset( $memberAwards['points'][ $ruleId ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \array_key_exists( 'points', $memberAwards ) and \count( $memberAwards['points'] ) )
|
||||
{
|
||||
\IPS\Member::load( $memberId )->awardPoints( array_sum( $memberAwards['points'] ), $logId, array_keys( $memberAwards['points'] ), $memberAwards['actor'], 0, $date );
|
||||
}
|
||||
}
|
||||
if ( $memberAwards['badges'] )
|
||||
{
|
||||
foreach ( array_unique( $memberAwards['badges'] ) as $ruleId => $badgeId )
|
||||
{
|
||||
try
|
||||
if ( ! isset( $alreadyHitMilestone[ $memberId ] ) or ! \in_array( $ruleId, $alreadyHitMilestone[ $memberId ] ) )
|
||||
{
|
||||
\IPS\Member::load( $memberId )->awardBadge( \IPS\core\Achievements\Badge::load( $badgeId ), $logId, $ruleId, $memberAwards['actor'], 0, $date );
|
||||
try
|
||||
{
|
||||
\IPS\Member::load( $memberId )->awardBadge( \IPS\core\Achievements\Badge::load( $badgeId ), $logId, $ruleId, $memberAwards['actor'], 0, $date );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5886,10 +6057,12 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
/* Did that push them over threshold for a new rank? Don't send a notification if rebuilds are in progress, and a random post made live triggers a new badge or award */
|
||||
if ( $newRank and ! \IPS\Settings::i()->achievements_rebuilding )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'new_rank', $this, [ $this ], [ $newRank->id ] );
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'new_rank', $this, [ $newRank, $this ], [ $newRank->id ] );
|
||||
$notification->recipients->attach( $this );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
$this->save();
|
||||
|
||||
if ( isset( static::$_memberRecognizedPoints[ $this->member_id ] ) )
|
||||
{
|
||||
@@ -5932,10 +6105,18 @@ class _Member extends \IPS\Patterns\ActiveRecord
|
||||
/* Don't send a notification if rebuilds are in progress, and a random post made live triggers a new badge or award */
|
||||
if ( ! \IPS\Settings::i()->achievements_rebuilding )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'new_badge', $this, [$badge], [$badge->id] );
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'new_badge', $this, [ $this, $badge ], [ $badge->id ] );
|
||||
$notification->recipients->attach( $this );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
$data = [
|
||||
'member' => $this->apiOutput(),
|
||||
'badge' => $badge->apiOutput(),
|
||||
];
|
||||
|
||||
\IPS\Api\Webhook::fire( 'member_badge_awarded', $data );
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public static $_memberRecognizedPoints = array();
|
||||
|
||||
Reference in new issue
Block a user