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

@@ -54,7 +54,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->metaTags['robots'] = 'noindex, follow';
}
\IPS\Output::i()->linkTags['canonical'] = (string)$this->member->url();
\IPS\Output::i()->linkTags['canonical'] = (string) $this->member->url();
\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' ) );
@@ -114,7 +114,7 @@ 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 && !isset( \IPS\Request::i()->getUploader ) )
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->commentPage && $canAccessStatuses && !isset( \IPS\Request::i()->getUploader ) )
{
try
{
@@ -378,6 +378,9 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* Get followers */
$followers = $this->member->followers( ( \IPS\Member::loggedIn()->isAdmin() OR \IPS\Member::loggedIn()->member_id === $this->member->member_id ) ? \IPS\Member::FOLLOW_PUBLIC + \IPS\Member::FOLLOW_ANONYMOUS : \IPS\Member::FOLLOW_PUBLIC, array( 'immediate', 'daily', 'weekly', 'none' ), NULL, array( 0, 12 ) );
/* Get solutions */
$solutions = \IPS\Db::i()->select( 'COUNT(*)', 'core_solved_index', array( 'member_id=?', $this->member->member_id ) )->first();
/* Update online location */
$module = \IPS\Application\Module::get( 'core', 'members', 'front' )->permissions();
@@ -398,15 +401,15 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
'name' => $this->member->name,
'primaryImageOfPage' => array(
'@type' => "ImageObject",
'contentUrl' => (string) $this->member->get_photo(),
'contentUrl' => (string) $this->member->get_photo( TRUE, TRUE ),
'representativeOfPage' => true,
'thumbnail' => array(
'@type' => "ImageObject",
'contentUrl' => (string) $this->member->get_photo( TRUE ),
'contentUrl' => (string) $this->member->get_photo( TRUE, TRUE ),
)
),
'thumbnailUrl' => (string) $this->member->get_photo( TRUE ),
'image' => (string) $this->member->get_photo(),
'thumbnailUrl' => (string) $this->member->get_photo( TRUE, TRUE ),
'image' => (string) $this->member->get_photo( FALSE, TRUE ),
'relatedLink' => (string) \IPS\Http\Url::internal( "app=core&module=members&controller=profile&do=content&id={$this->member->member_id}", "front", "profile_content", array( $this->member->members_seo_name ) ),
'dateCreated' => $this->member->joined->format( \IPS\DateTime::ISO8601 ),
'interactionStatistic' => array(
@@ -425,7 +428,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* 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 );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->profile( $this->member, $mainContent, $visitors, $sidebarFields, $followers, $addWarningUrl, $solutions );
}
/**
@@ -620,6 +623,33 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userContent( $this->member, $types, $currentAppModule, $currentType, (string) $output );
}
}
/**
* Show badges
*
* @return void
*/
public function badges()
{
if( !$this->member->canHaveAchievements() || !\IPS\core\Achievements\Badge::show() )
{
\IPS\Output::i()->error( 'no_module_permission', '2C138/S', 403, '' );
}
$percentage = NULL;
if ( $this->member->achievements_points )
{
$percentage = \IPS\Db::i()->select( "CEIL( 100 * COUNT( IF( achievements_points > " . ( $this->member->achievements_points - 1 ) . ", 1, NULL ) ) / COUNT(*) ) as percentage", 'core_members', ['achievements_points > 0'] )->first();
if ( $percentage > 51 )
{
$percentage = NULL;
}
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'members_badges', FALSE, array( 'sprintf' => array( $this->member->name ) ) );;
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userBadgeOverview( $this->member, $percentage );
}
/**
* Show Reputation
@@ -992,20 +1022,14 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* The basics */
$form->addTab( 'profile_edit_basic_tab', 'user');
$canChangeTitle = ( \IPS\Settings::i()->post_titlechange != -1 and ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) );
$canChangeBirthday = ( \IPS\Settings::i()->profile_birthday_type !== 'none' );
$canEnableDisableStatuses = ( \IPS\Settings::i()->profile_comments and $this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) AND !$this->member->members_bitoptions['bw_no_status_update'] );
if( $canChangeTitle or $canChangeBirthday or $canEnableDisableStatuses )
if( $canChangeBirthday or $canEnableDisableStatuses )
{
$form->addHeader( 'profile_edit_basic_header' );
}
if( \IPS\Settings::i()->post_titlechange != -1 and ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) )
{
$form->add( new \IPS\Helpers\Form\Text( 'member_title', $this->member->member_title, FALSE, array( 'maxLength' => 64 ) ) );
}
if ( \IPS\Settings::i()->profile_birthday_type !== 'none' )
{
$form->add( new \IPS\Helpers\Form\Custom( 'bday', array( 'year' => $this->member->bday_year, 'month' => $this->member->bday_month, 'day' => $this->member->bday_day ), FALSE, array( 'getHtml' => function( $element )
@@ -1107,11 +1131,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
*/
protected function _saveMember( $form, array $values )
{
if( ( \IPS\Settings::i()->post_titlechange == -1 or ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) ) AND isset( $values['member_title'] ) )
{
$this->member->member_title = $values['member_title'];
}
if( isset( $values['bday'] ) )
{
if( $values['bday'] and ( ( $values['bday']['day'] and !$values['bday']['month'] ) or ( $values['bday']['month'] and !$values['bday']['day'] ) ) )
@@ -1909,4 +1928,262 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Request::i()->action = 'delete';
return $this->moderate();
}
/**
* Show Solutions
*
* @return void
*/
public function solutions()
{
/* Get the different types */
$types = array();
$hasCallback = array();
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'profile.css', $class::$application ) );
if ( \IPS\IPS::classUsesTrait( $class, 'IPS\Content\Solvable' ) )
{
$types[ mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) ) ] = $class::$commentClass;
}
}
/* What type are we looking at? */
$currentType = NULL;
if ( isset( \IPS\Request::i()->type ) AND array_key_exists( \IPS\Request::i()->type, $types ) )
{
$currentType = \IPS\Request::i()->type;
}
if ( $currentType === NULL )
{
foreach ( $types as $key => $type )
{
$currentType = $key;
break;
}
}
$currentClass = $types[ $currentType ];
/* Build Output */
$url = \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=reputation&type={$currentType}", 'front', 'profile_reputation', array( $this->member->members_seo_name ) );
$table = new \IPS\Helpers\Table\Content( $currentClass, $url, NULL, NULL, \IPS\Content\Hideable::FILTER_AUTOMATIC, 'read', FALSE );
$table->joinContainer = TRUE;
$table->sortOptions = array( 'solved_date' );
$table->sortBy = 'solved_date';
$table->joins = array(
array(
'select' => "core_solved_index.id AS solved_id, core_solved_index.solved_date",
'from' => 'core_solved_index',
'where' => array( "core_solved_index.comment_id=" . $currentClass::$databaseTable . "." . $currentClass::$databasePrefix . $currentClass::$databaseColumnId . " AND core_solved_index.member_id=? AND core_solved_index.comment_class=?", $this->member->member_id, $currentClass ),
'type' => 'INNER'
)
);
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userSolutionsTable' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userSolutionsRows' );
$table->showAdvancedSearch = FALSE;
/* Display */
if ( \IPS\Request::i()->isAjax() && \IPS\Request::i()->change_section )
{
\IPS\Output::i()->sendOutput( (string) $table );
}
else
{
\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_solutions', FALSE, array('sprintf' => $this->member->name ) ), $table->page ) ) ) : \IPS\Member::loggedIn()->language()->addToStack( 'member_solutions', FALSE, array('sprintf' => $this->member->name ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userSolutions( $this->member, $types, $currentType, (string) $table, $this->member->solutionCount() );
}
}
/**
* Recognize
*
* @return void
*/
protected function recognize()
{
$class = \IPS\Request::i()->content_class;
$id = \IPS\Request::i()->content_id;
/* Does this content exist? */
try
{
$content = $class::loadAndCheckPerms( $id );
/* Can we view this item? */
if ( ! $content->canView() )
{
\IPS\Output::i()->error( 'node_error', '2C138/O', 403, '' );
}
/* Make sure there's no shenanigans */
if ( $this->member->member_id != $content->author()->member_id )
{
\IPS\Output::i()->error( 'node_error', '2C138/P', 403, '' );
}
/* Can we recognize this ? */
if ( ! $content->canRecognize() )
{
\IPS\Output::i()->error( 'node_error', '2C138/Q', 403, '' );
}
/* Now build the form */
$form = new \IPS\Helpers\Form( 'badge_form', 'save' );
$form->class = 'ipsForm_vertical ipsForm_fullWidth';
/* What has been awarded so far today? */
$message = NULL;
if ( $this->member->todaysRecognizePoints() and $this->member->todaysRecognizeBadges() )
{
$message = \IPS\Member::loggedIn()->language()->addToStack('recognize_points_so_far_both', NULL, [
'sprintf' => [
$this->member->name,
\IPS\Member::loggedIn()->language()->addToStack('recognize_points_pluralize', NULL, [ 'sprintf' => [ $this->member->todaysRecognizePoints() ], 'pluralize' => [ $this->member->todaysRecognizePoints() ] ]),
\IPS\Member::loggedIn()->language()->addToStack('recognize_badges_pluralize', NULL, [ 'sprintf' => [ $this->member->todaysRecognizeBadges() ], 'pluralize' => [ $this->member->todaysRecognizeBadges() ] ]),
] ] );
}
else if ( $this->member->todaysRecognizePoints() )
{
$message = \IPS\Member::loggedIn()->language()->addToStack('recognize_points_so_far_single', NULL, [
'sprintf' => [
$this->member->name,
\IPS\Member::loggedIn()->language()->addToStack('recognize_points_pluralize', NULL, [ 'sprintf' => [ $this->member->todaysRecognizePoints() ], 'pluralize' => [ $this->member->todaysRecognizePoints() ] ])
] ] );
}
else if ( $this->member->todaysRecognizeBadges() )
{
$message = \IPS\Member::loggedIn()->language()->addToStack('recognize_points_so_far_single', NULL, [
'sprintf' => [
$this->member->name,
\IPS\Member::loggedIn()->language()->addToStack('recognize_points_pluralize', NULL, [ 'sprintf' => [ $this->member->todaysRecognizeBadges() ], 'pluralize' => [ $this->member->todaysRecognizeBadges() ] ])
] ] );
}
$maxPoints = NULL;
$disabled = FALSE;
if ( \IPS\Settings::i()->achievements_recognize_max_per_user_day != -1 )
{
$maxPoints = \IPS\Settings::i()->achievements_recognize_max_per_user_day - $this->member->todaysRecognizePoints();
if ( $maxPoints > 0 )
{
$message .= \IPS\Member::loggedIn()->language()->addToStack( 'recognize_points_so_far_limit', NULL, ['sprintf' => [$this->member->name, $maxPoints]] );
}
else
{
$message .= \IPS\Member::loggedIn()->language()->addToStack( 'recognize_points_so_far_limit_none', NULL, ['sprintf' => [$this->member->name]] );
$disabled = TRUE;
}
if ( \IPS\Member::loggedIn()->modPermission('can_recognize_content_no_point_limit') )
{
$message .= \IPS\Member::loggedIn()->language()->addToStack('recognize_points_so_far_limit_but_none');
$maxPoints = NULL;
$disabled = FALSE;
}
}
if ( $message )
{
$form->addMessage( $message, 'ipsMessage ipsMessage_info' );
}
if ( \IPS\Member::loggedIn()->modPermission('can_recognize_content') == '*' OR \in_array( 'badges', \IPS\Member::loggedIn()->modPermission('can_recognize_content_options') ) )
{
$form->add( new \IPS\Helpers\Form\Node( 'recognize_badge', NULL, FALSE, [
'class' => '\IPS\core\Achievements\Badge',
'permissionCheck' => function ( $node ) {
return $node->manually_awarded;
},
'url' => $content->author()->url()->setQueryString( array('do' => 'recognize', 'content_class' => $class, 'content_id' => $id) )
] ) );
}
if ( \IPS\Member::loggedIn()->modPermission('can_recognize_content') == '*' OR \in_array( 'points', \IPS\Member::loggedIn()->modPermission('can_recognize_content_options') ) )
{
$form->add( new \IPS\Helpers\Form\Number( 'recognize_points', 0, FALSE, [ 'disabled' => $disabled, 'min' => 0, 'max' => $maxPoints ] ) );
}
$form->add( new \IPS\Helpers\Form\Text( 'recognize_message', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'recognize_public', TRUE, FALSE ) );
\IPS\Member::loggedIn()->language()->words['recognize_message_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'recognize_message__desc', NULL, [ 'sprintf' => [ $content->author()->name ] ] );
if ( $values = $form->values() )
{
if ( ! $values['recognize_badge'] and ! $values['recognize_points'] )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('recognize_form_empty');
}
else
{
\IPS\core\Achievements\Recognize::add( $content, $this->member, $values['recognize_points'], $values['recognize_badge'], $values['recognize_message'], \IPS\Member::loggedIn(), $values['recognize_public'] );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Member::loggedIn()->language()->addToStack( 'recognize_submit_success' ) );
}
else
{
\IPS\Output::i()->redirect( $content->url(), 'recognize_submit_success' );
}
}
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('recognize_author', NULL, [ 'sprintf' => [ $content->author()->name ] ] );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
catch( \Exception $e )
{
\IPS\Output::i()->error( 'node_error', '2C138/R', 403, '' );
}
}
/**
* Recognize
*
* @return void
*/
protected function unrecognize()
{
$class = \IPS\Request::i()->content_class;
$id = \IPS\Request::i()->content_id;
/* Does this content exist? */
try
{
$content = $class::loadAndCheckPerms( $id );
/* Can we view this item? */
if ( ! $content->canView() )
{
\IPS\Output::i()->error( 'node_error', '2C138/S', 403, '' );
}
/* Can we recognize this ? */
if ( ! $content->canRemoveRecognize() )
{
\IPS\Output::i()->error( 'node_error', '2C138/T', 403, '' );
}
$content->removeRecognize();
}
catch ( \Exception $e )
{
\IPS\Output::i()->error( 'node_error', '2C138/Ug', 403, '' );
}
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Member::loggedIn()->language()->addToStack( 'recognize_removed_success' ) );
}
else
{
\IPS\Output::i()->redirect( $content->url(), 'recognize_removed_success' );
}
}
}