Version 4.3.0
This commit is contained in:
1 parent
96997ddd8e
commit
fe1acf984a
1349 files changed
+116159
-67711
No files matched your search
@@ -60,6 +60,10 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
$baseUrl = \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' );
|
||||
if ( isset( \IPS\Request::i()->view ) and in_array( \IPS\Request::i()->view, array( 'grid', 'list' ) ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString( 'view', \IPS\Request::i()->view );
|
||||
}
|
||||
|
||||
/* All Clubs: Sort */
|
||||
$sortOption = \IPS\Settings::i()->clubs_default_sort;
|
||||
@@ -71,11 +75,25 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
/* All Clubs: Filters */
|
||||
$filters = array();
|
||||
$mineOnly = FALSE;
|
||||
$extraWhere = NULL;
|
||||
if ( isset( \IPS\Request::i()->filter ) and \IPS\Request::i()->filter === 'mine' )
|
||||
{
|
||||
$mineOnly = TRUE;
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', 'mine' );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->type ) and in_array( \IPS\Request::i()->type, array( 'free', 'paid' ) ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString( 'type', \IPS\Request::i()->type );
|
||||
|
||||
if ( \IPS\Request::i()->type === 'free' )
|
||||
{
|
||||
$extraWhere[] = array( 'fee IS NULL' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$extraWhere[] = array( 'fee IS NOT NULL' );
|
||||
}
|
||||
}
|
||||
foreach ( \IPS\Member\Club\CustomField::fields() as $field )
|
||||
{
|
||||
$k = "f{$field->id}";
|
||||
@@ -100,7 +118,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( isset( $options[ $id ] ) )
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $options[ $id ];
|
||||
if( $field->type == 'CheckboxSet' )
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $options[ $id ];
|
||||
}
|
||||
}
|
||||
}
|
||||
$baseUrl = $baseUrl->setQueryString( 'f' . $field->id, array_keys( $filters[ $field->id ] ) );
|
||||
@@ -116,8 +141,8 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
/* Get All Clubs */
|
||||
$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 ), $sortOption, $mineOnly, $filters );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $allClubs->count( TRUE ) / $perPage ), $page, $perPage );
|
||||
$allClubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), array( ( $page - 1 ) * $perPage, $perPage ), $sortOption, $mineOnly, $filters, $extraWhere );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( ( is_object( $allClubs ) ? $allClubs->count( TRUE ) : 0 ) / $perPage ), $page, $perPage );
|
||||
|
||||
/* Get my clubs */
|
||||
$myClubsActivity = NULL;
|
||||
@@ -128,7 +153,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build Map */
|
||||
$mapMarkers = NULL;
|
||||
if ( \IPS\Settings::i()->googlemaps and \IPS\Settings::i()->google_maps_api_key )
|
||||
if ( \IPS\GeoLocation::enabled() )
|
||||
{
|
||||
$mapMarkers = array();
|
||||
|
||||
@@ -139,7 +164,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
elseif ( !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$where[] = array( "( type<>? OR status IN('" . \IPS\Member\Club::STATUS_MEMBER . "','" . \IPS\Member\Club::STATUS_MODERATOR . "','" . \IPS\Member\Club::STATUS_LEADER . "') )", \IPS\Member\Club::TYPE_PRIVATE );
|
||||
$where[] = array( "( type<>? OR status IN('" . \IPS\Member\Club::STATUS_MEMBER . "','" . \IPS\Member\Club::STATUS_MODERATOR . "','" . \IPS\Member\Club::STATUS_LEADER . "','" . \IPS\Member\Club::STATUS_EXPIRED . "','" . \IPS\Member\Club::STATUS_EXPIRED_MODERATOR . "') )", \IPS\Member\Club::TYPE_PRIVATE );
|
||||
}
|
||||
|
||||
$select = \IPS\Db::i()->select( array( 'id', 'name', 'location_lat', 'location_long' ), 'core_clubs', $where );
|
||||
@@ -164,8 +189,21 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$view = \IPS\Settings::i()->clubs_default_view;
|
||||
if ( \IPS\Settings::i()->clubs_allow_view_change )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->view ) and in_array( \IPS\Request::i()->view, array( 'grid', 'list' ) ) )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'clubs_view', \IPS\Request::i()->view, \IPS\DateTime::create()->add( new \DateInterval('P1Y' ) ) );
|
||||
$view = \IPS\Request::i()->view;
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->cookie['clubs_view'] ) and in_array( \IPS\Request::i()->cookie['clubs_view'], array( 'grid', 'list' ) ) )
|
||||
{
|
||||
$view = \IPS\Request::i()->cookie['clubs_view'];
|
||||
}
|
||||
}
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->directory( $featuredClubs, $allClubs, $pagination, $baseUrl, $sortOption, $myClubsActivity, $mapMarkers );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->directory( $featuredClubs, $allClubs, $pagination, $baseUrl, $sortOption, $myClubsActivity, $mapMarkers, $view );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,6 +225,15 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
) ) ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'club_membership_fee', isset( \IPS\Request::i()->type ) ? \IPS\Request::i()->type : 'all', TRUE, array( 'options' => array(
|
||||
'all' => 'all_clubs',
|
||||
'free' => 'club_membership_free',
|
||||
'paid' => 'club_membership_paid'
|
||||
) ) ) );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
if ( $field->filterable )
|
||||
@@ -225,6 +272,11 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
$url = $url->setQueryString( 'filter', 'mine' );
|
||||
}
|
||||
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) and \IPS\Settings::i()->clubs_paid_on and $values['club_membership_fee'] !== 'all' )
|
||||
{
|
||||
$url = $url->setQueryString( 'type', $values['club_membership_fee'] );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
if ( $field->filterable )
|
||||
@@ -273,11 +325,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
protected function create()
|
||||
{
|
||||
$availableTypes = array();
|
||||
foreach ( explode( ',', \IPS\Member::loggedIn()->group['g_create_clubs'] ) as $type )
|
||||
if ( \IPS\Member::loggedIn()->member_id ) // Guests can't create any type of clubs
|
||||
{
|
||||
if ( $type !== '' )
|
||||
foreach ( explode( ',', \IPS\Member::loggedIn()->group['g_create_clubs'] ) as $type )
|
||||
{
|
||||
$availableTypes[ $type ] = 'club_type_' . $type;
|
||||
if ( $type !== '' )
|
||||
{
|
||||
$availableTypes[ $type ] = 'club_type_' . $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !$availableTypes )
|
||||
@@ -285,6 +340,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->member_id ? 'no_module_permission' : 'no_module_permission_guest', '2C349/1', 403, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->group['g_club_limit'] )
|
||||
{
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs', array( 'owner=?', \IPS\Member::loggedIn()->member_id ) )->first() >= \IPS\Member::loggedIn()->group['g_club_limit'] )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'too_many_clubs', FALSE, array( 'pluralize' => array( \IPS\Member::loggedIn()->group['g_club_limit'] ) ) ), '2C349/3', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
$club = new \IPS\Member\Club;
|
||||
if ( $form = $club->form( FALSE, TRUE, $availableTypes ) )
|
||||
{
|
||||
|
||||
@@ -105,6 +105,12 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Club info in sidebar */
|
||||
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $this->club, NULL, 'sidebar' );
|
||||
}
|
||||
|
||||
/* If this is a closed club, and we don't have permission to read it, show the member page instead */
|
||||
if ( $this->club->type == \IPS\Member\Club::TYPE_CLOSED && !$this->club->canRead() )
|
||||
{
|
||||
@@ -113,7 +119,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get the activity stream */
|
||||
$activity = \IPS\Content\Search\Query::init()->filterByClub( $this->club )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->search();
|
||||
$activity = \IPS\Content\Search\Query::init()->filterByClub( $this->club )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_CREATED )->search();
|
||||
|
||||
/* Get who joined the club in between those results */
|
||||
if ( $this->club->type != \IPS\Member\Club::TYPE_PUBLIC )
|
||||
@@ -121,7 +127,14 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$lastTime = NULL;
|
||||
foreach ( $activity as $key => $result )
|
||||
{
|
||||
$lastTime = $result->createdDate->getTimestamp();
|
||||
if ( $result !== NULL )
|
||||
{
|
||||
$lastTime = $result->createdDate->getTimestamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $activity[ $key ] );
|
||||
}
|
||||
}
|
||||
$joins = array();
|
||||
$joinWhere = array( array( 'club_id=?', $this->club->id ), array( \IPS\Db::i()->in( 'status', array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) ) );
|
||||
@@ -132,7 +145,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$select = 'core_clubs_memberships.joined' . ',' . implode( ',', array_map( function( $column ) {
|
||||
return 'core_members.' . $column;
|
||||
}, \IPS\Member::columnsForPhoto() ) );
|
||||
foreach ( \IPS\Db::i()->select( $select, 'core_clubs_memberships', $joinWhere, 'joined DESC', NULL, NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )->join( 'core_members', 'core_members.member_id=core_clubs_memberships.member_id' ) as $join )
|
||||
foreach ( \IPS\Db::i()->select( $select, 'core_clubs_memberships', $joinWhere, 'joined DESC', array( 0, 50 ), NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )->join( 'core_members', 'core_members.member_id=core_clubs_memberships.member_id' ) as $join )
|
||||
{
|
||||
$joins[] = new \IPS\Content\Search\Result\Custom(
|
||||
\IPS\DateTime::ts( $join['core_clubs_memberships']['joined'] ),
|
||||
@@ -144,7 +157,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Merge them in */
|
||||
if ( !empty( $joins ) )
|
||||
{
|
||||
$activity = array_merge( iterator_to_array( $activity ), $joins );
|
||||
$activity = array_filter( array_merge( iterator_to_array( $activity ), $joins ) );
|
||||
uasort( $activity, function( $a, $b )
|
||||
{
|
||||
if ( $a->createdDate->getTimestamp() == $b->createdDate->getTimestamp() )
|
||||
@@ -163,7 +176,8 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Display */
|
||||
/* Display */
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) $this->club->url();
|
||||
\IPS\Output::i()->title = $this->club->name;
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->view( $this->club, $activity, $this->club->fieldValues() );
|
||||
}
|
||||
@@ -215,7 +229,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function editPhoto()
|
||||
{
|
||||
if ( !( $this->club->owner and $this->club->owner == \IPS\Member::loggedIn() ) and !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
if ( !$this->club->isLeader() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/R', 403, '' );
|
||||
}
|
||||
@@ -301,7 +315,7 @@ class _view 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 )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('profile')->photoCrop( $field->name, $field->value, $this->club->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
return \IPS\Theme::i()->getTemplate('members', 'core', 'global')->photoCrop( $field->name, $field->value, $this->club->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
}
|
||||
) ) );
|
||||
|
||||
@@ -323,7 +337,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Save it */
|
||||
$croppedFilename = mb_substr( $original->originalFilename, 0, mb_strrpos( $original->originalFilename, '.' ) ) . '.cropped' . mb_substr( $original->originalFilename, mb_strrpos( $original->originalFilename, '.' ) );
|
||||
$cropped = \IPS\File::create( 'core_Profile', $original->originalFilename, (string) $image );
|
||||
$cropped = \IPS\File::create( 'core_Clubs', $croppedFilename, (string) $image );
|
||||
$this->club->profile_photo = (string) $cropped;
|
||||
$this->club->save();
|
||||
|
||||
@@ -389,12 +403,21 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_WAITING_PAYMENT:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_WAITING_PAYMENT;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_WAITING_PAYMENT );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_WAITING_PAYMENT );
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_BANNED:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_BANNED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_REQUESTED );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_BANNED );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -402,10 +425,19 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_INVITED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_INVITED );
|
||||
$statuses = array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_INVITED );
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_EXPIRED );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,11 +452,18 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Sort out the offset */
|
||||
$perPage = 28;
|
||||
|
||||
$activePage = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
|
||||
if( $activePage < 1 )
|
||||
{
|
||||
$activePage = 1;
|
||||
}
|
||||
|
||||
$offset = ( $activePage - 1 ) * $perPage;
|
||||
|
||||
/* Fetch them */
|
||||
$members = $this->club->members( $statuses, array( $offset, $perPage ), $orderByClause, $this->club->isLeader() ? 3 : 1 );
|
||||
$members = $this->club->members( $statuses, array( $offset, $perPage ), $orderByClause, $this->club->isLeader() ? 5 : 1 );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $members->count(TRUE) / $perPage ), $activePage, $perPage );
|
||||
|
||||
/* Display */
|
||||
@@ -434,9 +473,16 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$staffStatuses = array( \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_MODERATOR );
|
||||
if ( $this->club->isLeader( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$staffStatuses[] = \IPS\Member\Club::STATUS_EXPIRED_MODERATOR;
|
||||
}
|
||||
$clubStaff = $this->club->members( $staffStatuses, NULL, "IF(core_clubs_memberships.status='leader',0,1), core_clubs_memberships.joined ASC", $this->club->isLeader( \IPS\Member::loggedIn() ) ? 5 : 3 );
|
||||
|
||||
\IPS\Output::i()->title = $this->club->name;
|
||||
\IPS\Output::i()->breadcrumb[] = array( $this->club->url()->setQueryString( 'do', 'members' ), \IPS\Member::loggedIn()->language()->addToStack('club_members') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'clubs' )->members( $this->club, $members, $pagination, $sortBy, $filter );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'clubs' )->members( $this->club, $members, $pagination, $sortBy, $filter, $clubStaff );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,7 +510,12 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Add them */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE, \IPS\Member::loggedIn(), NULL, TRUE );
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( $this->club->isPaid() and !isset( \IPS\Request::i()->waiveFee ) )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_WAITING_PAYMENT;
|
||||
}
|
||||
$this->club->addMember( $member, $status, TRUE, \IPS\Member::loggedIn(), NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Notify the member */
|
||||
@@ -574,7 +625,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR ) ) )
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/7', 403, '' );
|
||||
}
|
||||
@@ -603,14 +654,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_LEADER )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -633,14 +697,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/L', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MODERATOR;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED_MODERATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MODERATOR, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -663,14 +740,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_MODERATOR )
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/N', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -695,17 +785,218 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
$status = $this->club->memberStatus( $member );
|
||||
if ( !in_array( $status, array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
|
||||
/* If this was just an invite, then just remove that */
|
||||
if ( in_array( $status, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
if ( $this->club->owner and $this->club->owner->member_id === $member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_cannot_remove_owner', '2C350/E', 403, '' );
|
||||
$this->club->removeMember( $member );
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'member=? AND notification_app=? AND notification_key=? and item_id=?', $member->member_id, 'core', 'club_invitation', $this->club->id ) );
|
||||
$member->recountNotifications();
|
||||
}
|
||||
|
||||
/* Remove */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_BANNED, TRUE, \IPS\Member::loggedIn() );
|
||||
/* If they were previously accepted and waiting for payment, treat it as a decline */
|
||||
elseif ( in_array( $status, array( \IPS\Member\Club::STATUS_WAITING_PAYMENT ) ) )
|
||||
{
|
||||
/* Decline them */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_DECLINED, TRUE, \IPS\Member::loggedIn() );
|
||||
|
||||
/* Notify the member */
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_response', $this->club, array( $this->club, FALSE ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
/* Otherwise check they are actually a member that can be removed */
|
||||
else
|
||||
{
|
||||
if ( !in_array( $status, array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
if ( $this->club->owner and $this->club->owner->member_id === $member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_cannot_remove_owner', '2C350/E', 403, '' );
|
||||
}
|
||||
|
||||
/* Cancel purchase */
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::load( \IPS\Request::i()->member ), $this->club->id ) as $purchase )
|
||||
{
|
||||
$purchase->cancelled = TRUE;
|
||||
$purchase->member->log( 'purchase', array( 'type' => 'cancel', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
$purchase->can_reactivate = FALSE;
|
||||
$purchase->save();
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_BANNED, TRUE, \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
/* Recount */
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Waive membership fee
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function bypassPayment()
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() or !\IPS\Application::appIsEnabled('nexus') or !\IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/W', 403, '' );
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Do it */
|
||||
switch ( $this->club->memberStatus( $member ) )
|
||||
{
|
||||
/* If they were waiting for payment, just go ahead and promote them to a member */
|
||||
case \IPS\Member\Club::STATUS_WAITING_PAYMENT:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
break;
|
||||
|
||||
/* If they were already in the club, find their purchase and remove the expiry date */
|
||||
case \IPS\Member\Club::STATUS_MEMBER:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
case \IPS\Member\Club::STATUS_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_LEADER:
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
$extra = $purchase->extra;
|
||||
$extra['originalExpire'] = $purchase->expire ? $purchase->expire->getTimestamp() : NULL;
|
||||
$purchase->extra = $extra;
|
||||
$purchase->expire = NULL;
|
||||
$purchase->save();
|
||||
|
||||
$member->log( 'purchase', array( 'type' => 'info', 'info' => 'never_expire', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
}
|
||||
break;
|
||||
|
||||
/* If they have been invited, just change their status to invited bypassing payment */
|
||||
case \IPS\Member\Club::STATUS_INVITED:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT, TRUE );
|
||||
break;
|
||||
|
||||
/* For anything else, we can't do this... */
|
||||
default:
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/X', 403, '' );
|
||||
}
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore Payment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restorePayment()
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() or !\IPS\Application::appIsEnabled('nexus') or !\IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/W', 403, '' );
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Do it */
|
||||
$status = $this->club->memberStatus( $member );
|
||||
switch ( $status )
|
||||
{
|
||||
/* If they were already in the club, find their purchase and restore the expiry date */
|
||||
case \IPS\Member\Club::STATUS_MEMBER:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
case \IPS\Member\Club::STATUS_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_LEADER:
|
||||
|
||||
$foundPurchase = FALSE;
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
$foundPurchase = TRUE;
|
||||
|
||||
if ( !$purchase->renewals or !$purchase->renewals->cost->amount->isZero() )
|
||||
{
|
||||
$purchase->renewals = $this->club->renewalTerm( $purchase->renewal_currency ?: $member->defaultCurrency() );
|
||||
}
|
||||
if ( isset( $purchase->extra['originalExpire'] ) )
|
||||
{
|
||||
$newExpiry = \IPS\DateTime::ts( $purchase->extra['originalExpire'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$newExpiry = \IPS\DateTime::create()->add( $purchase->renewals->interval );
|
||||
}
|
||||
$purchase->expire = $newExpiry;
|
||||
$purchase->save();
|
||||
$member->log( 'purchase', array( 'type' => 'info', 'info' => 'restored_expire', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
|
||||
if ( $newExpiry->getTimestamp() < time() )
|
||||
{
|
||||
if ( $status === \IPS\Member\Club::STATUS_MEMBER )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_EXPIRED, TRUE );
|
||||
}
|
||||
elseif ( $status === \IPS\Member\Club::STATUS_MODERATOR )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR, TRUE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $status === \IPS\Member\Club::STATUS_EXPIRED )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
}
|
||||
elseif ( $status === \IPS\Member\Club::STATUS_EXPIRED_MODERATOR )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MODERATOR, TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we couldn't find a purchase, we'll have to remove them and re-invite them */
|
||||
if ( !$foundPurchase )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_invitation', $this->club, array( $this->club, \IPS\Member::loggedIn() ), array( 'invitedBy' => \IPS\Member::loggedIn()->member_id ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* If they have been invited, just change their status to invited NOT bypassing payment */
|
||||
case \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE );
|
||||
break;
|
||||
|
||||
/* For anything else, we can't do this... */
|
||||
default:
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/X', 403, '' );
|
||||
}
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
@@ -729,11 +1020,55 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* If this is an open club, or the member was invited, or they have mod access anyway go ahead and add them */
|
||||
if ( $this->memberStatus === \IPS\Member\Club::STATUS_INVITED or $this->club->type === \IPS\Member\Club::TYPE_OPEN or \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
if ( in_array( $this->memberStatus, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT, \IPS\Member\Club::STATUS_WAITING_PAYMENT ) ) or $this->club->type === \IPS\Member\Club::TYPE_OPEN or \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$this->club->addMember( \IPS\Member::loggedIn(), \IPS\Member\Club::STATUS_MEMBER, TRUE, NULL, NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
$notificationKey = 'club_join';
|
||||
/* Unless they have to pay */
|
||||
if ( $this->club->isPaid() and $this->memberStatus !== \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT )
|
||||
{
|
||||
if ( $fee = $this->club->joiningFee() )
|
||||
{
|
||||
/* Create the item */
|
||||
$item = new \IPS\core\extensions\nexus\Item\ClubMembership( $this->club->name, $fee );
|
||||
$item->id = $this->club->id;
|
||||
try
|
||||
{
|
||||
$item->tax = \IPS\Settings::i()->clubs_paid_tax ? \IPS\nexus\Tax::load( \IPS\Settings::i()->clubs_paid_tax ) : NULL;
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
if ( \IPS\Settings::i()->clubs_paid_gateways )
|
||||
{
|
||||
$item->paymentMethodIds = explode( ',', \IPS\Settings::i()->clubs_paid_gateways );
|
||||
}
|
||||
$item->renewalTerm = $this->club->renewalTerm( $fee->currency );
|
||||
$item->payTo = $this->club->owner;
|
||||
$item->commission = \IPS\Settings::i()->clubs_paid_commission;
|
||||
if ( $fees = \IPS\Settings::i()->clubs_paid_transfee and isset( $fees[ $fee->currency ] ) )
|
||||
{
|
||||
$item->fee = new \IPS\nexus\Money( $fees[ $fee->currency ]['amount'], $fee->currency );
|
||||
}
|
||||
|
||||
/* Generate the invoice */
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice->currency = $fee->currency;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice->addItem( $item );
|
||||
$invoice->return_uri = "app=core&module=clubs&controller=view&id={$this->club->id}";
|
||||
$invoice->save();
|
||||
|
||||
/* Take them to it */
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_paid_unavailable', '1C350/N', 403, '' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->club->addMember( \IPS\Member::loggedIn(), \IPS\Member\Club::STATUS_MEMBER, TRUE, NULL, NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
$notificationKey = 'club_join';
|
||||
}
|
||||
}
|
||||
/* Otherwise, add the request */
|
||||
else
|
||||
@@ -762,7 +1097,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
protected function leave()
|
||||
{
|
||||
/* Can we leave? */
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) or ( $this->club->owner and $this->club->owner->member_id == \IPS\Member::loggedIn()->member_id ) )
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR, \IPS\Member\Club::STATUS_WAITING_PAYMENT, \IPS\Member\Club::STATUS_INVITED ) ) or ( $this->club->owner and $this->club->owner->member_id == \IPS\Member::loggedIn()->member_id ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/S', 403, '' );
|
||||
}
|
||||
@@ -770,15 +1105,57 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Cancel purchase */
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::loggedIn(), $this->club->id ) as $purchase )
|
||||
{
|
||||
$purchase->cancelled = TRUE;
|
||||
$purchase->member->log( 'purchase', array( 'type' => 'cancel', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
$purchase->can_reactivate = FALSE;
|
||||
$purchase->save();
|
||||
}
|
||||
}
|
||||
|
||||
/* Leave */
|
||||
$this->club->removeMember( \IPS\Member::loggedIn() );
|
||||
$this->club->recountMembers();
|
||||
$this->club->save();
|
||||
|
||||
/* Delete the invitation */
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'member=? AND notification_app=? AND notification_key=? and item_id=?', \IPS\Member::loggedIn()->member_id, 'core', 'club_invitation', $this->club->id ) );
|
||||
\IPS\Member::loggedIn()->recountNotifications();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function renew()
|
||||
{
|
||||
/* Can we renew? */
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/Y', 403, '' );
|
||||
}
|
||||
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Find the purchase */
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::loggedIn(), $this->club->id ) as $purchase )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $purchase->url()->setQueryString( array( 'do' => 'renew', 'cycles' => 1 ) )->csrf() );
|
||||
}
|
||||
|
||||
/* Couldn't find it? */
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/Z', 500, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invite Members
|
||||
*
|
||||
@@ -794,9 +1171,23 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$form = new \IPS\Helpers\Form( 'form', 'club_send_invitations' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'members', NULL, TRUE, array( 'multiple' => NULL ) ) );
|
||||
if ( $this->club->isPaid() and $this->club->isLeader() )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'club_invite_waive_fee', FALSE ) );
|
||||
if ( $this->club->renewal_price )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['club_invite_waive_fee_desc'] = \IPS\Member::loggedIn()->language()->addToStack('club_invite_waive_fee_renewal');
|
||||
}
|
||||
}
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_INVITED;
|
||||
if ( $this->club->isPaid() and $this->club->isLeader() and $values['club_invite_waive_fee'] )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT;
|
||||
}
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_invitation', $this->club, array( $this->club, \IPS\Member::loggedIn() ), array( 'invitedBy' => \IPS\Member::loggedIn()->member_id ) );
|
||||
foreach ( $values['members'] as $member )
|
||||
{
|
||||
@@ -805,7 +1196,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$memberStatus = $this->club->memberStatus( $member );
|
||||
if ( !$memberStatus or in_array( $memberStatus, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_REQUESTED, \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED ) ) )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
$notification->recipients->attach( $member );
|
||||
}
|
||||
}
|
||||
@@ -999,6 +1390,52 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->output = \IPS\Request::i()->isAjax() ? $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ) : $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a node
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function nodeDelete()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/AA', 403, '' );
|
||||
}
|
||||
|
||||
/* Load */
|
||||
$class = \IPS\Request::i()->type;
|
||||
try
|
||||
{
|
||||
$node = $class::load( \IPS\Request::i()->node );
|
||||
$club = $node->club();
|
||||
if ( !$club or $club->id !== $this->club->id )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/AB', 404, '' );
|
||||
}
|
||||
|
||||
/* Permission check */
|
||||
$itemClass = $node::$contentItemClass;
|
||||
if ( !$node->modPermission( 'delete', \IPS\Member::loggedIn() ) and $itemClass::contentCount( $node, TRUE, TRUE, TRUE, 1 ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/AC', 403, '' );
|
||||
}
|
||||
|
||||
/* Delete */
|
||||
\IPS\Db::i()->delete( 'core_clubs_node_map', array( 'club_id=? AND node_class=? AND node_id=?', $club->id, $class, $node->_id ) );
|
||||
$node->deleteOrMoveFormSubmit( array() );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $club->url() );
|
||||
}
|
||||
|
||||
/* !Cover Photo */
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->canUseContactUs() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2S333/1', 403, '' );
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2S333/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
@@ -100,15 +100,4 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Can Use Contact Us
|
||||
*
|
||||
* @return bool
|
||||
* @deprecated 4.3
|
||||
*/
|
||||
public static function canUseContactUs()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->canUseContactUs();
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$table->sortDirection = $table->sortDirection ?: 'DESC';
|
||||
|
||||
/* Like or what? */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
if ( \IPS\Content\Reaction::isLikeMode() )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['leader_rep_total'] = \IPS\Member::loggedIn()->language()->addToStack( 'leader_rep_total_likes' );
|
||||
\IPS\Member::loggedIn()->language()->words['leaderboard_history__desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_desc', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_likes') ) ) );
|
||||
@@ -202,7 +202,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$endDate = \IPS\DateTime::ts( time() )->setTimezone( $timezone );
|
||||
|
||||
$firstRepDate = \IPS\Db::i()->select( 'MIN(rep_date)', 'core_reputation_index' )->first();
|
||||
$firstIndexDate = \IPS\Db::i()->select( 'MIN(index_date_updated)', 'core_search_index' )->first();
|
||||
$firstIndexDate = \IPS\Content\Search\Index::i()->firstIndexDate();
|
||||
$appWhere = null;
|
||||
$descApp = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_in_all_apps' );
|
||||
|
||||
@@ -320,13 +320,14 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Got an app? */
|
||||
$appWhere = '';
|
||||
/* Do we want results for a specific app */
|
||||
$customApp = FALSE;
|
||||
|
||||
if ( isset( \IPS\Request::i()->in ) and isset( $areas[ \IPS\Request::i()->in ] ) )
|
||||
{
|
||||
$appWhere = " AND rep_class='" . \IPS\Db::i()->escape_string( $areas[ \IPS\Request::i()->in ][ 0 ] ) . "'";
|
||||
$descApp = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_in_app', NULL, array( 'sprintf' => array( $areas[ \IPS\Request::i()->in ][ 1 ] ) ) );
|
||||
$customApp = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -341,7 +342,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
$storeKey = NULL;
|
||||
$hashes = NULL;
|
||||
if ( ! $customStart and ! $customEnd AND ! $appWhere )
|
||||
if ( ! $customStart and ! $customEnd AND ! $customApp )
|
||||
{
|
||||
$storeKey = 'leaderHashes_' . \IPS\Request::i()->time . '-' . md5( implode( ',', \IPS\Member::loggedIn()->groups ) );
|
||||
|
||||
@@ -368,9 +369,9 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
/* Get rep hashes */
|
||||
$inner = \IPS\Db::i()->select( 'class_type_id_hash, SUM(rep_rating) as total_rep', array( 'core_reputation_index', 'x' ), array( 'rep_date BETWEEN ' . $date->getTimeStamp() . ' AND ' . $endDate->getTimeStamp() . $appWhere ), NULL, NULL, 'class_type_id_hash' );
|
||||
$repHashes = iterator_to_array( \IPS\Db::i()->select( 'class_type_id_hash, total_rep', $inner, NULL, 'x.total_rep desc', array( 0, 500 ) )->setKeyField('class_type_id_hash') );
|
||||
|
||||
|
||||
/* Now filter through permissions */
|
||||
$searchHashes = iterator_to_array( \IPS\Db::i()->select( 'index_class_type_id_hash', array( 'core_search_index', 'si' ), array( array( "( si.index_permissions = '*' OR " . \IPS\Db::i()->findInSet( 'si.index_permissions', \IPS\Member::loggedIn()->groups ) . ' AND si.index_hidden=0 )' ), array( \IPS\Db::i()->in( 'si.index_class_type_id_hash', array_keys( $repHashes ) ) ) ) )->setKeyField('index_class_type_id_hash') );
|
||||
$searchHashes = \IPS\Content\Search\Index::i()->hashesWithPermission( array_keys( $repHashes ), \IPS\Member::loggedIn() );
|
||||
|
||||
/* Filter out rep hashes not in search results */
|
||||
$hashes = array_slice( array_intersect_key( $repHashes, $searchHashes ), 0, 50 );
|
||||
@@ -386,7 +387,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$or = array();
|
||||
$results = array();
|
||||
$preLoadMembers = array();
|
||||
|
||||
|
||||
if ( count( $hashes ) )
|
||||
{
|
||||
/* Now get the reputation data */
|
||||
@@ -395,25 +396,15 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$data['total_rep'] = $hashes[ $data['class_type_id_hash'] ]['total_rep'];
|
||||
$repData[ $data['rep_class'] . '-' . $data['type_id'] ] = $data;
|
||||
$classes[ $data['rep_class'] ][] = $data['type_id'];
|
||||
|
||||
if ( ! empty( $data['member_id'] ) )
|
||||
{
|
||||
$preLoadMembers[] = $data['member_id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $classes as $class => $ids )
|
||||
{
|
||||
$or[] = '( index_class=\'' . \IPS\Db::i()->escape_string( $class ) . '\' AND ' . \IPS\Db::i()->in( 'index_object_id', $ids ) . ')';
|
||||
$or[] = \IPS\Content\Search\ContentFilter::init( $class )->onlyInIds( $ids );
|
||||
}
|
||||
|
||||
/* Construct the query */
|
||||
$query = \IPS\Db::i()->select( '*', array( 'core_search_index', 'main' ), array( implode( ' OR ', $or ) ), NULL, NULL, NULL, NULL );
|
||||
|
||||
$array = iterator_to_array( $query );
|
||||
$sorted = array();
|
||||
|
||||
/* Manually sort */
|
||||
/* Query and manually sort */
|
||||
$array = \IPS\Content\Search\Query::init()->filterByContent( $or )->search()->getArrayCopy();
|
||||
foreach( $array as $index => $data )
|
||||
{
|
||||
if ( isset( $repData[ $data['index_class'] . '-' . $data['index_object_id'] ] ) )
|
||||
@@ -433,8 +424,13 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Get top rated contributors */
|
||||
$topContributors = array();
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', array( 'member_received>0 ' . $appWhere . ' and rep_date BETWEEN ' . intval( $date->getTimeStamp() ) . ' AND ' . intval( $endDate->getTimeStamp() ) ), NULL, NULL, 'member' );
|
||||
|
||||
$innerQueryWhere = array();
|
||||
$innerQueryWhere[] = array( 'member_received>0 ' . $appWhere . ' and rep_date BETWEEN ' . intval( $date->getTimeStamp() ) . ' AND ' . intval( $endDate->getTimeStamp() ) );
|
||||
$innerQueryWhere[] = \IPS\Db::i()->in( 'member_group_id', \IPS\Settings::i()->leaderboard_excluded_groups, TRUE );
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', $innerQueryWhere, NULL, NULL, 'member' )->join( 'core_members', array( 'core_reputation_index.member_received = core_members.member_id' ) );
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'member, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', 4 )->setKeyField('member')->setValueField('rep') as $member => $rep )
|
||||
{
|
||||
$topContributors[ $member ] = $rep;
|
||||
@@ -455,7 +451,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Work out the description for popular content */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
if ( \IPS\Content\Reaction::isLikeMode() )
|
||||
{
|
||||
$popularResultsSingle = 'popular_results_single_desc';
|
||||
$popularResultsMany = 'popular_results_desc';
|
||||
@@ -481,6 +477,12 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) \IPS\Http\Url::internal( "app=core&module=discover&controller=popular&tab=leaderboard", 'front', 'leaderboard_leaderboard' );
|
||||
|
||||
/* If there are no results tell search engines not to index the page */
|
||||
if( !count( $results ) )
|
||||
{
|
||||
\IPS\Output::i()->metaTags['robots'] = 'noindex';
|
||||
}
|
||||
|
||||
/* Display */
|
||||
return \IPS\Theme::i()->getTemplate('popular')->popularWrapper( $results, $areas, $topContributors, $dates, $description, $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ), $tzOffsetDifference );
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
|
||||
* @since 13 Oct 2016
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Necessary CSS/JS */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_streams.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams.css' ) );
|
||||
\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/streams.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
@@ -121,7 +122,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'url' => $defaultStream->url(),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ),
|
||||
'tooltip' => $defaultStream->_title, // We need to pass this individually for the tooltip that shows, but the JS itself will escape any entities
|
||||
'id' => $defaultStream->_id
|
||||
) );
|
||||
@@ -166,7 +167,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'url' => \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_all' ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ),
|
||||
'id' => $defaultStream->_id
|
||||
) );
|
||||
}
|
||||
@@ -187,7 +188,13 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
/* but only if we haven't submitted the form on this request */
|
||||
if( !\IPS\Request::i()->stream_submitted )
|
||||
{
|
||||
$streamFields = array( 'include_comments', 'classes', 'clubs', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' );
|
||||
$streamFields = array( 'include_comments', 'classes', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' );
|
||||
|
||||
/* Clubs enabled? */
|
||||
if( \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$streamFields[] = 'clubs';
|
||||
}
|
||||
|
||||
/* Build and format field values */
|
||||
$_values = array();
|
||||
@@ -379,7 +386,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->streamItems( $results, TRUE, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
|
||||
$return = array(
|
||||
'title' => htmlspecialchars( $stream->_title, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $stream->_title, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'blurb' => $stream->blurb(),
|
||||
'config' => json_encode( $stream->config() ),
|
||||
'count' => count( $results ),
|
||||
@@ -484,7 +491,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $stream->member != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2C280/8', 403, '' );
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C280/8', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
@@ -599,7 +606,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$url = $stream ? $stream->baseUrl->setQueryString( 'className', $class ) : \IPS\Request::i()->url()->setQueryString( 'className', $class );
|
||||
$containerClass = $class::$containerNodeClass;
|
||||
$field = new \IPS\Helpers\Form\Node( 'stream_containers_' . $class::$title, isset( $currentContainers[ $class ] ) ? $currentContainers[ $class ] : array(), NULL, array( 'url' => $url, 'class' => $class::$containerNodeClass, 'multiple' => TRUE, 'permissionCheck' => $containerClass::searchableNodesPermission(), 'clubs' => \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) ), NULL, NULL, NULL, 'stream_containers_' . $class::$title );
|
||||
$field = new \IPS\Helpers\Form\Node( 'stream_containers_' . $class::$title, isset( $currentContainers[ $class ] ) ? $currentContainers[ $class ] : array(), NULL, array( 'url' => $url, 'class' => $class::$containerNodeClass, 'multiple' => TRUE, 'permissionCheck' => $containerClass::searchableNodesPermission(), 'clubs' => ( \IPS\Settings::i()->clubs AND \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) ) ), NULL, NULL, NULL, 'stream_containers_' . $class::$title );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( 'stream_narrow_by_container_label', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $containerClass::$nodeTitle ) ) ) );
|
||||
|
||||
return \IPS\Output::i()->json( array( 'node' => \IPS\Theme::i()->getTemplate('streams')->filterFormContentTypeContent( $field, $class, \IPS\Request::i()->key ) ) );
|
||||
@@ -616,6 +623,11 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function getClubElement()
|
||||
{
|
||||
if( !\IPS\Settings::i()->clubs )
|
||||
{
|
||||
return \IPS\Output::i()->json( array( 'field' => '' ) );
|
||||
}
|
||||
|
||||
$clubOptions = array();
|
||||
foreach ( \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE ) as $club )
|
||||
{
|
||||
@@ -681,25 +693,48 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* As the node container form elements are not in the actual form, we need to work some magic. And by magic, I do mean a sort of hacky thing. */
|
||||
foreach ( \IPS\Request::i() as $k => $v )
|
||||
/* As the node container form elements are not in the actual form, we need to work some magic.
|
||||
And by magic, I do mean a sort of hacky thing. First, if we are editing a stream, we need to get our existing stream filters
|
||||
and put these into an array. Then we loop over the input and overwrite the existing filters with what was submitted. If the user
|
||||
never loaded the container filters we'll retain what we had (expected) but if they did and adjusted or removed container filters
|
||||
then we'll update with what they submitted (expected).
|
||||
*/
|
||||
if( $stream->id )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 18 ) == 'stream_containers_' and $v )
|
||||
$currentContainers = $stream->containers ? json_decode( $stream->containers, TRUE ) : array();
|
||||
|
||||
foreach( $currentContainers as $class => $containers )
|
||||
{
|
||||
$vals = explode( ',', $v );
|
||||
$values[ $k ] = array_combine( $vals, $vals );
|
||||
$values['stream_containers_' . $class::$title ] = array_combine( $containers, $containers );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ( \IPS\Request::i() as $k => $v )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 18 ) == 'stream_containers_' )
|
||||
{
|
||||
if( $v )
|
||||
{
|
||||
$vals = explode( ',', $v );
|
||||
$values[ $k ] = array_combine( $vals, $vals );
|
||||
}
|
||||
elseif( isset( $values[ $k ] ) )
|
||||
{
|
||||
$values[ $k ] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update only */
|
||||
if ( isset( \IPS\Request::i()->updateOnly ) )
|
||||
{
|
||||
$formattedValues = $stream->formatFormValues( $values );
|
||||
|
||||
|
||||
foreach ( array( 'include_comments', 'classes', 'containers', 'clubs', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' ) as $k )
|
||||
{
|
||||
$requestKey = 'stream_' . $k;
|
||||
if ( isset( $formattedValues[ $k ] ) AND $stream->$k != $formattedValues[ $k ] )
|
||||
|
||||
if ( array_key_exists( $k, $formattedValues ) AND $stream->$k != $formattedValues[ $k ] )
|
||||
{
|
||||
$stream->$k = $formattedValues[ $k ];
|
||||
$stream->baseUrl = $stream->baseUrl->setQueryString( 'stream_' . $k, \IPS\Request::i()->$requestKey );
|
||||
|
||||
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,9 +232,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
$where[] = array( 'core_message_topic_user_map.map_has_unread=1' );
|
||||
}
|
||||
|
||||
/* Add a folder filter */
|
||||
if ( isset( \IPS\Request::i()->folder ) or !is_null( $folder ) )
|
||||
|
||||
/* Add a folder filter, if we are not coming from the Messages menu */
|
||||
if ( !isset( \IPS\Request::i()->_fromMenu ) )
|
||||
{
|
||||
if ( !is_null( $folder ) AND isset( $folders[ $folder ] ) )
|
||||
{
|
||||
@@ -252,6 +252,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
/* Limit result set to prevent time outs */
|
||||
$where[] = array( 'core_message_topic_user_map.map_last_topic_reply > ?', \IPS\DateTime::ts( time() )->sub( new \DateInterval( 'P1Y' ) )->getTimeStamp() );
|
||||
|
||||
$subQuery = \IPS\Db::i()->select( 'map_topic_id', array( 'core_message_topic_user_map', 'core_message_topic_user_map' ), $where );
|
||||
$where = array( array( 'core_message_posts.msg_topic_id IN (?)', $subQuery ) );
|
||||
$query = array();
|
||||
@@ -283,7 +286,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
/* Get a count */
|
||||
try
|
||||
{
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_message_posts', $where, NULL, NULL, 'msg_topic_id' )
|
||||
$count = \IPS\Db::i()->select( 'COUNT( DISTINCT(msg_topic_id) )', 'core_message_posts', array_merge( $where, array( array( 'core_message_topic_user_map.map_last_topic_reply > ?', \IPS\DateTime::ts( time() )->sub( new \DateInterval( 'P1Y' ) )->getTimeStamp() ) ) ) )
|
||||
->join(
|
||||
'core_message_topics',
|
||||
'core_message_posts.msg_topic_id=core_message_topics.mt_id'
|
||||
@@ -416,10 +419,17 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->conversation( $conversation, $folders );
|
||||
}
|
||||
elseif( \IPS\Request::i()->q )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, FALSE, $folders ),
|
||||
'pagination' => $pagination
|
||||
) );
|
||||
}
|
||||
elseif( \IPS\Request::i()->overview )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE, $folders ),
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, \IPS\Request::i()->_fromMenu ? FALSE : TRUE, $folders ),
|
||||
'pagination' => $pagination,
|
||||
'listBaseUrl' => $listUrl->setQueryString( array( 'sortBy' => \IPS\Request::i()->sortBy, 'filter' => \IPS\Request::i()->filter ) )->stripQueryString( 'id' )
|
||||
) );
|
||||
@@ -431,7 +441,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->template( $folder, $folders, $folderCounts, $conversations, $pagination, $conversation, $baseUrl, ( $conversation ? 'messenger_convo' : 'messenger' ), ( \IPS\Request::i()->sortBy ? htmlspecialchars( \IPS\Request::i()->sortBy, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ): 'mt_last_post_time' ), ( \IPS\Request::i()->filter ? htmlspecialchars( \IPS\Request::i()->filter, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ) : '' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->template( $folder, $folders, $folderCounts, $conversations, $pagination, $conversation, $baseUrl, ( $conversation ? 'messenger_convo' : 'messenger' ), ( \IPS\Request::i()->sortBy ? htmlspecialchars( \IPS\Request::i()->sortBy, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ): 'mt_last_post_time' ), ( \IPS\Request::i()->filter ? htmlspecialchars( \IPS\Request::i()->filter, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ) : '' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,8 +469,13 @@ class _messenger extends \IPS\Content\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$folders = json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE );
|
||||
array_walk( $folders, function( &$val )
|
||||
{
|
||||
$val = htmlspecialchars( $val, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8' );
|
||||
} );
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'move_message_to', NULL, FALSE, array( 'options' => array_merge( array( 'myconvo' => 'inbox' ), $folders ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'move_message_to', NULL, FALSE, array( 'options' => array_merge( array( 'myconvo' => \IPS\Member::loggedIn()->language()->addToStack('inbox') ), $folders ), 'parse' => 'normal' ) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -742,6 +757,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
$ids[] = $member->member_id;
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'private_message_added', $conversation, array( $conversation, \IPS\Member::loggedIn() ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,35 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _modcp extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Dispatcher looks for methods to match do param, which may exist in the extension files, so this method
|
||||
* prevents dispatcher throwing a 2S106/1 and allows the extensions to use the values
|
||||
*
|
||||
* @param string $method Desired method
|
||||
* @param array $args Arguments
|
||||
* @return void
|
||||
*/
|
||||
public function __call( $method, $args )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->do ) )
|
||||
{
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'overview';
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModCp', TRUE ) as $key => $extension )
|
||||
{
|
||||
if( method_exists( $extension, 'getTab' ) and mb_strtolower( $extension->getTab() ) == mb_strtolower( $activeTab ) )
|
||||
{
|
||||
if ( method_exists( $extension, \IPS\Request::i()->do ) )
|
||||
{
|
||||
return $this->manage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Still here? */
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C139/5', 404, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Moderator Control Panel
|
||||
*
|
||||
@@ -45,6 +74,9 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'overview';
|
||||
$tabs = array( 'reports' => array(), 'approval' => array() );
|
||||
$content = '';
|
||||
|
||||
$approvalQueueCount = 0;
|
||||
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModCp', TRUE ) as $key => $extension )
|
||||
{
|
||||
if( method_exists( $extension, 'getTab' ) )
|
||||
@@ -55,6 +87,12 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$tabs[ $tab ][] = $key;
|
||||
}
|
||||
|
||||
/* Get the count for the approval queue from the extension */
|
||||
if( $tab == 'approval' )
|
||||
{
|
||||
$approvalQueueCount = $extension->getApprovalQueueCount( false );
|
||||
}
|
||||
}
|
||||
|
||||
if( mb_strtolower( $extension->getTab() ) == mb_strtolower( $activeTab ) )
|
||||
@@ -113,22 +151,6 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the count for the approval queue. If the community has a lot of data in the search index, thid can take a long
|
||||
time, so we cache for a short while */
|
||||
try
|
||||
{
|
||||
$approvalQueueCount = \IPS\Data\Cache::i()->getWithExpire( 'modCpApprovalQueueCount_' . \IPS\Member::loggedIn()->member_id, TRUE );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$approvalQueueCount = \IPS\Content\Search\Query::init()->setHiddenFilter( \IPS\Content\Search\Query::HIDDEN_UNAPPROVED )->count();
|
||||
if ( \IPS\Settings::i()->clubs and \IPS\Settings::i()->clubs_require_approval and \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$approvalQueueCount += \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs', 'approved=0' )->first();
|
||||
}
|
||||
\IPS\Data\Cache::i()->storeWithExpire( 'modCpApprovalQueueCount_' . \IPS\Member::loggedIn()->member_id, $approvalQueueCount, \IPS\DateTime::create()->add( new \DateInterval( 'PT15M' ) ), TRUE );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/modcp.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/modcp_responsive.css' ) );
|
||||
|
||||
@@ -36,76 +36,43 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session\Front::i()->setTheme( \IPS\Member::loggedIn()->skin ?: 0 );
|
||||
session_write_close();
|
||||
|
||||
$notInMyName = array();
|
||||
foreach( \IPS\Member\Group::groups() as $group )
|
||||
{
|
||||
if ( $group->g_hide_online_list )
|
||||
{
|
||||
$notInMyName[] = $group->g_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initial filters */
|
||||
$subWhere = array(
|
||||
array( "s.running_time>?", \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ),
|
||||
array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_SPIDER )
|
||||
);
|
||||
if ( !\IPS\Member::loggedIn()->isAdmin() )
|
||||
{
|
||||
$subWhere[] = array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS );
|
||||
}
|
||||
|
||||
if ( count( $notInMyName ) )
|
||||
{
|
||||
$subWhere[] = array( \IPS\Db::i()->in( 's.member_group', $notInMyName, TRUE ) );
|
||||
}
|
||||
|
||||
/* Ok, this looks odd, but the ONLY_FULL_GROUP_BY bites us here, so selecting max(id) allows us to return a session ID even though we're grouping on member_id */
|
||||
$where = array( array( "( core_sessions.id IN(?) OR ( core_sessions.member_id IS NULL AND core_sessions.login_type != ? AND core_sessions.running_time > ?) )", \IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $subWhere, NULL, NULL, 'member_id' ), \IPS\Session\Front::LOGIN_TYPE_SPIDER, \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ) );
|
||||
|
||||
if ( count( $notInMyName ) )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'core_sessions.member_group', $notInMyName, TRUE ) );
|
||||
}
|
||||
|
||||
/* Create the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_sessions', \IPS\Http\Url::internal( 'app=core&module=online&controller=online', 'front', 'online' ), $where );
|
||||
$table = new \IPS\core\Online\Table( \IPS\Http\Url::internal( 'app=core&module=online&controller=online', 'front', 'online' ) );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' ), 'onlineUsersTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' ), 'onlineUsersRow' );
|
||||
$table->langPrefix = 'online_users_';
|
||||
$table->include = array( 'photo', 'member_name', 'location_lang', 'running_time', 'ip_address', 'login_type' );
|
||||
$table->limit = 30;
|
||||
$table->noSort = array( 'photo', 'location_lang' );
|
||||
|
||||
/* Custom parsers */
|
||||
$table->parsers = array(
|
||||
'location_lang' => function( $val, $row )
|
||||
'location_lang' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Session\Front::getLocation( $row );
|
||||
},
|
||||
'photo' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( \IPS\Member::load( $row['member_id'] ), 'mini' );
|
||||
},
|
||||
'running_time' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->relative();
|
||||
},
|
||||
'member_name' => function( $val, $row )
|
||||
{
|
||||
if( $row['member_id'] )
|
||||
{
|
||||
return \IPS\Session\Front::getLocation( $row );
|
||||
},
|
||||
'photo' => function( $val, $row )
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $row['member_id'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( \IPS\Member::load( $row['member_id'] ), 'mini' );
|
||||
},
|
||||
'running_time' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->relative();
|
||||
},
|
||||
'member_name' => function( $val, $row )
|
||||
{
|
||||
if( $row['member_id'] )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $row['member_id'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'guest' );
|
||||
}
|
||||
},
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'guest' );
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
$table->filters = array(
|
||||
'filter_loggedin' => 'core_sessions.member_id <> 0',
|
||||
'filter_loggedin' => 'filter_loggedin',
|
||||
);
|
||||
|
||||
foreach ( \IPS\Member\Group::groups( TRUE, TRUE, TRUE ) as $group )
|
||||
@@ -123,29 +90,18 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $group->g_id == \IPS\Settings::i()->guest_group )
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_id IS NULL';
|
||||
$table->filters[ 'group_' . $group->g_id ] = $group->g_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_group=' . $group->g_id;
|
||||
$table->filters[ 'group_' . $group->g_id ] = $group->g_id;
|
||||
}
|
||||
}
|
||||
|
||||
$table->sortBy = $table->sortBy ?: 'running_time';
|
||||
$table->sortDirection = $table->sortDirection ?: 'desc';
|
||||
|
||||
/* Get the count */
|
||||
$counter = \IPS\Db::i()->select( 'COUNT(*)', 'core_sessions', $where );
|
||||
|
||||
foreach( $table->joins as $join )
|
||||
{
|
||||
$counter = $counter->join( $join['from'], $join['where'] );
|
||||
}
|
||||
|
||||
$totalCount = $counter->first();
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('online_users');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' )->onlineUsersList( (string) $table, $totalCount );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' )->onlineUsersList( (string) $table, $table->count );
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C356/5', 404, '' );
|
||||
}
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) and $promote->added_by != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C366/2', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$object = $class::load( $id );
|
||||
@@ -57,13 +62,87 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C356/7', 404, '' );
|
||||
}
|
||||
|
||||
$title = NULL;
|
||||
$settings = $promote->form_data;
|
||||
|
||||
if ( ! empty( $settings['internal']['title'] ) )
|
||||
{
|
||||
$title = $settings['internal']['title'];
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'save' );
|
||||
$form->class = 'ipsForm_vertical cPromoteDialog';
|
||||
$form->attributes = array( 'data-controller' => 'core.front.system.promote' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'promote_social_title_internal', $title, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\TextArea( 'promote_internal_text', $promote->getText('internal'), FALSE, array( 'rows' => 10 ) ) );
|
||||
|
||||
/* Existing media */
|
||||
try
|
||||
{
|
||||
if ( $images = $object->contentImages( 20 ) )
|
||||
{
|
||||
$form->addHtml( \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialogImages( $images, $promote ) );
|
||||
}
|
||||
}
|
||||
catch( \BadMethodCallException $e ) { }
|
||||
|
||||
/* Upload box */
|
||||
$existingMedia = array();
|
||||
if ( $promote )
|
||||
{
|
||||
foreach( $promote->media as $file )
|
||||
{
|
||||
try
|
||||
{
|
||||
$existingMedia[] = \IPS\File::get( 'core_Promote', $file );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
}
|
||||
|
||||
$uploader = new \IPS\Helpers\Form\Upload( 'promote_media', $existingMedia, FALSE, array(
|
||||
'multiple' => TRUE,
|
||||
'storageExtension' => 'core_Promote',
|
||||
'maxFiles' => 10,
|
||||
'image' => TRUE,
|
||||
'maxFileSize' => 3,
|
||||
) );
|
||||
|
||||
$form->add( $uploader );
|
||||
|
||||
/* Saving? */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Content images */
|
||||
$saveImages = array();
|
||||
if ( $images )
|
||||
{
|
||||
foreach( $images as $image )
|
||||
{
|
||||
foreach( $image as $extension => $path )
|
||||
{
|
||||
if ( \IPS\Request::i()->attach_files and in_array( $path, array_keys( \IPS\Request::i()->attach_files ) ) )
|
||||
{
|
||||
$saveImages[] = array( $extension => $path );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$media = array();
|
||||
if ( is_array( $values['promote_media'] ) )
|
||||
{
|
||||
foreach( $values['promote_media'] as $key => $file )
|
||||
{
|
||||
$media[] = (string) $file;
|
||||
}
|
||||
}
|
||||
|
||||
$settings['internal']['title'] = $values['promote_social_title_internal'];
|
||||
|
||||
$promote->images = $saveImages;
|
||||
$promote->media = $media;
|
||||
$promote->form_data = $settings;
|
||||
$promote->setText( 'internal', $values['promote_internal_text'] );
|
||||
$promote->save();
|
||||
|
||||
@@ -129,6 +208,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
/* Create the table */
|
||||
$table = new \IPS\core\Promote\Table( \IPS\Http\Url::internal( 'app=core&module=promote&controller=promote&do=view', 'front', 'promote_manage' ) );
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) )
|
||||
{
|
||||
$table->setMember( \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_promote.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/promote.css' ) );
|
||||
|
||||
@@ -160,6 +244,12 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
try
|
||||
{
|
||||
$item = \IPS\core\Promote::load( \IPS\Request::i()->promote_id );
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) and $item->added_by != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C366/1', 403, '' );
|
||||
}
|
||||
|
||||
$item->delete();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=promote&controller=promote&do=view', 'front', 'promote_manage' ), 'promote_item_deleted' );
|
||||
@@ -228,6 +318,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
if( !$class OR !class_exists( $class ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
$object = $class::load( $id );
|
||||
}
|
||||
catch ( \Exception $ex )
|
||||
@@ -405,6 +500,8 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$text = array();
|
||||
$shareTo = array();
|
||||
$processedForms = array();
|
||||
|
||||
foreach( $services as $service )
|
||||
{
|
||||
$key = mb_strtolower( $service->key );
|
||||
@@ -413,9 +510,10 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
$text[ $key ] = $values[ 'promote_social_content_' . $key ];
|
||||
$shareTo[] = $key;
|
||||
}
|
||||
|
||||
$processedForms[ $key ] = $service->processPromoteForm( $values );
|
||||
}
|
||||
|
||||
|
||||
$media = array();
|
||||
if ( is_array( $values['promote_media'] ) )
|
||||
{
|
||||
@@ -481,6 +579,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
$promote->share_to = $shareTo;
|
||||
$promote->failed = 0; # Reset the failed flag if we're re-promoting
|
||||
$promote->sent = 0;
|
||||
$promote->form_data = $processedForms;
|
||||
$promote->save();
|
||||
|
||||
if ( isset( \IPS\Request::i()->promote_id ) )
|
||||
@@ -496,7 +595,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialog( \IPS\Member::loggedIn()->language()->addToStack('promote_social_title'), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'promote', 'core' ) ), 'promoteDialogTemplate' ) ), $existing, $object );
|
||||
$output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialog( \IPS\Member::loggedIn()->language()->addToStack('promote_social_title'), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'promote', 'core' ) ), 'promoteDialogTemplate' ), $existing, $object ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'tags', \IPS\Request::i()->tags );
|
||||
}
|
||||
|
||||
$types = $this->_contentTypes();
|
||||
$types = static::contentTypes();
|
||||
|
||||
/* Flood control */
|
||||
\IPS\Request::floodCheck();
|
||||
@@ -199,8 +199,16 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
foreach( $groups as $_idx => $groupId )
|
||||
{
|
||||
if( \IPS\Member\Group::load( $groupId )->g_bitoptions['gbw_hide_group'] )
|
||||
try
|
||||
{
|
||||
if( \IPS\Member\Group::load( $groupId )->g_bitoptions['gbw_hide_group'] )
|
||||
{
|
||||
unset( $groups[ $_idx ] );
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
/* Group didn't exist, so let's ignore it */
|
||||
unset( $groups[ $_idx ] );
|
||||
}
|
||||
}
|
||||
@@ -339,9 +347,10 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Set content type */
|
||||
if ( isset( \IPS\Request::i()->type ) and array_key_exists( \IPS\Request::i()->type, $types ) )
|
||||
{
|
||||
$class = $types[ \IPS\Request::i()->type ];
|
||||
|
||||
if ( isset( \IPS\Request::i()->item ) )
|
||||
{
|
||||
$class = $types[ \IPS\Request::i()->type ];
|
||||
try
|
||||
{
|
||||
$item = $class::loadAndCheckPerms( \IPS\Request::i()->item );
|
||||
@@ -392,19 +401,19 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_comments', \IPS\Request::i()->search_min_comments );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_comments', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_comments ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_replies ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_replies ) AND isset( $class::$commentClass ) )
|
||||
{
|
||||
$filter->minimumComments( \IPS\Request::i()->search_min_replies + 1 );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_replies', \IPS\Request::i()->search_min_replies );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_replies', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_replies ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_reviews ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_reviews ) AND isset( $class::$reviewClass ) )
|
||||
{
|
||||
$filter->minimumReviews( \IPS\Request::i()->search_min_reviews );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_reviews', \IPS\Request::i()->search_min_reviews );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_reviews', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_reviews ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_views ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_views ) AND isset( $class::$databaseColumnMap['views'] ) )
|
||||
{
|
||||
$filter->minimumViews( \IPS\Request::i()->search_min_views );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_views', \IPS\Request::i()->search_min_views );
|
||||
@@ -429,7 +438,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Filter by club */
|
||||
if ( isset( \IPS\Request::i()->club ) )
|
||||
if ( isset( \IPS\Request::i()->club ) AND \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$clubIds = array();
|
||||
$clubNames = array();
|
||||
@@ -521,12 +530,16 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
$tagList = array_map( function( $val )
|
||||
{
|
||||
return '\'' . htmlentities( $val, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . '\'';
|
||||
return '\'' . htmlentities( $val, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . '\'';
|
||||
}, explode( ',', \IPS\Request::i()->tags ) );
|
||||
}
|
||||
$title = '';
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
\IPS\core\Facebook\Pixel::i()->Search = array(
|
||||
'search_string' => \IPS\Request::i()->q
|
||||
);
|
||||
|
||||
if ( \IPS\Request::i()->tags )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->eitherTermsOrTags ) and \IPS\Request::i()->eitherTermsOrTags === 'and' )
|
||||
@@ -588,10 +601,11 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'sortby', \IPS\Request::i()->sortby );
|
||||
|
||||
$flags = ( isset( \IPS\Request::i()->eitherTermsOrTags ) and \IPS\Request::i()->eitherTermsOrTags === 'and' ) ? \IPS\Content\Search\Query::TERM_AND_TAGS : \IPS\Content\Search\Query::TERM_OR_TAGS;
|
||||
|
||||
if ( isset( \IPS\Request::i()->search_and_or ) and \IPS\Request::i()->search_and_or === 'or' )
|
||||
$operator = NULL;
|
||||
|
||||
if ( isset( \IPS\Request::i()->search_and_or ) and in_array( \IPS\Request::i()->search_and_or, array( \IPS\Content\Search\Query::OPERATOR_OR, \IPS\Content\Search\Query::OPERATOR_AND ) ) )
|
||||
{
|
||||
$flags = $flags | \IPS\Content\Search\Query::TERM_OR_MODE;
|
||||
$operator = \IPS\Request::i()->search_and_or;
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_and_or', \IPS\Request::i()->search_and_or );
|
||||
}
|
||||
|
||||
@@ -605,7 +619,8 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$results = $query->search(
|
||||
isset( \IPS\Request::i()->q ) ? ( \IPS\Request::i()->q ) : NULL,
|
||||
isset( \IPS\Request::i()->tags ) ? explode( ',', \IPS\Request::i()->tags ) : NULL,
|
||||
$flags + \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY
|
||||
$flags + \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY,
|
||||
$operator
|
||||
);
|
||||
|
||||
/* Get pagination */
|
||||
@@ -622,7 +637,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* There's no point resetting the page at this point as the search query has been run and no results have been found */
|
||||
$_SESSION['lastSearch'] = 0;
|
||||
\IPS\Output::i()->redirect( $baseUrl->setQueryString( 'page', 1 ) );
|
||||
\IPS\Output::i()->redirect( $baseUrl->setQueryString( 'page', 1 ), NULL, 303 );
|
||||
}
|
||||
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, $pages, $page, $query->resultsToGet ) );
|
||||
@@ -690,7 +705,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Types */
|
||||
$types = array( '' => 'search_everything' );
|
||||
$contentTypes = $this->_contentTypes();
|
||||
$contentTypes = static::contentTypes();
|
||||
$contentToggles = array();
|
||||
$typeFields = array();
|
||||
$typeFieldToggles = array('' => array( 'club' ) );
|
||||
@@ -742,7 +757,13 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$types[ $k ] = $k . '_pl';
|
||||
if ( $k !== 'core_members' )
|
||||
{
|
||||
$typeFieldToggles[ $k ] = array_merge( $contentToggles, array( $k . '_node', 'search_min_views' ) );
|
||||
$typeFieldToggles[ $k ][] = $k . '_node';
|
||||
|
||||
if( isset( $class::$databaseColumnMap['views'] ) )
|
||||
{
|
||||
$typeFieldToggles[ $k ][] = 'search_min_views';
|
||||
}
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
if ( $class::$firstCommentRequired )
|
||||
@@ -768,23 +789,26 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Term */
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'q' ), NULL, 'search_tab_all' );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'tags', \IPS\Request::i()->tags, FALSE, array( 'autocomplete' => TRUE ), NULL, NULL, NULL, 'tags' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'tags', \IPS\Request::i()->tags, FALSE, array( 'autocomplete' => array( 'minimized' => FALSE ) ), NULL, NULL, NULL, 'tags' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'eitherTermsOrTags', \IPS\Request::i()->eitherTermsOrTags, FALSE, array( 'options' => array( 'or' => 'termsortags_or_desc', 'and' => 'termsortags_and_desc' ) ), NULL, NULL, NULL, 'eitherTermsOrTags' ), NULL, 'search_tab_content' );
|
||||
|
||||
/* Author */
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'author', NULL, FALSE, array(), NULL, NULL, NULL, 'author' ), NULL, 'search_tab_content' );
|
||||
|
||||
/* Club */
|
||||
$clubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE );
|
||||
if ( count( $clubs ) )
|
||||
if( \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$clubOptions = array();
|
||||
foreach ( $clubs as $club )
|
||||
$clubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE );
|
||||
if ( is_object( $clubs ) AND $clubs->count( TRUE ) )
|
||||
{
|
||||
$clubOptions[ "c{$club->id}" ] = $club->name;
|
||||
$clubOptions = array();
|
||||
foreach ( $clubs as $club )
|
||||
{
|
||||
$clubOptions[ "c{$club->id}" ] = $club->name;
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'club', NULL, FALSE, array( 'options' => $clubOptions, 'parse' => 'normal', 'multiple' => TRUE, 'noDefault' => TRUE, 'class' => 'ipsField_fullWidth' ), NULL, NULL, NULL, 'club' ), NULL, 'search_tab_content' );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'club', NULL, FALSE, array( 'options' => $clubOptions, 'parse' => 'normal', 'multiple' => TRUE, 'noDefault' => TRUE, 'class' => 'ipsContained' ), NULL, NULL, NULL, 'club' ), NULL, 'search_tab_content' );
|
||||
}
|
||||
|
||||
/* Dates */
|
||||
@@ -795,15 +819,29 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Other filters */
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_in', \IPS\Request::i()->search_in, FALSE, array( 'options' => array( 'all' => 'titles_and_body', 'titles' => 'titles_only' ) ), NULL, NULL, NULL, 'searchIn' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_and_or', \IPS\Request::i()->search_and_or, FALSE, array( 'options' => array( 'and' => 'search_and', 'or' => 'search_or' ) ), NULL, NULL, NULL, 'andOr' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_and_or', isset( \IPS\Request::i()->search_and_or ) ? \IPS\Request::i()->search_and_or : \IPS\Settings::i()->search_default_operator, FALSE, array( 'options' => array( 'and' => 'search_and', 'or' => 'search_or' ) ), NULL, NULL, NULL, 'andOr' ), NULL, 'search_tab_content' );
|
||||
|
||||
/* Nodes */
|
||||
foreach ( $contentTypes as $k => $class )
|
||||
{
|
||||
if ( isset( $class::$containerNodeClass ) )
|
||||
{
|
||||
$nodes = NULL;
|
||||
|
||||
/* If we have a node type, we should only select nodes for that type */
|
||||
if( isset( \IPS\Request::i()->type ) AND !empty( \IPS\Request::i()->type ) )
|
||||
{
|
||||
$typeInfo = explode( '_', \IPS\Request::i()->type );
|
||||
$typeClass = 'IPS\\' . $typeInfo[0] . '\\' . mb_ucfirst( $typeInfo[1] );
|
||||
|
||||
if( $typeClass == $class )
|
||||
{
|
||||
$nodes = ( isset( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$nodeClass = $class::$containerNodeClass;
|
||||
$field = new \IPS\Helpers\Form\Node( $k . '_node', ( isset( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : NULL, FALSE, array( 'class' => $nodeClass, 'multiple' => TRUE, 'permissionCheck' => $nodeClass::searchableNodesPermission(), 'forceOwner' => FALSE, 'clubs' => \IPS\IPS::classUsesTrait( $nodeClass, 'IPS\Content\ClubContainer' ) ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field = new \IPS\Helpers\Form\Node( $k . '_node', $nodes, FALSE, array( 'class' => $nodeClass, 'subnodes' => FALSE, 'multiple' => TRUE, 'permissionCheck' => $nodeClass::searchableNodesPermission(), 'forceOwner' => FALSE, 'clubs' => ( \IPS\Settings::i()->clubs AND \IPS\IPS::classUsesTrait( $nodeClass, 'IPS\Content\ClubContainer' ) ) ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $nodeClass::$nodeTitle );
|
||||
$form->add( $field, NULL, 'search_tab_nodes' );
|
||||
}
|
||||
@@ -1018,12 +1056,57 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle quicksearch and redirect to correct results page
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function quicksearch()
|
||||
{
|
||||
$query = array();
|
||||
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
$query['q'] = \IPS\Request::i()->q;
|
||||
|
||||
if ( \IPS\Request::i()->type != 'all' )
|
||||
{
|
||||
if ( mb_substr( \IPS\Request::i()->type, 0, 11 ) === 'contextual_' )
|
||||
{
|
||||
if ( $json = json_decode( mb_substr( \IPS\Request::i()->type, 11 ), TRUE ) )
|
||||
{
|
||||
foreach ( $json as $k => $v )
|
||||
{
|
||||
$query[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$query['type'] = \IPS\Request::i()->type;
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->search_and_or != \IPS\Settings::i()->search_default_operator )
|
||||
{
|
||||
$query['search_and_or'] = \IPS\Request::i()->search_and_or;
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->search_in == 'titles' )
|
||||
{
|
||||
$query['search_in'] = 'titles';
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=search&controller=search', 'front', 'search' )->setQueryString( $query ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the different content type extensions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _contentTypes()
|
||||
public static function contentTypes()
|
||||
{
|
||||
$types = array();
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
@@ -1039,7 +1122,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/**
|
||||
* Splits the search term into distinct matches
|
||||
* e.g. one "two three" beccomes ['one', 'two three']
|
||||
* e.g. one "two three" becomes ['one', 'two three']
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -1050,10 +1133,12 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$words = preg_split("/[\s]*\\\"([^\\\"]+)\\\"[\s]*|[\s]*'([^']+)'[\s]*|[\s]+/", \IPS\Request::i()->q, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
$words = \IPS\Content\Search\Index::i()->stemmedTerms( $words );
|
||||
|
||||
foreach( $words as $idx => $word )
|
||||
{
|
||||
$words[ $idx ] = htmlentities( $word, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ); // ENT_QUOTES is because this will go in a HTML attribute (data-term="$value") so if you include a single quote in your search query, it can break
|
||||
$words[ $idx ] = htmlentities( $word, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ); // ENT_QUOTES is because this will go in a HTML attribute (data-term="$value") so if you include a single quote in your search query, it can break
|
||||
}
|
||||
|
||||
return json_encode( $words );
|
||||
@@ -1066,6 +1151,6 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function globalFilterOptions()
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'search' )->globalSearchMenuOptions( \IPS\Request::i()->checked ) );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'search' )->globalSearchMenuOptions( explode( ',', \IPS\Request::i()->exclude ) ) );
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,8 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
$results[] = array(
|
||||
'id' => $member->member_id,
|
||||
'value' => $member->name,
|
||||
'name' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->group['prefix'] . htmlspecialchars( $member->name, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . $member->group['suffix'] : htmlspecialchars( $member->name, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'extra' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? htmlspecialchars( $member->email, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) : $member->groupName,
|
||||
'name' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->group['prefix'] . htmlspecialchars( $member->name, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . $member->group['suffix'] : htmlspecialchars( $member->name, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'extra' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? htmlspecialchars( $member->email, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) : $member->groupName,
|
||||
'photo' => (string) $member->photo,
|
||||
);
|
||||
}
|
||||
@@ -342,9 +342,9 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
$return['notifications']['data'][] = array(
|
||||
'id' => $notification->id,
|
||||
'title' => htmlspecialchars( $data['title'], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $data['title'], ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $data['url'],
|
||||
'content' => isset( $data['content'] ) ? htmlspecialchars( $data['content'], \IPS\HTMLENTITIES, 'UTF-8', FALSE ) : NULL,
|
||||
'content' => isset( $data['content'] ) ? htmlspecialchars( $data['content'], ENT_DISALLOWED, 'UTF-8', FALSE ) : NULL,
|
||||
'date' => $notification->updated_time->getTimestamp(),
|
||||
'author_photo' => $data['author'] ? $data['author']->photo : NULL
|
||||
);
|
||||
@@ -360,17 +360,24 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
foreach ( \IPS\Db::i()->select( 'map_topic_id', 'core_message_topic_user_map', array( 'map_user_id=? AND map_user_active=1 AND map_has_unread=1 AND map_ignore_notification=0', \IPS\Member::loggedIn()->member_id ), 'map_last_topic_reply DESC', $messagesDifference ) as $conversationId )
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::load( $conversationId );
|
||||
$message = $conversation->comments( 1, 0, 'date', 'desc' );
|
||||
|
||||
$return['messages']['data'][] = array(
|
||||
'id' => $conversation->id,
|
||||
'title' => htmlspecialchars( $conversation->title, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $conversation->url()->setQueryString( 'latest', 1 ),
|
||||
'message' => $message->truncated(),
|
||||
'date' => $message->mapped('date'),
|
||||
'author_photo' => (string) $message->author()->photo
|
||||
);
|
||||
$conversation = \IPS\core\Messenger\Conversation::load( $conversationId );
|
||||
$message = $conversation->comments( 1, 0, 'date', 'desc' );
|
||||
|
||||
if( $message )
|
||||
{
|
||||
$return['messages']['data'][] = array(
|
||||
'id' => $conversation->id,
|
||||
'title' => htmlspecialchars( $conversation->title, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $conversation->url()->setQueryString( 'latest', 1 ),
|
||||
'message' => $message->truncated(),
|
||||
'date' => $message->mapped('date'),
|
||||
'author_photo' => (string) $message->author()->photo
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Log::log( "Private conversation {$conversation->id} titled {$conversation->title} has no messages", 'orphaned_data' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Cookie Policy
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 12 Dec 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cookie Policy
|
||||
*/
|
||||
class _cookies extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Privacy Policy
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=cookies', NULL, 'cookies' ), array(), 'loc_viewing_cookie_policy' );
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('cookies_about') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('cookies_about');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->cookies();
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,6 @@ class _designermode extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function missing()
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( \IPS\Request::i()->id ) ) ), "DESMODE", 500 );
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( intval( \IPS\Request::i()->id ) ) ) ), "4C370/1", 500 );
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
protected function code()
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->code( \IPS\Request::i()->val, \IPS\Request::i()->editorId, md5( uniqid() ), \IPS\Request::i()->lang ?: '' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->code( \IPS\Request::i()->val, \IPS\Request::i()->editorId, md5( mt_rand() ), \IPS\Request::i()->lang ?: '' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +155,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = \IPS\Request::i()->title ?: $url;
|
||||
$title = \IPS\Request::i()->title ?: (string) $url;
|
||||
$insert = "<a href='{$url}' ipsNoEmbed='true'>{$title}</a>";
|
||||
}
|
||||
|
||||
@@ -178,41 +178,42 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Emoticons Configuration
|
||||
* Get Emoji
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function emoticons()
|
||||
protected function emoji()
|
||||
{
|
||||
$emoticons = array();
|
||||
$emoji = ( \IPS\Settings::i()->emoji_style == 'disabled' or !\IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') ) ? array() : json_decode( file_get_contents( \IPS\ROOT_PATH . '/applications/core/data/emoji.json' ), TRUE );
|
||||
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_emoticons', NULL, 'emo_set_position,emo_position' ) as $row )
|
||||
{
|
||||
if ( !isset( $emoticons[ $row['emo_set'] ] ) )
|
||||
$shortcode = ( \IPS\Settings::i()->emoji_shortcodes and preg_match( '/^:.*:$/', $row['typed'] ) );
|
||||
|
||||
try
|
||||
{
|
||||
$setLang = 'core_emoticon_group_' . $row['emo_set'];
|
||||
|
||||
$emoticons[ $row['emo_set'] ] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( $setLang ),
|
||||
'total' => 0,
|
||||
'emoticons' => array(),
|
||||
);
|
||||
$categoryName = \IPS\Member::loggedIn()->language()->get( 'core_emoticon_group_' . $row['emo_set'] );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$categoryName = '_default';
|
||||
}
|
||||
|
||||
$emoticons[ $row['emo_set'] ]['emoticons'][] = array(
|
||||
'src' => \IPS\File::get( 'core_Emoticons', $row['image'] )->url,
|
||||
'srcset' => $row['image_2x'] ? \IPS\File::get( 'core_Emoticons', $row['image_2x'] )->url . ' 2x' : FALSE,
|
||||
'height' => $row['height'] ?: FALSE,
|
||||
'width' => $row['width'] ?: FALSE,
|
||||
'text' => $row['typed']
|
||||
$emoji[ $row['emo_set'] ][] = array(
|
||||
'code' => 'custom-' . $row['emo_set'] . '-' . $row['id'],
|
||||
'name' => $row['typed'],
|
||||
'skinTone' => false,
|
||||
'shortNames' => $shortcode ? array( trim( $row['typed'], ':' ) ) : array(),
|
||||
'ascii' => $shortcode ? array() : array( $row['typed'] ),
|
||||
'categoryName' => $categoryName,
|
||||
'image' => \IPS\File::get( 'core_Emoticons', $row['image'] )->url,
|
||||
'image2x' => $row['image_2x'] ? \IPS\File::get( 'core_Emoticons', $row['image_2x'] )->url : FALSE,
|
||||
'width' => $row['width'],
|
||||
'height' => $row['height'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $emoticons as $set => $data )
|
||||
{
|
||||
$emoticons[ $set ]['total'] = count( $data['emoticons'] );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $emoticons );
|
||||
\IPS\Output::i()->json( $emoji );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,9 +37,6 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Get the different types */
|
||||
$types = array();
|
||||
|
||||
/* Don't forget Members */
|
||||
$types['core'] = array( 'core_member' => "\IPS\Member" );
|
||||
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
@@ -61,6 +58,9 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't forget Members - add this on to the end so it never defaults UNLESS we only have apps that do not have followable content */
|
||||
$types['core'] = array( 'core_member' => "\IPS\Member" );
|
||||
|
||||
/* What type are we looking at? */
|
||||
$currentAppModule = NULL;
|
||||
@@ -84,11 +84,6 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $_types as $key => $class )
|
||||
{
|
||||
if ( $key == 'core_member' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$currentAppModule = $appModule;
|
||||
$currentType = $key;
|
||||
break 2;
|
||||
|
||||
@@ -31,11 +31,14 @@ class _guidelines extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Settings::i()->gl_type == "none" )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '', 404 ); /* @todo Error code */
|
||||
\IPS\Output::i()->error( 'node_error', '2C380/1', 404, 'guidelines_set_to_none_admin' );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=guidelines', NULL, 'guidelines' ), array(), 'loc_viewing_guidelines' );
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('guidelines') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('guidelines');
|
||||
|
||||
@@ -34,24 +34,47 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Force HTTPs? */
|
||||
if ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and \IPS\Settings::i()->logins_over_https and \IPS\Request::i()->url()->data['scheme'] !== 'https' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
}
|
||||
|
||||
/* Init login class */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
|
||||
/* Init login class */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' ) );
|
||||
|
||||
/* What's our referrer? */
|
||||
$ref = \IPS\Request::i()->ref;
|
||||
|
||||
/* Process */
|
||||
$error = isset( \IPS\Request::i()->_err ) && \IPS\Member::loggedIn()->language()->checkKeyExists( \IPS\Request::i()->_err ) ? \IPS\Request::i()->_err : NULL;
|
||||
$error = NULL;
|
||||
try
|
||||
{
|
||||
$member = $login->authenticate();
|
||||
if ( $member !== NULL )
|
||||
if ( $success = $login->authenticate() )
|
||||
{
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'], \IPS\Login::getDestination(), FALSE, $login->usedHandler );
|
||||
if ( $ref and $ref = @base64_decode( $ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
if ( $success->mfa() )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'destination' => (string) $ref, 'handler' => $success->handler->id );
|
||||
\IPS\Output::i()->redirect( $ref->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
$success->process();
|
||||
|
||||
\IPS\Output::i()->redirect( $ref->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
@@ -59,91 +82,33 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
if ( $e->getCode() === \IPS\Login\Exception::MERGE_SOCIAL_ACCOUNT )
|
||||
{
|
||||
$e->member = $e->member->member_id;
|
||||
$e->handler = $e->handler->id;
|
||||
$_SESSION['linkAccounts'] = json_encode( $e );
|
||||
|
||||
$linkUrl = \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$linkUrl = $linkUrl->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $linkUrl );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' )->setQueryString( 'ref', $ref ), '', 303 );
|
||||
}
|
||||
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() && $error )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'error', 'error' => $error ), 401 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Display Login Form */
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->login( $login->forms(), $error );
|
||||
}
|
||||
/* Display Login Form */
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->login( $login, $ref, $error );
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', NULL, 'login' ), array(), 'loc_logging_in' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the login
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param bool $anonymous If the login is anonymous
|
||||
* @param bool $rememberMe If the "remember me" checkbox was checked
|
||||
* @param \IPS\Http\Url $destination Where to redirect to
|
||||
* @param bool $bypass2FA If true, will not perform 2FA check
|
||||
* @param string $loginHandler Which login handler processed the login
|
||||
* @return void
|
||||
*/
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE, $destination=NULL, $bypass2FA=FALSE, $loginHandler=NULL )
|
||||
{
|
||||
/* Get destination */
|
||||
if ( !$destination )
|
||||
{
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
/* Is this a known device? */
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
|
||||
/* Do we need to do 2FA? */
|
||||
if ( !$bypass2FA and $output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Http\Url::internal( '' ), $member ) )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $member->member_id, 'anonymous' => $anonymous, 'remember' => $rememberMe, 'destination' => (string) $destination, 'handler' => $loginHandler );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
|
||||
{
|
||||
\IPS\Session::i()->setAnon();
|
||||
}
|
||||
|
||||
/* Log device */
|
||||
$device->anonymous = $anonymous and !\IPS\Settings::i()->disable_anonymous;
|
||||
$device->updateAfterAuthentication( $rememberMe, $loginHandler );
|
||||
|
||||
/* Member sync */
|
||||
$member->memberSync( 'onLogin', array( \IPS\Login::getDestination() ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ), '', 303 );
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mfa()
|
||||
{
|
||||
{
|
||||
/* Have we logged in? */
|
||||
$member = NULL;
|
||||
if ( isset( $_SESSION['processing2FA'] ) )
|
||||
@@ -156,7 +121,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Where do we want to go? */
|
||||
$destination = NULL;
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
try
|
||||
{
|
||||
$destination = \IPS\Http\Url::createFromString( $_SESSION['processing2FA']['destination'] );
|
||||
@@ -167,8 +132,9 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
$output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'front', 'login' ), $member );
|
||||
if ( !$output )
|
||||
{
|
||||
$this->_doLogin( $member, $_SESSION['processing2FA']['anonymous'], $_SESSION['processing2FA']['remember'], $destination, TRUE, $_SESSION['processing2FA']['handler'] );
|
||||
{
|
||||
( new \IPS\Login\Success( $member, \IPS\Login\Handler::load( $_SESSION['processing2FA']['handler'] ), $_SESSION['processing2FA']['remember'], $_SESSION['processing2FA']['anonymous'] ) )->process();
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ), '', 303 );
|
||||
}
|
||||
|
||||
/* Nope, just send us where we want to go not logged in */
|
||||
@@ -199,35 +165,36 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function link()
|
||||
{
|
||||
/* Get the member we're linking with */
|
||||
if ( !isset( $_SESSION['linkAccounts'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
$details = json_decode( $_SESSION['linkAccounts'], TRUE );
|
||||
|
||||
$member = \IPS\Member::load( $details['member'] );
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'link_accounts', 'login' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
/* And then handler to link with */
|
||||
$handler = \IPS\Login\Handler::load( $details['handler'] );
|
||||
|
||||
/* Init reauthentication */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' )->setQueryString( 'ref', isset( \IPS\Request::i()->ref ) ? \IPS\Request::i()->ref : NULL ), \IPS\Login::LOGIN_REAUTHENTICATE );
|
||||
$login->reauthenticateAs = $member;
|
||||
$error = NULL;
|
||||
|
||||
/* If successful (or if there's no way to reauthenticate which would only happen if a login handler has been deleted)) complete the link... */
|
||||
try
|
||||
{
|
||||
$form->hiddenValues['ref'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
$form->addDummy( 'email_address', htmlspecialchars( isset( $details['email'] ) ? $details['email'] : $member->email, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'validateFor' => $member ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
try
|
||||
{
|
||||
$class = 'IPS\Login\\' . ucfirst( $details['handler'] );
|
||||
$class::link( $member, $details['details'] );
|
||||
if ( $success = $login->authenticate() or ( !count( $login->usernamePasswordMethods() ) and !count( $login->buttonMethods() ) ) )
|
||||
{
|
||||
$handler->completeLink( $member, $details['details'] );
|
||||
|
||||
unset( $_SESSION['linkAccounts'] );
|
||||
|
||||
$destination = NULL;
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
@@ -240,18 +207,27 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
$this->_doLogin( $member, FALSE, TRUE, $destination, FALSE, $details['handler'] );
|
||||
|
||||
$success = new \IPS\Login\Success( $member, $handler );
|
||||
if ( $success->mfa() )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'destination' => (string) $destination, 'handler' => $success->handler->id );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
$success->process();
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
$form->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
/* Otherwise show the reauthenticate form */
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->mergeSocialAccount( $details['handler'], $member, $form );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->mergeSocialAccount( $handler, $member, $login, $error );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,16 +285,6 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
setcookie( session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] );
|
||||
session_destroy();
|
||||
|
||||
/* Login handler callback */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->logoutAccount( $member, $redirectUrl );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
|
||||
/* Member sync callback */
|
||||
$member->memberSync( 'onLogout', array( $redirectUrl ) );
|
||||
|
||||
@@ -345,7 +311,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* Not logged in as admin? */
|
||||
if ( $admin->member_id != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https )->setQueryString( array( 'ref' => base64_encode( \IPS\Request::i()->url() ), '_err' => 'login_as_user_login' ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( array( 'ref' => base64_encode( \IPS\Request::i()->url() ), '_err' => 'login_as_user_login' ) ) );
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
|
||||
@@ -22,6 +22,26 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( \IPS\Settings::i()->allow_forgot_password == 'disabled' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'page_doesnt_exist', '2S151/2', 404, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->allow_forgot_password == 'redirect' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Settings::i()->allow_forgot_password_target ) );
|
||||
}
|
||||
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
@@ -32,11 +52,7 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( "lostpass", 'request_password' );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'bypassProfanity' => TRUE ), function( $val ){
|
||||
|
||||
/* Check email exists */
|
||||
$member = \IPS\Member::load( $val, 'email' );
|
||||
|
||||
if( !$member->member_id )
|
||||
if( !\IPS\Login::emailIsInUse( $val ) )
|
||||
{
|
||||
throw new \LogicException( 'lost_pass_no_email' );
|
||||
}
|
||||
@@ -47,62 +63,107 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* Handle the reset */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Load the member */
|
||||
/* If using "normal" method and we have an account, and at least one login handler we can process a password change for, we're good */
|
||||
$member = \IPS\Member::load( $values['email_address'], 'email' );
|
||||
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
if ( $member->member_id and \IPS\Settings::i()->allow_forgot_password == 'normal' )
|
||||
{
|
||||
$existing = \IPS\Db::i()->select( array( 'vid', 'email_sent' ), 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) )->first();
|
||||
$vid = $existing['vid'];
|
||||
|
||||
/* If we sent a lost password email within the last 15 minutes, don't send another one otherwise someone could be a nuisence */
|
||||
if ( $existing['email_sent'] and $existing['email_sent'] > ( time() - 900 ) )
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
$sendEmail = FALSE;
|
||||
if ( $method->canChangePassword( $member ) )
|
||||
{
|
||||
return $this->_sendForgotPasswordEmail( $member );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $vid ) );
|
||||
}
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$vid = md5( $member->members_pass_hash . \IPS\Login::generateRandomString() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => $member->member_id,
|
||||
'entry_date' => time(),
|
||||
'lost_pass' => 1,
|
||||
'ip_address' => $member->ip_address,
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
}
|
||||
|
||||
/* Send email */
|
||||
if ( $sendEmail )
|
||||
/* If not, send them to the handler if we can */
|
||||
foreach( \IPS\Login::methods() as $method )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "lost_pass_confirm";
|
||||
if( $method->emailIsInUse( $values['email_address'] ) === TRUE )
|
||||
{
|
||||
if ( $url = $method->forgotPasswordUrl() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have no way to reset the password, can we allow creating a local password as a last attempt? */
|
||||
if ( $member->member_id )
|
||||
{
|
||||
foreach( \IPS\Login::methods() as $method )
|
||||
{
|
||||
if ( $method instanceof \IPS\Login\Handler\Standard )
|
||||
{
|
||||
return $this->_sendForgotPasswordEmail( $member );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, sorry, we can't do this */
|
||||
\IPS\Output::i()->error( 'lost_pass_not_possible', '1S151/3', 403, '' );
|
||||
}
|
||||
|
||||
/* Show form */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPass( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send forgot password email
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @return void
|
||||
*/
|
||||
protected function _sendForgotPasswordEmail( \IPS\Member $member )
|
||||
{
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
{
|
||||
$existing = \IPS\Db::i()->select( array( 'vid', 'email_sent' ), 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) )->first();
|
||||
$vid = $existing['vid'];
|
||||
|
||||
/* If we sent a lost password email within the last 15 minutes, don't send another one otherwise someone could be a nuisence */
|
||||
if ( $existing['email_sent'] and $existing['email_sent'] > ( time() - 900 ) )
|
||||
{
|
||||
$sendEmail = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = "lost_pass_too_soon";
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $vid ) );
|
||||
}
|
||||
|
||||
/* Show confirmation page with further instructions */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPassConfirm( $message );
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$vid = md5( $member->members_pass_hash . \IPS\Login::generateRandomString() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => $member->member_id,
|
||||
'entry_date' => time(),
|
||||
'lost_pass' => 1,
|
||||
'ip_address' => $member->ip_address,
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
}
|
||||
|
||||
/* Send email */
|
||||
if ( $sendEmail )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "lost_pass_confirm";
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPass( $form );
|
||||
$message = "lost_pass_too_soon";
|
||||
}
|
||||
|
||||
/* Show confirmation page with further instructions */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPassConfirm( $message );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,21 +196,17 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* Reset the failed logins storage - we don't need to save because the login handler will do that for us later */
|
||||
$member->failed_logins = array();
|
||||
|
||||
/* Now reset the member's password */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
/* Now reset the member's password. If no handlers accept the change, create a local password */
|
||||
if ( !$member->changePassword( $values['password'], 'lost' ) )
|
||||
{
|
||||
/* We cannot update our password in some login handlers, that's ok */
|
||||
try
|
||||
{
|
||||
$handler->changePassword( $member, $values['password'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
$member->setLocalPassword( $values['password'] );
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Log in, and invalidate all other sessions */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
$member->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( isset( \IPS\Request::i()->cookie['login_key'] ), '' );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( isset( \IPS\Request::i()->cookie['login_key'] ) );
|
||||
|
||||
/* Delete validating record and log in */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) );
|
||||
|
||||
@@ -93,6 +93,8 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function end()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$_SESSION['live_meta_tags'] = FALSE;
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( \IPS\Request::i()->url ) );
|
||||
|
||||
@@ -113,6 +113,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Log if admin mail setting is changed */
|
||||
if ( \IPS\Member::loggedIn()->allow_admin_mails !== $values['allow_admin_mails'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'admin_mails', array( 'enabled' => $values['allow_admin_mails'] ) );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->allow_admin_mails = $values['allow_admin_mails'];
|
||||
\IPS\Member::loggedIn()->auto_track = json_encode( array(
|
||||
'content' => ( is_array( $values['auto_track'] ) AND in_array( 'content', $values['auto_track'] ) ) ? 1 : 0,
|
||||
@@ -168,12 +174,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $ext->classes as $classname )
|
||||
{
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
@@ -182,7 +188,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
{
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
@@ -216,6 +222,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\Member\Club';
|
||||
}
|
||||
|
||||
if ( !$class )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C154/3', 404, '' );
|
||||
@@ -223,7 +234,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
$indexId = NULL;
|
||||
try
|
||||
{
|
||||
if ( in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
@@ -242,17 +252,19 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
elseif ( $class == 'IPS\Member\Club' )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'follow_thing', FALSE, array( 'sprintf' => array( $thing->_title ) ) );
|
||||
\IPS\Output::i()->breadcrumb = array(
|
||||
array( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ), \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs') ),
|
||||
array( $thing->url(), $thing->name )
|
||||
);
|
||||
}
|
||||
elseif ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'follow_thing', FALSE, array( 'sprintf' => array( $thing->mapped('title') ) ) );
|
||||
|
||||
/* Work out the index ID */
|
||||
try
|
||||
{
|
||||
$indexId = \IPS\Content\Search\Index::i()->getIndexId( $thing );
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
/* Set navigation */
|
||||
$container = NULL;
|
||||
@@ -300,7 +312,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$type = 'follower_content';
|
||||
}
|
||||
elseif ( in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
elseif ( $class == 'IPS\Member\Club' or in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
{
|
||||
$type = 'new_comment';
|
||||
}
|
||||
@@ -348,8 +360,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $class != "IPS\Member" )
|
||||
{
|
||||
$options['daily'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily');
|
||||
$options['weekly'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly');
|
||||
if ( $class != "IPS\Member\Club" )
|
||||
{
|
||||
$options['daily'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily');
|
||||
$options['weekly'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly');
|
||||
}
|
||||
$options['none'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_no_notification');
|
||||
}
|
||||
|
||||
@@ -361,7 +376,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
foreach ( $options as $k => $v )
|
||||
{
|
||||
$form->hiddenValues[ $k ] = $v;
|
||||
@@ -401,7 +416,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
'follow_notify_freq' => ( $class == "IPS\Member" ) ? 'immediate' : $values['follow_type'],
|
||||
'follow_notify_sent' => 0,
|
||||
'follow_visible' => 1,
|
||||
'follow_index_id' => $indexId,
|
||||
);
|
||||
if ( $current )
|
||||
{
|
||||
@@ -412,6 +426,33 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
\IPS\Db::i()->insert( 'core_follow', $save );
|
||||
}
|
||||
|
||||
/* Also follow all nodes if following club */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
$save = array(
|
||||
'follow_id' => md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ),
|
||||
'follow_app' => $followApp,
|
||||
'follow_area' => $followArea,
|
||||
'follow_rel_id' => $node['node_id'],
|
||||
'follow_member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'follow_is_anon' => !$values['follow_public'],
|
||||
'follow_added' => time(),
|
||||
'follow_notify_do' => ( isset( $values['follow_type'] ) AND $values['follow_type'] == 'none' ) ? 0 : 1,
|
||||
'follow_notify_meta' => '',
|
||||
'follow_notify_freq' => $values['follow_type'],
|
||||
'follow_notify_sent' => 0,
|
||||
'follow_visible' => 1,
|
||||
);
|
||||
\IPS\Db::i()->insert( 'core_follow', $save, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Send notification if following member */
|
||||
if( $class == "IPS\Member" )
|
||||
{
|
||||
@@ -463,40 +504,46 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', \IPS\Request::i()->id, \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Get class */
|
||||
$class = NULL;
|
||||
foreach ( \IPS\Application::load( \IPS\Request::i()->follow_app )->extensions( 'core', 'ContentRouter' ) as $ext )
|
||||
/* Get class */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
foreach ( $ext->classes as $classname )
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
elseif( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = NULL;
|
||||
foreach ( \IPS\Application::load( \IPS\Request::i()->follow_app )->extensions( 'core', 'ContentRouter' ) as $ext )
|
||||
{
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
foreach ( $ext->classes as $classname )
|
||||
{
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
}
|
||||
if( isset( $classname::$containerFollowClasses ) )
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
}
|
||||
if( isset( $classname::$containerFollowClasses ) )
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
@@ -515,6 +562,19 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
}
|
||||
|
||||
/* Unfollow club areas */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ), \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
@@ -542,9 +602,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
else if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area );
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area );
|
||||
}
|
||||
|
||||
if ( !class_exists( $class ) )
|
||||
@@ -566,6 +630,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$anonymous = $classname::containerFollowers( $thing, $classname::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class == "IPS\Member\Club" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
@@ -617,9 +688,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area );
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area );
|
||||
}
|
||||
if ( !class_exists( $class ) )
|
||||
{
|
||||
@@ -693,6 +768,23 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id ) );
|
||||
|
||||
if( \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
try
|
||||
{
|
||||
$club = \IPS\Member\Club::load( \IPS\Request::i()->follow_id );
|
||||
foreach ( $club->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', $followApp, $followArea, $node['node_id'] ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ), 'followers_removed' );
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class _privacy extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Settings::i()->privacy_type == "none" )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '', 404 ); /* @todo Error code */
|
||||
\IPS\Output::i()->error( 'node_error', '2C381/1', 404, 'privacy_set_to_none_acp' );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
|
||||
@@ -34,11 +34,19 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( \IPS\Settings::i()->base_url );
|
||||
}
|
||||
|
||||
if( !\IPS\Settings::i()->allow_reg and \IPS\Request::i()->do !== 'complete'
|
||||
if( \IPS\Request::i()->do !== 'complete'
|
||||
and \IPS\Request::i()->do !== 'changeEmail' and \IPS\Request::i()->do !== 'validate'
|
||||
and \IPS\Request::i()->do !== 'validating' and \IPS\Request::i()->do !== 'reconfirm' )
|
||||
and \IPS\Request::i()->do !== 'validating' and \IPS\Request::i()->do !== 'reconfirm'
|
||||
and \IPS\Request::i()->do !== 'finish' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_disabled', '2S129/5', 403, '' );
|
||||
if ( \IPS\Login::registrationType() == 'redirect' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Settings::i()->allow_reg_target ) );
|
||||
}
|
||||
elseif ( \IPS\Login::registrationType() == 'disabled' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_disabled', '2S129/5', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
@@ -62,20 +70,20 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
|
||||
/* Quick registration does not work with COPPA */
|
||||
if ( \IPS\Settings::i()->quick_register )
|
||||
if ( \IPS\Login::registrationType() == 'normal' )
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
$form->class = 'ipsForm_fullWidth';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
|
||||
if( (string) \IPS\Request::i()->url() == (string) \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ) )
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) ) );
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -137,7 +145,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
};
|
||||
|
||||
/* Output */
|
||||
@@ -209,18 +217,36 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, '' );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, NULL );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $ref ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +267,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$haveRequired = FALSE;
|
||||
foreach( $steps AS $id => $step )
|
||||
{
|
||||
if ( $step->required )
|
||||
if ( $step->required AND !$step->completed( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$haveRequired = TRUE;
|
||||
break;
|
||||
@@ -253,8 +279,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Nope, forward */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
$wizardSteps = array();
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=finish', 'front', 'register' );
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'ProfileSteps' ) AS $extension )
|
||||
@@ -265,6 +290,8 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$wizardSteps = \IPS\Member\ProfileStep::setOrder( $wizardSteps );
|
||||
|
||||
$wizardSteps = array_merge( $wizardSteps, array( 'profile_done' => function( $data ) {
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'saved' );
|
||||
} ) );
|
||||
@@ -288,11 +315,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$form = new \IPS\Helpers\Form( 'form', 'register_button', NULL, array( 'data-controller' => 'core.front.system.register') );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username', NULL, TRUE, array( 'accountUsername' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE, 'maxLength' => 150, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password', 'bypassProfanity' => TRUE ) ) );
|
||||
|
||||
/* Profile fields */
|
||||
if ( ! \IPS\Settings::i()->quick_register )
|
||||
if ( \IPS\Login::registrationType() == 'full' )
|
||||
{
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
@@ -330,7 +357,15 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $qanda )
|
||||
{
|
||||
$question = \IPS\Db::i()->select( '*', 'core_question_and_answer', array( 'qa_id=?', $qanda ) )->first();
|
||||
try
|
||||
{
|
||||
$question = \IPS\Db::i()->select( '*', 'core_question_and_answer', array( 'qa_id=?', $qanda ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
throw new \DomainException( 'q_and_a_incorrect' );
|
||||
}
|
||||
|
||||
$answers = json_decode( $question['qa_answers'] );
|
||||
|
||||
if( $answers )
|
||||
@@ -380,14 +415,14 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$form->addSeparator();
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', TRUE, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', \IPS\Settings::i()->updates_consent_default == 'enabled' ? TRUE : FALSE, FALSE ) );
|
||||
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms' ) );
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms', array(), \IPS\Http\Url::PROTOCOL_RELATIVE ) );
|
||||
|
||||
/* Build the appropriate links for registration terms & privacy policy */
|
||||
if ( \IPS\Settings::i()->privacy_type == "internal" )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] .= sprintf( \IPS\Member::loggedIn()->language()->get("reg_privacy_link"), \IPS\Http\Url::internal( 'app=core&module=system&controller=privacy', 'front', 'privacy' ), 'data-ipsDialog data-ipsDialog-size="wide" data-ipsDialog-title="' . \IPS\Member::loggedIn()->language()->get("privacy") . '"' );
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] .= sprintf( \IPS\Member::loggedIn()->language()->get("reg_privacy_link"), \IPS\Http\Url::internal( 'app=core&module=system&controller=privacy', 'front', 'privacy', array(), \IPS\Http\Url::PROTOCOL_RELATIVE ), 'data-ipsDialog data-ipsDialog-size="wide" data-ipsDialog-title="' . \IPS\Member::loggedIn()->language()->get("privacy") . '"' );
|
||||
}
|
||||
else if ( \IPS\Settings::i()->privacy_type == "external" )
|
||||
{
|
||||
@@ -478,33 +513,40 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$member = new \IPS\Member;
|
||||
$member->name = $values['username'];
|
||||
$member->email = $values['email_address'];
|
||||
$member->members_pass_salt = $member->generateSalt();
|
||||
$member->members_pass_hash = $member->encryptedPassword( $values['password'] );
|
||||
$member->setLocalPassword( $values['password'] );
|
||||
$member->allow_admin_mails = $values['reg_admin_mails'];
|
||||
$member->member_group_id = \IPS\Settings::i()->member_group;
|
||||
$member->members_bitoptions['view_sigs'] = TRUE;
|
||||
$member->last_visit = time();
|
||||
|
||||
/* Query spam service */
|
||||
$spamCode = NULL;
|
||||
$spamAction = NULL;
|
||||
if( \IPS\Settings::i()->spam_service_enabled )
|
||||
{
|
||||
if( $member->spamService() == 4 )
|
||||
$spamAction = $member->spamService( 'register', NULL, $spamCode );
|
||||
if( $spamAction == 4 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2S129/1', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Initial Save */
|
||||
$member->save();
|
||||
|
||||
/* This looks a bit weird, but the extensions expect an account to exist at this point, so we'll let the system save it now, then do what we need to do, then save again */
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
if ( \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
$extension = $step->extension;
|
||||
$extension::formatFormValues( $values, $member, $form );
|
||||
/* Initial Save */
|
||||
$member->save();
|
||||
|
||||
/* This looks a bit weird, but the extensions expect an account to exist at this point, so we'll let the system save it now, then do what we need to do, then save again */
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
{
|
||||
$extension = $step->extension;
|
||||
$extension::formatFormValues( $values, $member, $form );
|
||||
}
|
||||
}
|
||||
|
||||
/* Save anything the profile extensions did */
|
||||
$member->save();
|
||||
$member->logHistory( 'core', 'account', array( 'type' => 'register', 'spamCode' => $spamCode, 'spamAction' => $spamAction ), FALSE );
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
@@ -550,7 +592,18 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
}
|
||||
|
||||
|
||||
/* Log that we gave consent for admin emails */
|
||||
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => (boolean) $member->allow_admin_mails ) );
|
||||
|
||||
/* Log that we gave consent for terms and privacy */
|
||||
if ( \IPS\Settings::i()->privacy_type != 'none' )
|
||||
{
|
||||
$member->logHistory( 'core', 'terms_acceptance', array( 'type' => 'privacy' ) );
|
||||
}
|
||||
|
||||
$member->logHistory( 'core', 'terms_acceptance', array( 'type' => 'terms' ) );
|
||||
|
||||
/* Handle validation */
|
||||
$member->postRegistration();
|
||||
|
||||
@@ -593,7 +646,13 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* They're not validated but in what way? */
|
||||
if( $validating['user_verified'] )
|
||||
if ( $validating['reg_cancelled'] )
|
||||
{
|
||||
/* They are cancelled and will be deleted, haha, etc */
|
||||
\IPS\Output::i()->error( 'reg_is_cancelled', '2C223/9', 403, '' );
|
||||
|
||||
}
|
||||
else if ( $validating['user_verified'] )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->notAdminValidated();
|
||||
}
|
||||
@@ -690,7 +749,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Check we are an incomplete member */
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
elseif ( \IPS\Member::loggedIn()->real_name and \IPS\Member::loggedIn()->email )
|
||||
{
|
||||
@@ -711,6 +770,17 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE ) ) );
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_agreed_terms', NULL, TRUE, array(), function( $val )
|
||||
{
|
||||
if ( !$val )
|
||||
{
|
||||
throw new \InvalidArgumentException('reg_not_agreed_terms');
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
$form->addButton( 'cancel', 'link', \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=cancel', 'front', 'register' )->csrf() );
|
||||
|
||||
/* Handle the submission */
|
||||
@@ -720,13 +790,16 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Member::loggedIn()->name = $values['username'];
|
||||
}
|
||||
$spamCode = NULL;
|
||||
$spamAction = NULL;
|
||||
if( isset( $values['email_address'] ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->email = $values['email_address'];
|
||||
|
||||
if( \IPS\Settings::i()->spam_service_enabled )
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->spamService() == 4 )
|
||||
$spamAction = \IPS\Member::loggedIn()->spamService( 'register', NULL, $spamCode );
|
||||
if( $spamAction == 4 )
|
||||
{
|
||||
$action = \IPS\Settings::i()->spam_service_action_4;
|
||||
|
||||
@@ -740,9 +813,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
|
||||
/* Save */
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'account', array( 'type' => 'complete' ), FALSE );
|
||||
|
||||
/* Handle validation */
|
||||
\IPS\Member::loggedIn()->postRegistration( ( isset( $values['email_address'] ) ) ? FALSE : TRUE );
|
||||
@@ -751,7 +826,26 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->setType( \IPS\Session\Front::LOGIN_TYPE_MEMBER );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Login::getRegistrationDestination( \IPS\Member::loggedIn() ) );
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
@@ -784,7 +878,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => \IPS\Member::loggedIn() ) ) );
|
||||
$captcha = new \IPS\Helpers\Form\Captcha;
|
||||
if ( (string) $captcha !== '' )
|
||||
{
|
||||
@@ -794,17 +888,33 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Check spam defense whitelist */
|
||||
if( \IPS\Settings::i()->spam_service_enabled AND ( isset( $pending['new_reg'] ) AND $pending['new_reg'] ) AND \IPS\Member::loggedIn()->spamDefenseWhitelist() )
|
||||
{
|
||||
/* We specifically say it's 'register' so that actions are still performed on the account */
|
||||
$newEmailScore = \IPS\Member::loggedIn()->spamService( 'register', $values['new_email'] );
|
||||
|
||||
/* Is it a ban response? */
|
||||
if( $newEmailScore == 4 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2C223/A', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the email */
|
||||
$oldEmail = \IPS\Member::loggedIn()->email;
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
\IPS\Member::loggedIn()->email = $values['new_email'];
|
||||
\IPS\Member::loggedIn()->save();
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
$method->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Member::loggedIn()->memberSync( 'onEmailChange', array( $values['new_email'], $oldEmail ) );
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'email_change', array( 'old' => $oldEmail, 'new' => $values['new_email'], 'by' => 'manual' ) );
|
||||
|
||||
/* Invalidate sessions except this one */
|
||||
\IPS\Member::loggedIn()->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
@@ -879,16 +989,9 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Member sync callback */
|
||||
\IPS\Member::loggedIn()->memberSync( 'onLogout', array( \IPS\Http\Url::internal( '' ) ) );
|
||||
|
||||
/* Login handler callback */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->logoutAccount( \IPS\Member::loggedIn(), \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
|
||||
/* Flag user as having cancelled their registration */
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'reg_cancelled' => time() ), array( 'member_id=? AND new_reg=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'reg_canceled' );
|
||||
@@ -902,23 +1005,27 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
protected function reconfirm()
|
||||
{
|
||||
/* Generate form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form = new \IPS\Helpers\Form( 'reconfirm_checkbox', 'reconfirm_checkbox' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$form->hiddenValues['ref'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reconfirm_checkbox', NULL, FALSE, array(), function( $val )
|
||||
{
|
||||
if ( !$val )
|
||||
{
|
||||
throw new \InvalidArgumentException('reg_not_agreed_terms');
|
||||
}
|
||||
} ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Log that we gave consent */
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'terms_acceptance', array( 'type' => 'privacy' ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'terms_acceptance', array( 'type' => 'terms' ) );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] = FALSE;
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -31,10 +31,10 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( ! \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
}
|
||||
|
||||
$twitter = \IPS\Login::getHandler('Twitter');
|
||||
$twitter = \IPS\Login\Handler::findMethod('IPS\Login\Handler\Oauth1\Twitter');
|
||||
$promote = \IPS\core\Promote::getPromoter( 'Twitter' );
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' );
|
||||
|
||||
@@ -43,8 +43,7 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
/* Get a request token */
|
||||
if ( !isset( \IPS\Request::i()->oauth_token ) )
|
||||
{
|
||||
$callback = $url->setQueryString( 'csrf', \IPS\Session::i()->csrfKey );
|
||||
$response = $twitter->sendRequest( 'get', 'https://api.twitter.com/oauth/request_token', array( 'oauth_callback' => (string) $callback ) )->decodeQueryString('oauth_token');
|
||||
$response = $twitter->requestToken( $url->setQueryString( 'csrf', \IPS\Session::i()->csrfKey ) );
|
||||
\IPS\Output::i()->redirect( "https://api.twitter.com/oauth/authorize?force_login=1&oauth_token={$response['oauth_token']}" );
|
||||
}
|
||||
|
||||
@@ -55,9 +54,7 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Authenticate */
|
||||
$response = $twitter->sendRequest( 'post', 'https://api.twitter.com/oauth/access_token', array( 'oauth_verifier' => \IPS\Request::i()->oauth_verifier ), \IPS\Request::i()->oauth_token )->decodeQueryString('user_id');
|
||||
|
||||
$user = $twitter->sendRequest( 'get', 'https://api.twitter.com/1.1/account/verify_credentials.json', array(), $response['oauth_token'], $response['oauth_token_secret'] )->decodeJson();
|
||||
$response = $twitter->exchangeToken( \IPS\Request::i()->oauth_verifier, \IPS\Request::i()->oauth_token );
|
||||
|
||||
/* Store the settings */
|
||||
$promote->saveSettings( array(
|
||||
@@ -65,17 +62,19 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
'owner' => \IPS\Member::loggedIn()->member_id,
|
||||
'secret' => $response['oauth_token_secret'],
|
||||
'token' => $response['oauth_token'],
|
||||
'name' => $user['screen_name']
|
||||
'name' => $response['screen_name']
|
||||
) );
|
||||
|
||||
/* Show a done page */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('promote_twitter_sorted');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteTwitterComplete( $user );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteTwitterComplete( $response );
|
||||
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
|
||||
\IPS\Log::log( $e, 'twitter_promote' );
|
||||
|
||||
\IPS\Output::i()->error( 'generic_error', '4C375/1', 403, $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,9 @@ class _unsubscribe extends \IPS\Dispatcher\Controller
|
||||
$member->allow_admin_mails = 0;
|
||||
$member->save();
|
||||
|
||||
/* Log it */
|
||||
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => FALSE ) );
|
||||
|
||||
/* And then show them a confirmation screen */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('unsubscribed');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->unsubscribed();
|
||||
|
||||
@@ -81,7 +81,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
/* VSE CSS */
|
||||
if ( isset( $css['core']['front']['custom']['vse.css'] ) )
|
||||
{
|
||||
$functionName = "css_" . uniqid();
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['vse.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$vseCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
if ( isset( $css['core']['front']['custom']['custom.css'] ) )
|
||||
{
|
||||
/* Custom CSS */
|
||||
$functionName = "css_" . uniqid();
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['custom.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$customCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
@@ -133,10 +133,16 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
$options['options'] = $options;
|
||||
break;
|
||||
}
|
||||
|
||||
$field = new $class( "core_theme_setting_title_{$data['sc_id']}", $value, false, $options );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $data['sc_title'], FALSE, array( 'escape' => true ) );
|
||||
$form->add( $field );
|
||||
if ( class_exists( $class ) )
|
||||
{
|
||||
$field = new $class( "core_theme_setting_title_{$data['sc_id']}", $value, false, $options );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $data['sc_title'], FALSE, array( 'escape' => true ) );
|
||||
$form->add( $field );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Log::log( 'VSE tried to load ' . $class . ' for theme setting ' . $key, 'vse_error' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C184/6', 403, '' );
|
||||
}
|
||||
|
||||
|
||||
/* Build the form */
|
||||
$form = \IPS\core\Warnings\Warning::create();
|
||||
$form->class = 'ipsForm_vertical';
|
||||
@@ -165,7 +165,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Axknowledge Warning
|
||||
* Acknowledge Warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -262,7 +262,13 @@ class _warnings extends \IPS\Content\Controller
|
||||
* @return void
|
||||
*/
|
||||
protected function reasonAjax()
|
||||
{
|
||||
{
|
||||
/* Check permission */
|
||||
if ( ! ( \IPS\Settings::i()->warn_on AND \IPS\Member::loggedIn()->modPermission('mod_see_warn') ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C135/9', 403, '' );
|
||||
}
|
||||
|
||||
$remove = array(
|
||||
'date' => NULL,
|
||||
'time' => NULL,
|
||||
@@ -351,6 +357,13 @@ class _warnings extends \IPS\Content\Controller
|
||||
);
|
||||
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Check permission */
|
||||
if ( !( \IPS\Settings::i()->warn_on AND ( \IPS\Member::loggedIn()->modPermission('mod_see_warn') or ( \IPS\Settings::i()->warn_show_own and \IPS\Member::loggedIn()->member_id == $member->member_id ) ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C135/9', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$action = \IPS\Db::i()->select( '*', 'core_members_warn_actions', array( 'wa_points<=?', ( $member->warn_level + \IPS\Request::i()->points ) ), 'wa_points DESC', 1 )->first();
|
||||
|
||||
@@ -68,7 +68,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$block = \IPS\Widget::load( $appOrPlugin, $widget['key'], uniqid(), array(), $widget['restrict'], null );
|
||||
$block = \IPS\Widget::load( $appOrPlugin, $widget['key'], mt_rand(), array(), $widget['restrict'], null );
|
||||
$block->allowReuse = (boolean) $widget['allow_reuse'];
|
||||
$block->menuStyle = $widget['menu_style'];
|
||||
|
||||
@@ -131,12 +131,20 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
|
||||
if ( !isset( $widget ) )
|
||||
{
|
||||
$widget = \IPS\Widget::load( ( $key[0] == 'plugin' ) ? \IPS\Plugin::load( $key[1] ) : \IPS\Application::load( $key[1] ), $key[2], $key[3], array(), null, \IPS\Request::i()->orientation );
|
||||
try
|
||||
{
|
||||
$widget = \IPS\Widget::load( ( $key[0] == 'plugin' ) ? \IPS\Plugin::load( $key[1] ) : \IPS\Application::load( $key[1] ), $key[2], $key[3], array(), null, \IPS\Request::i()->orientation );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$widget = '';
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( (string) $widget );
|
||||
@@ -217,6 +225,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
|
||||
$blocks[ $k ]['configuration'] = $values;
|
||||
\IPS\Db::i()->insert( 'core_widget_areas', array( 'app' => \IPS\Request::i()->pageApp, 'module' => \IPS\Request::i()->pageModule, 'controller' => \IPS\Request::i()->pageController, 'area' => \IPS\Request::i()->pageArea, 'widgets' => json_encode( $blocks ) ), TRUE );
|
||||
\IPS\Widget::deleteCaches( $block['key'], ( isset( $block['app'] ) ) ? $block['app'] : NULL, ( isset( $block['plugin'] ) ) ? $block['plugin'] : NULL );
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
\IPS\Output::i()->output = $widget->configuration()->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'widgets', 'core' ) ), 'formTemplate' ), $widget );
|
||||
|
||||
Reference in new issue
Block a user