Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

@@ -2,9 +2,9 @@
/**
* @brief Profile
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 19 Jul 2013
* @version SVN_VERSION_NUMBER
*/
@@ -23,7 +23,6 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
/**
* [Content\Controller] Class
*/
@@ -54,6 +53,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_statuses.js', 'core' ) );
\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' ) );
if ( \IPS\Theme::i()->settings['responsive'] )
{
@@ -104,7 +104,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()->submitting && !\IPS\Request::i()->getUploader && $canAccessStatuses )
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->page && $canAccessStatuses )
{
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'statuses' )->statusReplies( $status );
@@ -152,10 +152,18 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* Work out the main content to display */
if ( $canAccessSingleStatuses and \IPS\Request::i()->status and \IPS\Request::i()->type == 'status' )
{
$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/E', 404, '' );
}
$mainContent = \IPS\Theme::i()->getTemplate( 'profile' )->singleStatus( $this->member, $status );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->get( 'viewing_single_status' );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'viewing_single_status_of', FALSE, array('sprintf' => array( \IPS\DateTime::ts( $status->mapped('date') )->localeDate() , $status->author()->name ) ) );
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->get( 'viewing_single_status' ) );
}
else
@@ -257,7 +265,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
elseif ( mb_substr( $tab, 0, 6 ) == 'field_' )
{
$fieldId = mb_substr( $tab, 6 );
$tabContents = \IPS\Theme::i()->getTemplate( 'profile' )->fieldTab( $fieldId, $fields[ $fieldId ] );
foreach( $mainFields as $group => $fields )
{
foreach( $fields as $field => $value )
{
if ( $field == $fieldId )
{
$tabContents = \IPS\Theme::i()->getTemplate( 'profile' )->fieldTab( $fieldId, $value );
}
}
}
}
elseif ( mb_substr( $tab, 0, 5 ) == 'node_' )
{
@@ -298,12 +315,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$visitorInfo = json_decode( $this->member->pp_last_visitors, TRUE );
if ( is_array( $visitorInfo ) and $this->member->members_bitoptions['pp_setting_count_visitors'] )
{
$visitorData = array();
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'member_id', array_keys( array_reverse( $visitorInfo, TRUE ) ) ) ) ), 'IPS\Member' ) AS $row )
{
$visitorData[$row->member_id] = $row;
}
foreach( array_reverse( $visitorInfo, TRUE ) as $id => $time )
{
$visitor = \IPS\Member::load( $id );
if ( $visitor->member_id )
if ( isset( $visitorData[$id] ) )
{
$visitors[$id]['member'] = $visitor;
$visitors[$id]['member'] = $visitorData[$id];
$visitors[$id]['visit_time'] = $time;
}
}
@@ -425,6 +447,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
$query = \IPS\Content\Search\Query::init()->filterByAuthor( $this->member )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->setPage( $page );
$results = $query->search();
/* If we requested a higher page than is allowed, redirect back to last page */
$totalResults = $results->count( TRUE );
if( $totalResults AND ceil( $totalResults / $query->resultsToGet ) < $page )
{
$highestPage = floor( $totalResults / $query->resultsToGet );
\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 );
}
@@ -435,7 +467,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$currentApp = $currentAppArray[0];
if( isset( $hasCallback[ $currentType ] ) )
{
$output = $hasCallback[ $currentType ]->customTableHelper( $currentClass, $this->member->url()->setQueryString( array( 'do' => 'content', 'type' => $currentType ) ), array( array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['author'] . '=?', $this->member->member_id ) ) );
$output = $hasCallback[ $currentType ]->customTableHelper( $currentClass, \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=content", 'front', 'profile_content', $this->member->members_seo_name )->setQueryString( array( 'type' => $currentType ) ), array( array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['author'] . '=?', $this->member->member_id ) ) );
}
else
{
@@ -445,21 +477,25 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
$where[] = array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['state'] . ' != ?', 'link' );
}
if ( isset( $currentClass::$databaseColumnMap['status'] ) )
{
$where[] = array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['status'] . ' != ?', 'draft' );
}
if( method_exists( $currentClass, 'commentWhere' ) AND $currentClass::commentWhere() !== NULL )
{
$where[] = $currentClass::commentWhere();
}
$output = new \IPS\Helpers\Table\Content( $currentClass, $this->member->url()->setQueryString( array( 'do' => 'content', 'type' => $currentType ) ), $where, NULL, NULL, 'read', FALSE );
$output = new \IPS\Helpers\Table\Content( $currentClass, \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=content", 'front', 'profile_content', $this->member->members_seo_name )->setQueryString( array( 'type' => $currentType ) ), $where, NULL, NULL, 'read', FALSE );
}
if ( $currentType == 'core_statuses_status' )
{
$output->noModerate = TRUE;
}
$output->showFilters = FALSE;
$output->classes[] = 'cProfileContent';
}
@@ -471,7 +507,8 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
else
{
/* Display */
\IPS\Output::i()->title = $this->member->name;
$title = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( $this->member->name, \IPS\Request::i()->page ) ) ) : $this->member->name;
\IPS\Output::i()->title = $title;
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/statuses.css' ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userContent( $this->member, $types, $currentAppModule, $currentType, (string) $output );
}
@@ -545,105 +582,23 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* 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 ) );
$where = array( array( '( core_reputation_index.member_id=? OR core_reputation_index.member_received=? ) AND core_reputation_index.app=? AND core_reputation_index.type=?', $this->member->member_id, $this->member->member_id, $currentClass::$application, $currentClass::$reputationType ) );
if( method_exists( $currentClass, 'commentWhere' ) AND $currentClass::commentWhere() !== NULL )
{
$where[] = $currentClass::commentWhere();
}
$containerClass = NULL;
$permClass = $currentClass;
if ( isset( $currentClass::$itemClass ) )
{
$permClass = $currentClass::$itemClass;
}
if ( in_array( 'IPS\Content\Permissions', class_implements( $permClass ) ) )
{
$containerClass = $permClass::$containerNodeClass;
$permissionKey = 'read';
$member = \IPS\Member::loggedIn();
$categories = array();
foreach( \IPS\Db::i()->select( 'perm_type_id', 'core_permission_index', array( "core_permission_index.app='" . $containerClass::$permApp . "' AND core_permission_index.perm_type='" . $containerClass::$permType . "' AND (" . \IPS\Db::i()->findInSet( 'perm_' . $containerClass::$permissionMap[ $permissionKey ], $member->groups ) . ' OR ' . 'perm_' . $containerClass::$permissionMap[ $permissionKey ] . "='*' )" ) ) as $result )
{
$categories[] = $result;
}
if( count( $categories ) )
{
$where[] = array( $permClass::$databaseTable . "." . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . ' IN(' . implode( ',', $categories ) . ')' );
}
else
{
$where[] = array( $permClass::$databaseTable . "." . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . '=0' );
}
}
$table = new \IPS\Helpers\Table\Db( $currentClass::$databaseTable, $url, $where );
$table = new \IPS\Helpers\Table\Content( $currentClass, $url, NULL, NULL, \IPS\Content\Hideable::FILTER_AUTOMATIC, 'read', FALSE );
$table->joinContainer = TRUE;
$table->sortOptions = array( 'rep_date' );
$table->sortBy = 'rep_date';
$table->joins = array(
array( 'select' => "core_reputation_index.id AS rep_id, core_reputation_index.rep_date, core_reputation_index.rep_rating, core_reputation_index.member_received as rep_member_received, core_reputation_index.member_id as rep_member", 'from' => 'core_reputation_index', 'where' => array( "core_reputation_index.type_id=" . $currentClass::$databaseTable . "." . $currentClass::$databasePrefix . $currentClass::$databaseColumnId ) ),
array(
'select' => "core_reputation_index.id AS rep_id, core_reputation_index.rep_date, core_reputation_index.rep_rating, core_reputation_index.member_received as rep_member_received, core_reputation_index.member_id as rep_member",
'from' => 'core_reputation_index',
'where' => array( "core_reputation_index.type_id=" . $currentClass::$databaseTable . "." . $currentClass::$databasePrefix . $currentClass::$databaseColumnId . " AND ( core_reputation_index.member_id=? OR core_reputation_index.member_received=? ) AND core_reputation_index.app=? AND core_reputation_index.type=?", $this->member->member_id, $this->member->member_id, $currentClass::$application, $currentClass::$reputationType ),
'type' => 'INNER'
)
);
if ( $containerClass )
{
if ( isset( $currentClass::$itemClass ) )
{
$itemClass = $currentClass::$itemClass;
$table->joins[] = array(
'select' => $itemClass::$databaseTable . '.*',
'from' => $itemClass::$databaseTable,
'where' => array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['item'] . '=' . $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnId )
);
}
$table->joins[] = array(
'select' => $containerClass::$databaseTable . '.*',
'from' => $containerClass::$databaseTable,
'where' => array( $permClass::$databaseTable . '.' . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . '=' . $containerClass::$databaseTable . '.' . $containerClass::$databasePrefix . $containerClass::$databaseColumnId )
);
}
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userReputationTable' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userReputationRows' );
$table->showAdvancedSearch = FALSE;
$table->include = array( 'obj', 'reputationData' );
$table->parsers = array(
'obj' => function( $val, $row ) use ( $currentClass )
{
try
{
$return = $currentClass::constructFromData( $row );
if ( $return instanceof \IPS\Content\Comment )
{
$return->item(); // Prevent the exception later
}
return $return;
}
catch ( \OutOfRangeException $e )
{
if ( $row['rep_id'] )
{
\IPS\Db::i()->delete( 'core_reputation_index', array( 'id=?', $row['rep_id'] ) );
}
}
},
'reputationData' => function( $val, $row )
{
return array(
'rep_date' => $row['rep_date'],
'rep_rating' => $row['rep_rating'],
'rep_member' => $row['rep_member'],
'rep_member_received' => $row['rep_member_received'],
);
}
);
/* Display */
if ( \IPS\Request::i()->isAjax() && \IPS\Request::i()->change_section )
@@ -651,8 +606,9 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->sendOutput( (string) $table );
}
else
{
\IPS\Output::i()->title = $this->member->name;
{
\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 );
}
}
@@ -760,175 +716,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->error( 'no_permission_edit_profile', '2S147/1', 403, '' );
}
/* Build the form */
$form = new \IPS\Helpers\Form;
/* The basics */
$form->addTab( 'profile_edit_basic_tab', 'user');
$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 ) ) );
}
$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 )
{
return strtr( \IPS\Member::loggedIn()->language()->preferredDateFormat(), array(
'dd' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_day( $element->name, $element->value, $element->error ),
'mm' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_month( $element->name, $element->value, $element->error ),
'yy' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
'yyyy' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
) );
} ) ) );
if ( \IPS\Settings::i()->profile_comments and $this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'enable_status_updates', $this->member->pp_setting_count_comments ) );
}
/* Profile fields */
try
{
$values = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
}
catch( \UnderflowException $e )
{
$values = array();
}
foreach ( \IPS\core\ProfileFields\Field::fields( $values, \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
{
$form->addHeader( "core_pfieldgroups_{$group}" );
foreach ( $fields as $field )
{
$form->add( $field );
}
}
/* Moderator stuff */
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id )
{
$form->add( new \IPS\Helpers\Form\Editor( 'signature', $this->member->signature, FALSE, array( 'app' => 'core', 'key' => 'Signatures', 'autoSaveKey' => "frontsig-" . $this->member->member_id, 'attachIds' => array( $this->member->member_id ) ) ) );
$form->addTab( 'profile_edit_moderation', 'times' );
if ( $this->member->mod_posts !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_mod_posts', NULL, FALSE ) );
}
if ( $this->member->restrict_post !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_restrict_post', NULL, FALSE ) );
}
if ( $this->member->temp_ban !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_ban', NULL, FALSE ) );
}
}
$form = $this->buildEditForm();
/* Handle the submission */
if ( $values = $form->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( $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 ( isset( $values['enable_status_updates'] ) )
{
$this->member->pp_setting_count_comments = $values['enable_status_updates'];
if ( $values['enable_status_updates'] )
{
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '*', NULL, NULL, $this->member->member_id );
}
else
{
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '', NULL, NULL, $this->member->member_id );
}
}
/* Profile Fields */
try
{
$profileFields = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
}
catch( \UnderflowException $e )
{
$profileFields = array();
}
/* If the row only contains one column (eg. member_id) then the result of the query is a string, we do not want this */
if ( !is_array( $profileFields ) )
{
$profileFields = array();
}
$profileFields['member_id'] = $this->member->member_id;
foreach ( \IPS\core\ProfileFields\Field::fields( $profileFields, \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
{
foreach ( $fields as $id => $field )
{
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
if ( $field instanceof \IPS\Helpers\Form\Editor )
{
\IPS\core\ProfileFields\Field::load( $id )->claimAttachments( $this->member->member_id );
}
}
$this->member->changedCustomFields = $profileFields;
}
/* Moderator stuff */
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id)
{
if ( isset( $values['remove_mod_posts'] ) AND $values['remove_mod_posts'] )
{
$this->member->mod_posts = 0;
}
if ( isset( $values['remove_restrict_post'] ) AND $values['remove_restrict_post'] )
{
$this->member->restrict_post = 0;
}
if ( isset( $values['remove_ban'] ) AND $values['remove_ban'] )
{
$this->member->temp_ban = 0;
}
if ( isset( $values['signature'] ) )
{
$this->member->signature = $values['signature'];
}
}
/* Save */
\IPS\Db::i()->replace( 'core_pfields_content', $profileFields );
$this->member->save();
$this->_saveMember( $form, $values );
\IPS\Output::i()->redirect( $this->member->url() );
}
@@ -947,7 +740,205 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'editing_profile', FALSE, array( 'sprintf' => array( $this->member->name ) ) );
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'editing_profile', FALSE, array( 'sprintf' => array( $this->member->name ) ) ) );
}
/**
* Build Edit Form
*
* @return \IPS\Helpers\Form
*/
protected function buildEditForm()
{
/* Build the form */
$form = new \IPS\Helpers\Form;
/* The basics */
$form->addTab( 'profile_edit_basic_tab', 'user');
$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 )
{
return strtr( \IPS\Member::loggedIn()->language()->preferredDateFormat(), array(
'DD' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_day( $element->name, $element->value, $element->error ),
'MM' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_month( $element->name, $element->value, $element->error ),
'YY' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
'YYYY' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
) );
} ) ) );
if ( \IPS\Settings::i()->profile_birthday_type == 'private' )
{
$form->addMessage( 'profile_birthday_display_private', 'ipsMessage ipsMessage_info' );
}
}
if ( \IPS\Settings::i()->profile_comments and $this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) AND !$this->member->members_bitoptions['bw_no_status_update'] )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'enable_status_updates', $this->member->pp_setting_count_comments ) );
}
/* Profile fields */
try
{
$values = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
}
catch( \UnderflowException $e )
{
$values = array();
}
foreach ( \IPS\core\ProfileFields\Field::fields( $values, \IPS\core\ProfileFields\Field::PROFILE ) as $group => $fields )
{
$form->addHeader( "core_pfieldgroups_{$group}" );
foreach ( $fields as $field )
{
$form->add( $field );
}
}
/* Moderator stuff */
if ( ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') OR \IPS\Member::loggedIn()->modPermission('can_unban') ) AND \IPS\Member::loggedIn()->member_id != $this->member->member_id )
{
$form->add( new \IPS\Helpers\Form\Editor( 'signature', $this->member->signature, FALSE, array( 'app' => 'core', 'key' => 'Signatures', 'autoSaveKey' => "frontsig-" . $this->member->member_id, 'attachIds' => array( $this->member->member_id ) ) ) );
if ( \IPS\Member::loggedIn()->modPermission('can_unban') )
{
$form->addTab( 'profile_edit_moderation', 'times' );
if ( $this->member->mod_posts !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_mod_posts', NULL, FALSE ) );
}
if ( $this->member->restrict_post !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_restrict_post', NULL, FALSE ) );
}
if ( $this->member->temp_ban !== 0 )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_ban', NULL, FALSE ) );
}
}
}
return $form;
}
/**
* Save Member
*
* @param $form
* @param array $values
*/
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( $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 ( isset( $values['enable_status_updates'] ) )
{
$this->member->pp_setting_count_comments = $values['enable_status_updates'];
if ( $values['enable_status_updates'] )
{
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '*', NULL, NULL, $this->member->member_id );
}
else
{
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '', NULL, NULL, $this->member->member_id );
}
}
/* Profile Fields */
try
{
$profileFields = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
}
catch( \UnderflowException $e )
{
$profileFields = array();
}
/* If the row only contains one column (eg. member_id) then the result of the query is a string, we do not want this */
if ( !is_array( $profileFields ) )
{
$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\Editor )
{
\IPS\core\ProfileFields\Field::load( $id )->claimAttachments( $this->member->member_id );
}
}
$this->member->changedCustomFields = $profileFields;
}
/* Moderator stuff */
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id)
{
if ( isset( $values['remove_mod_posts'] ) AND $values['remove_mod_posts'] )
{
$this->member->mod_posts = 0;
}
if ( isset( $values['remove_restrict_post'] ) AND $values['remove_restrict_post'] )
{
$this->member->restrict_post = 0;
}
if ( isset( $values['remove_ban'] ) AND $values['remove_ban'] )
{
$this->member->temp_ban = 0;
}
if ( isset( $values['signature'] ) )
{
$this->member->signature = $values['signature'];
}
}
/* Save */
\IPS\Db::i()->replace( 'core_pfields_content', $profileFields );
$this->member->save();
}
/**
* Edit Photo
*
@@ -968,16 +959,15 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$toggles = array( 'custom' => array( 'member_photo_upload' ), 'url' => array( 'member_photo_url' ) );
$extra = array();
$options = array();
$defaultType = $this->member->pp_photo_type;
/* Can we upload? */
if ( $photoVars[0] )
{
$options['custom'] = 'member_photo_upload';
$options['url'] = 'member_photo_url';
}
/* We can always use URLs */
$options['url'] = 'member_photo_url';
/* Can we use gallery images? */
if ( \IPS\Application::appIsEnabled('gallery') AND $this->member->pp_photo_type == 'gallery_Images' )
{
@@ -988,8 +978,11 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
if ( \IPS\Settings::i()->allow_gravatars )
{
$options['gravatar'] = 'member_photo_gravatar';
$extra[] = new \IPS\Helpers\Form\Email( 'photo_gravatar_email_public', $this->member->pp_gravatar ?: $this->member->email, FALSE, array( 'maxLength' => 255 ), NULL, NULL, NULL, 'member_photo_gravatar' );
$toggles['gravatar'] = array( 'member_photo_gravatar' );
if ( $this->member->member_id === \IPS\Member::loggedIn()->member_id or \IPS\Member::loggedIn()->modPermission('can_see_emails') )
{
$extra[] = new \IPS\Helpers\Form\Email( 'photo_gravatar_email_public', $this->member->pp_gravatar ?: $this->member->email, FALSE, array( 'maxLength' => 255 ), NULL, NULL, NULL, 'member_photo_gravatar' );
$toggles['gravatar'] = array( 'member_photo_gravatar' );
}
}
/* ProfileSync (Facebook, etc.) */
@@ -1006,19 +999,34 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* And of course we can always not have a photo */
$options['none'] = 'member_photo_none';
/* Create that selection */
$form->add( new \IPS\Helpers\Form\Radio( 'pp_photo_type', $this->member->pp_photo_type, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
/* iOS doesn't like upload forms being hidden by a toggle; and it makes sense if we do not have a profile photo to show the upload as the selected option */
if ( $defaultType == 'none' and $photoVars[0] )
{
$defaultType = 'custom';
}
/* Create that selection */
$form->add( new \IPS\Helpers\Form\Radio( 'pp_photo_type', $defaultType, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
/* Create the upload field */
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 ), NULL, NULL, NULL, 'member_photo_upload' ) );
$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() );
if( $image->isAnimatedGif and !$this->member->group['g_upload_animated_photos'] )
{
throw new \DomainException('member_photo_upload_no_animated');
}
}
}, NULL, NULL, 'member_photo_upload' ) );
/* Create the URL */
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), NULL, NULL, NULL, 'member_photo_url' ) );
}
/* Create the URL */
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL ), NULL, NULL, NULL, 'member_photo_url' ) );
/* Add additional elements */
foreach ( $extra as $element )
{
@@ -1028,12 +1036,24 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
/* Handle submissions */
if ( $values = $form->values() )
{
$this->member->pp_photo_type = $values['pp_photo_type'] === 'none' ? NULL : $values['pp_photo_type'];
$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 ) )
{
foreach( $services AS $class )
{
$obj = new $class( $this->member );
$obj->save( array( 'profilesync_photo' => FALSE ) );
}
}
switch ( $values['pp_photo_type'] )
{
case 'custom':
if ( $values['member_photo_upload'] )
if ( $photoVars[0] and $values['member_photo_upload'] )
{
if ( (string) $values['member_photo_upload'] !== '' )
{
@@ -1050,7 +1070,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
break;
case 'url':
if( $values['member_photo_url'] )
if( $photoVars[0] and $values['member_photo_url'] )
{
$this->member->pp_photo_type = 'custom';
$this->member->pp_main_photo = NULL;
@@ -1070,7 +1090,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
break;
case 'gravatar':
$this->member->pp_gravatar = ( $values['photo_gravatar_email_public'] === $this->member->email ) ? NULL : $values['photo_gravatar_email_public'];
$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:
@@ -1131,6 +1151,11 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
*/
protected function cropPhoto()
{
if ( !\IPS\Member::loggedIn()->modPermission('can_modify_profiles') and ( \IPS\Member::loggedIn()->member_id !== $this->member->member_id or !$this->member->group['g_edit_profile'] ) )
{
\IPS\Output::i()->error( 'no_permission_edit_profile', '2C138/F', 403, '' );
}
if( !$this->member->pp_main_photo )
{
\IPS\Output::i()->error( 'no_photo_to_crop', '2C138/C', 404, '' );
@@ -1180,10 +1205,13 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
}
/* Save the new */
$cropped = \IPS\File::create( 'core_Profile', $original->filename, (string) $image );
$cropped = \IPS\File::create( 'core_Profile', $original->originalFilename, (string) $image );
$this->member->pp_thumb_photo = (string) $cropped->thumbnail( 'core_Profile', \IPS\PHOTO_THUMBNAIL_SIZE, \IPS\PHOTO_THUMBNAIL_SIZE );
$this->member->save();
/* Delete the temporary full size cropped image */
$cropped->delete();
/* Edited member, so clear widget caches (stats, widgets that contain photos, names and so on) */
\IPS\Widget::deleteCaches();
@@ -1291,7 +1319,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
{
try
{
$item = ( \IPS\Request::i()->type == 'status' ) ? \IPS\core\Statuses\Status::load( \IPS\Request::i()->status ) : \IPS\core\Statuses\Reply::load( \IPS\Request::i()->status );
$item = ( \IPS\Request::i()->type == 'status' ) ? \IPS\core\Statuses\Status::load( \IPS\Request::i()->status ) : \IPS\core\Statuses\Reply::load( \IPS\Request::i()->reply );
\IPS\Output::i()->output = $item->reputationTable();
}
@@ -1368,7 +1396,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
$limit = array( ( $page - 1 ) * 50, 50 );
$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' ), NULL, $limit, 'name' );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'profile' )->followers( $this->member, $followers ) );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('members_followers', FALSE, array( 'sprintf' => array( $this->member->name ) ) );
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('members_followers', FALSE, array( 'sprintf' => array( $this->member->name ) ) ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->allFollowers( $this->member, $followers );
@@ -1392,10 +1425,45 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
*/
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo )
{
/* 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 ) )
{
foreach( $services AS $class )
{
$obj = new $class( $this->member );
if ( $obj->connected() )
{
$obj->save( array( 'profilesync_cover' => FALSE ) );
}
}
}
$this->member->pp_cover_photo = (string) $photo->file;
$this->member->pp_cover_offset = $photo->offset;
$this->member->pp_cover_offset = (int) $photo->offset;
$this->member->save();
}
/**
* Get Name History
*/
protected function namehistory()
{
if ( !\IPS\Member::loggedIn()->group['g_view_displaynamehistory'] )
{
\IPS\Output::i()->error( 'no_module_permission', '1C138/G', 403, '' );
}
$table = new \IPS\Helpers\Table\Db( 'core_dnames_change', $this->member->url()->setQueryString( 'do', 'namehistory' ), array( 'dname_member_id=?', $this->member->member_id ) );
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'profile' ), 'nameHistoryTable' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'profile' ), 'nameHistoryRows' );
$table->sortBy = 'dname_date';
$table->sortDirection = 'desc';
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addtoStack( 'members_dname_history', FALSE, array( 'sprintf' => ( $this->member->name ) ) );
\IPS\Output::i()->output = $table;
}
/**
* Get Cover Photo