Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

@@ -50,6 +50,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_profile.js', 'core' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_statuses.js', 'core' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_core.js', 'core', 'global' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/profiles.css' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams.css' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/leaderboard.css' ) );
@@ -57,7 +58,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
if ( \IPS\Theme::i()->settings['responsive'] )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/profiles_responsive.css' ) );
}
}
}
/* Go */
@@ -103,9 +104,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$canAccessStatuses = $canAccessSingleStatuses and ( $this->member->pp_setting_count_comments or \IPS\Member::loggedIn()->member_id == $this->member->member_id );
/* Are we loading a different page of comments? */
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->page && $canAccessStatuses )
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->page && $canAccessStatuses && !isset( \IPS\Request::i()->getUploader ) )
{
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
try
{
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
}
catch( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2C138/M', 404, '' );
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'statuses' )->statusReplies( $status );
return;
}
@@ -167,11 +176,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
else
{
/* What tabs are available? */
$tabs = array( 'activity' => 'users_activity_feed' );
if ( \IPS\Settings::i()->clubs )
if ( \IPS\Settings::i()->clubs and count( \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'created', $this->member ) ) )
{
$tabs['clubs'] = 'users_clubs';
}
@@ -279,7 +287,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$perPage = 24;
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
$allClubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), array( ( $page - 1 ) * $perPage, $perPage ), 'last_activity', $this->member );
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $allClubs->count( TRUE ) / $perPage ), $page, $perPage );
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ( ceil( is_object( $allClubs ) ? $allClubs->count( TRUE ) : 0 ) / $perPage ), $page, $perPage );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/clubs.css', 'core', 'front' ) );
if ( \IPS\Theme::i()->settings['responsive'] )
@@ -376,7 +384,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
'@context' => "http://schema.org",
'@type' => "ProfilePage",
'url' => (string) $this->member->url(),
'name' => htmlspecialchars( $this->member->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
'name' => $this->member->name,
'primaryImageOfPage' => array(
'@type' => "ImageObject",
'contentUrl' => (string) $this->member->get_photo(),
@@ -403,7 +411,9 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
),
),
);
\IPS\Output::i()->linkTags['canonical'] = (string) $this->member->url();
/* Output */
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_profile.js', 'core' ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->profile( $this->member, $mainContent, $visitors, $sidebarFields, $followers, $addWarningUrl );
@@ -439,15 +449,13 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
foreach( $router->classes as $class )
{
if( !isset( $class::$includeInUserProfiles ) OR !$class::$includeInUserProfiles )
{
continue;
}
/* Add CSS for this app */
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'profile.css', $class::$application ) );
$types[ $class::$application . '_' . $class::$module ][ mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) ) ] = $class;
if ( isset( $class::$databaseColumnMap['author'] ) )
{
$types[ $class::$application . '_' . $class::$module ][ mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) ) ] = $class;
}
$supportsComments = ( in_array( 'IPS\Content\Item', class_parents( $class ) ) and $class::supportsComments( \IPS\Member::loggedIn() ) );
if ( $supportsComments )
@@ -516,8 +524,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->redirect( \IPS\Request::i()->url()->setQueryString( 'page', $highestPage ?: 1 ), NULL, 303 );
}
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $this->member->url()->setQueryString( array( 'do' => 'content' ) ), ceil( $results->count( TRUE ) / $query->resultsToGet ), $page, $query->resultsToGet ) );
$output = \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination );
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $this->member->url()->setQueryString( array( 'do' => 'content', 'all_activity' => 1 ) ), ceil( $results->count( TRUE ) / $query->resultsToGet ), $page, $query->resultsToGet ) );
if ( \IPS\Request::i()->isAjax() AND \IPS\Request::i()->all_activity )
{
\IPS\Output::i()->json( array( 'rows' => \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination ) ) );
return;
}
else
{
$output = \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination );
}
}
else
{
@@ -667,9 +683,35 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
else
{
/* Get the reputation summary */
$reactions = array( 'given' => array(), 'received' => array() );
foreach( \IPS\Db::i()->select( 'reaction, COUNT(*) as count', 'core_reputation_index', array( 'member_id=?', $this->member->member_id ), NULL, NULL, 'reaction' ) as $reaction )
{
try
{
$object = \IPS\Content\Reaction::load( $reaction['reaction'] );
$reactions['given'][] = array( 'count' => $reaction['count'], 'reaction' => $object );
}
catch( \UnderflowException $e ){}
}
foreach( \IPS\Db::i()->select( 'reaction, COUNT(*) as count', 'core_reputation_index', array( 'member_received=?', $this->member->member_id ), NULL, NULL, 'reaction' ) as $reaction )
{
try
{
$object = \IPS\Content\Reaction::load( $reaction['reaction'] );
$reactions['received'][] = array( 'count' => $reaction['count'], 'reaction' => $object );
}
catch( \UnderflowException $e ){}
}
\IPS\Output::i()->title = ( $table->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'member_reputation_from', FALSE, array('sprintf' => $this->member->name ) ), $table->page ) ) ) : \IPS\Member::loggedIn()->language()->addToStack( 'member_reputation_from', FALSE, array('sprintf' => $this->member->name ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userReputation( $this->member, $types, $currentAppModule, $currentType, (string) $table );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userReputation( $this->member, $types, $currentAppModule, $currentType, (string) $table, $reactions );
}
}
@@ -741,7 +783,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
$form = new \IPS\Helpers\Form( 'form', 'status_save' );
$form->class = 'ipsForm_vertical';
$form->class = 'ipsForm_vertical ipsForm_noLabels';
$formElements = \IPS\core\Statuses\Status::formElements( $status );
$form->add( $formElements['status_content'] );
@@ -755,7 +797,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->redirect( $status->url() );
}
\IPS\Output::i()->output = $form;
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
}
catch ( \Exception $e )
{
@@ -763,6 +805,54 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
}
/**
* Edit Status Reply
*
* @return void
*/
protected function editStatusReply()
{
try
{
$reply = \IPS\core\Statuses\Reply::loadAndCheckPerms( \IPS\Request::i()->reply );
if ( !$reply->canEdit() )
{
throw new \DomainException;
}
$form = new \IPS\Helpers\Form;
$form->class = 'ipsForm_vertical';
$form->add( new \IPS\Helpers\Form\Editor( 'comment_value', $reply->content, TRUE, array(
'app' => 'core',
'key' => 'Members',
'autoSaveKey' => 'editComment-core/members-' . $reply->id,
'attachIds' => $reply->attachmentIds()
) ) );
if ( $values = $form->values() )
{
$reply->editContents( $values['comment_value'] );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->output = $reply->html();
return;
}
else
{
\IPS\Output::i()->redirect( $reply->url() );
}
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
}
catch( \Exception $e )
{
\IPS\Output::i()->error( 'node_error', '2C138/K', 404, '' );
}
}
/**
* Edit Profile
*
@@ -931,24 +1021,27 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$this->member->member_title = $values['member_title'];
}
if( $values['bday'] and ( ( $values['bday']['day'] and !$values['bday']['month'] ) or ( $values['bday']['month'] and !$values['bday']['day'] ) ) )
if( isset( $values['bday'] ) )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'bday_month_and_day_required' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->editContentForm( \IPS\Member::loggedIn()->language()->addToStack( 'profile_edit' ), $form );
return;
}
if( $values['bday'] and ( ( $values['bday']['day'] and !$values['bday']['month'] ) or ( $values['bday']['month'] and !$values['bday']['day'] ) ) )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'bday_month_and_day_required' );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->editContentForm( \IPS\Member::loggedIn()->language()->addToStack( 'profile_edit' ), $form );
return;
}
if ( $values['bday'] and $values['bday']['day'] and $values['bday']['month'] )
{
$this->member->bday_day = $values['bday']['day'];
$this->member->bday_month = $values['bday']['month'];
$this->member->bday_year = $values['bday']['year'];
}
else
{
$this->member->bday_day = NULL;
$this->member->bday_month = NULL;
$this->member->bday_year = NULL;
if ( $values['bday'] and $values['bday']['day'] and $values['bday']['month'] )
{
$this->member->bday_day = $values['bday']['day'];
$this->member->bday_month = $values['bday']['month'];
$this->member->bday_year = $values['bday']['year'];
}
else
{
$this->member->bday_day = NULL;
$this->member->bday_month = NULL;
$this->member->bday_year = NULL;
}
}
if ( isset( $values['enable_status_updates'] ) )
@@ -980,14 +1073,21 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
$profileFields = array();
}
$profileFields['member_id'] = $this->member->member_id;
foreach ( \IPS\core\ProfileFields\Field::fields( $profileFields, \IPS\core\ProfileFields\Field::PROFILE ) as $group => $fields )
{
foreach ( $fields as $id => $field )
{
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
if ( $field instanceof \IPS\Helpers\Form\Upload )
{
$profileFields[ "field_{$id}" ] = (string) $values[ $field->name ];
}
else
{
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
}
if ( $field instanceof \IPS\Helpers\Form\Editor )
{
@@ -1076,17 +1176,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
}
/* ProfileSync (Facebook, etc.) */
foreach ( \IPS\core\ProfileSync\ProfileSyncAbstract::services() as $key => $class )
{
$obj = new $class( $this->member );
if ( $obj->connected() )
{
$langKey = 'profilesync__' . $key;
$options[ 'sync-' . $key ] = \IPS\Member::loggedIn()->language()->addToStack( 'member_photo_sync' , FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $langKey ) ) ) );
}
}
/* And of course we can always not have a photo... except when we can't */
$photoRequired = FALSE;
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
@@ -1097,7 +1186,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
break;
}
}
if ( $photoRequired === FALSE )
{
$options['none'] = 'member_photo_none';
@@ -1116,7 +1204,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
if ( $photoVars[0] )
{
$form->add( new \IPS\Helpers\Form\Upload( 'member_photo_upload', NULL, FALSE, array( 'image' => array( 'maxWidth' => $photoVars[1], 'maxHeight' => $photoVars[2] ), 'storageExtension' => 'core_Profile', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL ), function( $val ) {
if ( $val instanceof \IPS\File )
{
$image = \IPS\Image::create( $val->contents() );
@@ -1128,7 +1215,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}, NULL, NULL, 'member_photo_upload' ) );
/* Create the URL */
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'image' => TRUE, 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), NULL, NULL, NULL, 'member_photo_url' ) );
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'image' => TRUE, 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), function( $val ) {
if ( $val instanceof \IPS\Http\Url )
{
$image = \IPS\Image::create( (string) $val->request()->get() );
if( $image->isAnimatedGif and !$this->member->group['g_upload_animated_photos'] )
{
throw new \DomainException('member_photo_upload_no_animated');
}
}
}, NULL, NULL, 'member_photo_url' ) );
}
/* Add additional elements */
@@ -1142,16 +1238,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
$this->member->pp_photo_type = $values['pp_photo_type'];
/* If we are changing our photo, it is safe to assume that any services currently set to sync should no longer do so */
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
if ( !empty( $services ) )
/* Disable syncing */
$profileSync = $this->member->profilesync;
if ( isset( $profileSync['photo'] ) )
{
foreach( $services AS $class )
{
$obj = new $class( $this->member );
$obj->save( array( 'profilesync_photo' => FALSE ) );
}
unset( $profileSync['photo'] );
$this->member->profilesync = $profileSync;
}
switch ( $values['pp_photo_type'] )
@@ -1197,14 +1289,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
case 'gravatar':
$this->member->pp_gravatar = ( !isset( $values['photo_gravatar_email_public'] ) or $values['photo_gravatar_email_public'] === $this->member->email ) ? NULL : $values['photo_gravatar_email_public'];
break;
default:
if ( mb_substr( $values['pp_photo_type'], 0, 5 ) === 'sync-' )
{
$class = 'IPS\core\ProfileSync\\' . mb_substr( $values['pp_photo_type'], 5 );
$obj = new $class( $this->member );
$obj->save( array( 'profilesync_photo' => TRUE ) );
}
}
/* Reset Profile Complete flag in case this was an optional step */
@@ -1212,6 +1296,15 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$this->member->save();
if ( $this->member->pp_photo_type )
{
$this->member->logHistory( 'core', 'photo', array( 'action' => 'new', 'type' => $this->member->pp_photo_type ) );
}
else
{
$this->member->logHistory( 'core', 'photo', array( 'action' => 'remove' ) );
}
if ( $this->member->pp_photo_type == 'custom' )
{
if ( \IPS\Request::i()->isAjax() )
@@ -1270,8 +1363,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
/* Get the photo */
$original = \IPS\File::get( 'core_Profile', $this->member->pp_main_photo );
$image = \IPS\Image::create( $original->contents() );
try
{
$original = \IPS\File::get( 'core_Profile', $this->member->pp_main_photo );
$image = \IPS\Image::create( $original->contents() );
}
catch( \Exception $e )
{
\IPS\Log::log( $e, 'crop_error' );
\IPS\Output::i()->error( 'no_photo_to_crop', '3C138/N', 404, '' );
}
/* Work out which dimensions to suggest */
if ( $image->width < $image->height )
@@ -1290,7 +1392,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$form->add( new \IPS\Helpers\Form\Custom('photo_crop', array( 0, 0, $suggestedWidth, $suggestedHeight ), FALSE, array(
'getHtml' => function( $field ) use ( $original, $member )
{
return \IPS\Theme::i()->getTemplate('profile')->photoCrop( $field->name, $field->value, $member->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
return \IPS\Theme::i()->getTemplate('members', 'core', 'global')->photoCrop( $field->name, $field->value, $member->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
}
) ) );
@@ -1328,7 +1430,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
catch ( \Exception $e )
{
$form->error = 'photo_crop_bad';
$form->error = \IPS\Member::loggedIn()->language()->addToStack('photo_crop_bad');
}
}
@@ -1485,7 +1587,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$tabs['all'] = \IPS\Member::loggedIn()->language()->addToStack('all');
foreach( \IPS\Content\Reaction::roots() AS $reaction )
{
$tabs[ $reaction->id ] = $reaction->_title;
if ($reaction->_enabled !== FALSE)
{
$tabs[$reaction->id] = $reaction->_title;
}
}
$activeTab = 'all';
@@ -1537,7 +1642,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
if ( $canReport !== TRUE )
{
\IPS\Output::i()->error( 'generic_error', '1C138/6', 403, '' );
\IPS\Output::i()->error( $canReport, '1C138/6', 403, '' );
}
$form = new \IPS\Helpers\Form( NULL, 'report_submit' );
@@ -1613,23 +1718,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
* Set Cover Photo
*
* @param \IPS\Helpers\CoverPhoto $photo New Photo
* @param string $type 'new', 'remove', 'reposition'
* @return void
*/
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo )
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo, $type=NULL )
{
/* If we are changing our cover photo, it is safe to assume that any services currently set to sync should no longer do so */
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
if ( !empty( $services ) )
/* Disable syncing */
$profileSync = $this->member->profilesync;
if ( isset( $profileSync['cover'] ) )
{
foreach( $services AS $class )
{
$obj = new $class( $this->member );
if ( $obj->connected() )
{
$obj->save( array( 'profilesync_cover' => FALSE ) );
}
}
unset( $profileSync['cover'] );
$this->member->profilesync = $profileSync;
}
$this->member->pp_cover_photo = (string) $photo->file;
@@ -1639,6 +1738,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$this->member->members_bitoptions['profile_completed'] = FALSE;
$this->member->save();
if ( $type != 'reposition' )
{
$this->member->logHistory( 'core', 'coverphoto', array( 'action' => $type ) );
}
}
/**