Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 14 Feb 2017 */ namespace IPS\core\modules\front\clubs; /* 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; } /** * Clubs View */ class _view extends \IPS\Helpers\CoverPhoto\Controller { /** * @brief The club being viewed */ protected $club; /** * @brief The logged in user's status */ protected $memberStatus; /** * Execute * * @return void */ public function execute() { if ( \IPS\Request::i()->do != 'embed' ) { /* Permission check */ if ( !\IPS\Settings::i()->clubs ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/P', 403, '' ); } /* Load the club */ try { $this->club = \IPS\Member\Club::load( \IPS\Request::i()->id ); } catch ( \OutOfRangeException $e ) { \IPS\Output::i()->error( 'node_error', '2C350/1', 404, '' ); } $this->memberStatus = $this->club->memberStatus( \IPS\Member::loggedIn() ); /* If we can't even know it exists, show an error */ if ( !$this->club->canView() ) { \IPS\Output::i()->error( \IPS\Member::loggedIn()->member_id ? 'no_module_permission' : 'no_module_permission_guest', '2C350/2', 403, '' ); } /* Sort out the breadcrumb */ \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( $this->club->url(), $this->club->name ) ); /* Add a "Search in this club" contextual search option */ \IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_club' ) ] = array( 'type' => '', 'club' => "c{$this->club->id}" ); /* CSS */ \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'] ) { \IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/clubs_responsive.css', 'core', 'front' ) ); } /* JS */ \IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_clubs.js', 'core', 'front' ) ); /* Location for online list */ if ( $this->club->type !== \IPS\Member\Club::TYPE_PRIVATE ) { \IPS\Session::i()->setLocation( $this->club->url(), array(), 'loc_clubs_club', array( $this->club->name => FALSE ) ); } else { \IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ), array(), 'loc_clubs_directory' ); } } /* Pass upwards */ parent::execute(); } /** * View * * @return void */ protected function manage() { /* 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() ) { $this->members(); return; } /* Get the activity stream */ $activity = \IPS\Content\Search\Query::init()->filterByClub( $this->club )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->search(); /* Get who joined the club in between those results */ if ( $this->club->type != \IPS\Member\Club::TYPE_PUBLIC ) { $lastTime = NULL; foreach ( $activity as $key => $result ) { $lastTime = $result->createdDate->getTimestamp(); } $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 ) ) ) ); if ( $lastTime ) { $joinWhere[] = array( 'core_clubs_memberships.joined>?', $lastTime ); } $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 ) { $joins[] = new \IPS\Content\Search\Result\Custom( \IPS\DateTime::ts( $join['core_clubs_memberships']['joined'] ), \IPS\Member::loggedIn()->language()->addToStack( 'clubs_activity_joined', FALSE, array( 'htmlsprintf' => \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userLinkFromData( $join['core_members']['member_id'], $join['core_members']['name'], $join['core_members']['members_seo_name'] ) ) ), \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->userPhotoFromData( $join['core_members']['member_id'], $join['core_members']['name'], $join['core_members']['members_seo_name'], \IPS\Member::photoUrl( $join['core_members'] ), 'tiny' ) ); } /* Merge them in */ if ( !empty( $joins ) ) { $activity = array_merge( iterator_to_array( $activity ), $joins ); uasort( $activity, function( $a, $b ) { if ( $a->createdDate->getTimestamp() == $b->createdDate->getTimestamp() ) { return 0; } elseif( $a->createdDate->getTimestamp() < $b->createdDate->getTimestamp() ) { return 1; } else { return -1; } } ); } } /* Display */ \IPS\Output::i()->title = $this->club->name; \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->view( $this->club, $activity, $this->club->fieldValues() ); } /** * Map Callback * * @return void */ protected function mapPopup() { \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->mapPopup( $this->club ); } /** * Edit * * @return void */ protected function edit() { if ( !( $this->club->owner and $this->club->owner == \IPS\Member::loggedIn() ) and !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/A', 403, '' ); } if ( $form = $this->club->form() ) { \IPS\Output::i()->title = $this->club->name; if( \IPS\Request::i()->isAjax() ) { \IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ); } else { \IPS\Output::i()->output = $form; } } else { \IPS\Output::i()->redirect( $this->club->url() ); } } /** * Edit Photo * * @return void */ protected function editPhoto() { if ( !( $this->club->owner and $this->club->owner == \IPS\Member::loggedIn() ) and !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/R', 403, '' ); } \IPS\Output::i()->title = $this->club->name; $form = new \IPS\Helpers\Form( 'club_profile_photo', 'continue' ); $form->ajaxOutput = TRUE; $form->add( new \IPS\Helpers\Form\Upload( 'club_profile_photo', $this->club->profile_photo_uncropped ? \IPS\File::get( 'core_Clubs', $this->club->profile_photo_uncropped ) : NULL, FALSE, array( 'storageExtension' => 'core_Clubs', 'image' => array( 'maxWidth' => 200, 'maxHeight' => 200 ) ) ) ); if ( $values = $form->values() ) { if ( !$values['club_profile_photo'] or $this->club->profile_photo_uncropped != (string) $values['club_profile_photo'] ) { foreach ( array( 'profile_photo', 'profile_photo_uncropped' ) as $k ) { try { \IPS\File::get( 'core_Clubs', $this->club->$k )->delete(); } catch ( \Exception $e ) { } $this->club->$k = NULL; } } if ( $values['club_profile_photo'] ) { $this->club->profile_photo_uncropped = (string) $values['club_profile_photo']; $this->club->save(); if ( \IPS\Request::i()->isAjax() ) { $this->cropPhoto(); return; } else { \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'cropPhoto' ) ); } } else { $this->club->save(); \IPS\Output::i()->redirect( $this->club->url() ); } } \IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ); } /** * Crop Photo * * @return void */ protected function cropPhoto() { if ( !( $this->club->owner and $this->club->owner == \IPS\Member::loggedIn() ) and !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/V', 403, '' ); } \IPS\Output::i()->title = $this->club->name; /* Get the photo */ if ( !$this->club->profile_photo_uncropped ) { \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'editPhoto' ) ); } $original = \IPS\File::get( 'core_Clubs', $this->club->profile_photo_uncropped ); $image = \IPS\Image::create( $original->contents() ); /* Work out which dimensions to suggest */ if ( $image->width < $image->height ) { $suggestedWidth = $suggestedHeight = $image->width; } else { $suggestedWidth = $suggestedHeight = $image->height; } /* Build form */ $form = new \IPS\Helpers\Form( 'photo_crop', 'save', $this->club->url()->setQueryString( 'do', 'cropPhoto' ) ); $form->class = 'ipsForm_noLabels'; $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() ); } ) ) ); /* Handle submissions */ if ( $values = $form->values() ) { /* Crop it */ $image->cropToPoints( $values['photo_crop'][0], $values['photo_crop'][1], $values['photo_crop'][2], $values['photo_crop'][3] ); /* Delete the existing */ if ( $this->club->profile_photo ) { try { \IPS\File::get( 'core_Clubs', $this->club->profile_photo )->delete(); } catch ( \Exception $e ) { } } /* 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 ); $this->club->profile_photo = (string) $cropped; $this->club->save(); /* Edited member, so clear widget caches (stats, widgets that contain photos, names and so on) */ \IPS\Widget::deleteCaches(); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url() ); } /* Display */ \IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ); } /** * Get photo for cropping * If the photo is on a different domain to the JS that handles cropping, * it will be blocked because of CORS. See notes in Cropper documentation. * * @return void */ protected function cropPhotoGetPhoto() { \IPS\Session::i()->csrfCheck(); $original = \IPS\File::get( 'core_Clubs', $this->club->profile_photo_uncropped ); $headers = array( "Content-Disposition" => \IPS\Output::getContentDisposition( 'inline', $original->filename ) ); \IPS\Output::i()->sendOutput( $original->contents(), 200, \IPS\File::getMimeType( $original->filename ), $headers ); } /** * See Members * * @return void */ protected function members() { /* Public groups have no member list */ if ( $this->club->type === \IPS\Member\Club::TYPE_PUBLIC ) { \IPS\Output::i()->error( 'node_error', '2C350/H', 404, '' ); } /* What members are we getting? */ $filter = NULL; $statuses = array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ); $baseUrl = $this->club->url()->setQueryString( 'do', 'members' ); if ( isset( \IPS\Request::i()->filter ) ) { switch ( \IPS\Request::i()->filter ) { case \IPS\Member\Club::STATUS_LEADER: $filter = \IPS\Member\Club::STATUS_LEADER; $statuses = array( \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ); $baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_LEADER ); break; case \IPS\Member\Club::STATUS_REQUESTED: if ( $this->club->isLeader() ) { $filter = \IPS\Member\Club::STATUS_REQUESTED; $statuses = array( \IPS\Member\Club::STATUS_REQUESTED ); $baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_REQUESTED ); } 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 ); } break; case \IPS\Member\Club::STATUS_INVITED: if ( $this->club->isLeader() ) { $filter = \IPS\Member\Club::STATUS_INVITED; $statuses = array( \IPS\Member\Club::STATUS_INVITED ); $baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_INVITED ); } break; } } /* What are we sorting by? */ $orderByClause = 'core_clubs_memberships.joined DESC'; $sortBy = 'joined'; if ( isset( \IPS\Request::i()->sortby ) and \IPS\Request::i()->sortby === 'name' ) { $orderByClause = 'core_members.name ASC'; $sortBy = 'name'; } /* Sort out the offset */ $perPage = 28; $activePage = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1; $offset = ( $activePage - 1 ) * $perPage; /* Fetch them */ $members = $this->club->members( $statuses, array( $offset, $perPage ), $orderByClause, $this->club->isLeader() ? 3 : 1 ); $pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $members->count(TRUE) / $perPage ), $activePage, $perPage ); /* Display */ if ( \IPS\Request::i()->isAjax() ) { \IPS\Output::i()->json( array( 'rows' => \IPS\Theme::i()->getTemplate( 'clubs' )->membersRows( $this->club, $members ), 'pagination' => $pagination, 'extraHtml' => '' ) ); } else { \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 ); } } /** * Accept a join request * * @return void */ protected function acceptRequest() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/3', 403, '' ); } /* Check the member's request is pending */ $member = \IPS\Member::load( \IPS\Request::i()->member ); if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_REQUESTED ) { \IPS\Output::i()->error( 'node_error', '2C350/4', 403, '' ); } /* Add them */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE, \IPS\Member::loggedIn(), NULL, TRUE ); $this->club->recountMembers(); /* Notify the member */ $notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_response', $this->club, array( $this->club, TRUE ) ); $notification->recipients->attach( $member ); $notification->send(); /* Send a notification to any leaders besides ourselves */ $notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_join', $this->club, array( $this->club, $member ), array( 'response' => TRUE ) ); foreach ( $this->club->members( array( \IPS\Member\Club::STATUS_LEADER ), NULL, NULL, 2 ) as $leader ) { $leader = \IPS\Member::constructFromData( $leader ); if ( $leader->member_id != \IPS\Member::loggedIn()->member_id ) { $notification->recipients->attach( $leader ); } } if ( count( $notification->recipients ) ) { $notification->send(); } if ( \IPS\Request::i()->isAjax() ) { \IPS\Output::i()->json( array( 'status' => 'approved' ) ); } else { /* If other requests are pending, send us back, otherwise take us to the main member list */ $url = $this->club->url()->setQueryString( 'do', 'members' ); if ( count( $this->club->members( array( \IPS\Member\Club::STATUS_REQUESTED ) ) ) ) { \IPS\Output::i()->redirect( $url->setQueryString( 'filter', \IPS\Member\Club::STATUS_REQUESTED ) ); } else { \IPS\Output::i()->redirect( $url ); } } } /** * Decline a join request * * @return void */ protected function declineRequest() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/F', 403, '' ); } /* Check the member's request is pending */ $member = \IPS\Member::load( \IPS\Request::i()->member ); if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_REQUESTED ) { \IPS\Output::i()->error( 'node_error', '2C350/G', 403, '' ); } /* 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(); if ( \IPS\Request::i()->isAjax() ) { \IPS\Output::i()->json( array( 'status' => 'declined' ) ); } else { /* If other requests are pending, send us back, otherwise take us to the main member list */ $url = $this->club->url()->setQueryString( 'do', 'members' ); if ( count( $this->club->members( array( \IPS\Member\Club::STATUS_REQUESTED ) ) ) ) { \IPS\Output::i()->redirect( $url->SetQueryString( 'filter', \IPS\Member\Club::STATUS_REQUESTED ) ); } else { \IPS\Output::i()->redirect( $url ); } } } /** * Make a member a leader * * @return void */ protected function makeLeader() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/6', 403, '' ); } /* 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 ) ) ) { \IPS\Output::i()->error( 'node_error', '2C350/7', 403, '' ); } /* Promote */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_LEADER, TRUE ); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) ); } /** * Demote a member from being a leader * * @return void */ protected function demoteLeader() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/8', 403, '' ); } /* Get member */ $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, '' ); } /* Promote */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE ); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) ); } /** * Make a member a moderator * * @return void */ protected function makeModerator() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/K', 403, '' ); } /* 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 ) ) ) { \IPS\Output::i()->error( 'node_error', '2C350/L', 403, '' ); } /* Promote */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_MODERATOR, TRUE ); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) ); } /** * Demote a member from being a moderator * * @return void */ protected function demoteModerator() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/M', 403, '' ); } /* Get member */ $member = \IPS\Member::load( \IPS\Request::i()->member ); if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_MODERATOR ) { \IPS\Output::i()->error( 'node_error', '2C350/N', 403, '' ); } /* Promote */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE ); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) ); } /** * Remove a member * * @return void */ protected function removeMember() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/C', 403, '' ); } /* 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 ) ) ) { \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, '' ); } /* Remove */ $this->club->addMember( $member, \IPS\Member\Club::STATUS_BANNED, TRUE, \IPS\Member::loggedIn() ); $this->club->recountMembers(); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) ); } /** * Join * * @return void */ protected function join() { /* Can we join? */ if ( !$this->club->canJoin() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/I', 403, '' ); } /* CSRF Check */ \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') ) { $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 { $this->club->addMember( \IPS\Member::loggedIn(), \IPS\Member\Club::STATUS_REQUESTED ); $notificationKey = 'club_request'; } /* Send a notification to any leaders */ $notification = new \IPS\Notification( \IPS\Application::load('core'), $notificationKey, $this->club, array( $this->club, \IPS\Member::loggedIn() ) ); foreach ( $this->club->members( array( \IPS\Member\Club::STATUS_LEADER ), NULL, NULL, 2 ) as $member ) { $notification->recipients->attach( \IPS\Member::constructFromData( $member ) ); } $notification->send(); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url() ); } /** * Leave * * @return void */ 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 ) ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/S', 403, '' ); } /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Leave */ $this->club->removeMember( \IPS\Member::loggedIn() ); $this->club->recountMembers(); $this->club->save(); /* Redirect */ \IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ) ); } /** * Invite Members * * @return void */ protected function invite() { if ( !$this->club->canInvite() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/5', 403, '' ); } $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 ( $values = $form->values() ) { $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 ) { if ( $member instanceof \IPS\Member ) { $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 ); $notification->recipients->attach( $member ); } } } $notification->send(); \IPS\Output::i()->redirect( $this->club->url(), 'club_notifications_sent' ); } \IPS\Output::i()->title = $this->club->name; \IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ); } /** * Re-invite a banned memer * * @return void */ protected function reInvite() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !$this->club->isLeader() ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/J', 403, '' ); } /* Check the member needs to be reinvited */ $member = \IPS\Member::load( \IPS\Request::i()->member ); if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED ) ) ) { \IPS\Output::i()->error( 'node_error', '2C350/K', 403, '' ); } /* Add them */ $this->club->removeMember( $member ); $this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, FALSE, NULL, \IPS\Member::loggedIn() ); $this->club->recountMembers(); /* Notify the member */ $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(); /* If other requests are banned, send us back, otherwise take us to the main member list */ $url = $this->club->url()->setQueryString( 'do', 'members' ); if ( count( $this->club->members( array( \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED ) ) ) ) { \IPS\Output::i()->redirect( $url->SetQueryString( 'filter', \IPS\Member\Club::STATUS_BANNED ) ); } else { \IPS\Output::i()->redirect( $url ); } } /** * Feature * * @return void */ protected function feature() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !\IPS\Member::loggedIn()->modPermission('can_manage_featured_clubs') ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/Q', 403, '' ); } /* Feature */ $this->club->featured = TRUE; $this->club->save(); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url() ); } /** * Unfeature * * @return void */ protected function unfeature() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !\IPS\Member::loggedIn()->modPermission('can_manage_featured_clubs') ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/Q', 403, '' ); } /* Unfeature */ $this->club->featured = FALSE; $this->club->save(); /* Redirect */ \IPS\Output::i()->redirect( $this->club->url() ); } /** * Approve/Deny * * @return void */ protected function approve() { /* CSRF Check */ \IPS\Session::i()->csrfCheck(); /* Permission check */ if ( !\IPS\Member::loggedIn()->modPermission('can_manage_featured_clubs') or $this->club->approved or !\IPS\Settings::i()->clubs_require_approval ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/U', 403, '' ); } /* Approve... */ if ( \IPS\Request::i()->approved ) { $this->club->approved = TRUE; $this->club->save(); \IPS\Output::i()->redirect( $this->club->url() ); } /* ... or delete */ else { $this->club->delete(); \IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ) ); } } /** * Create a node * * @return void */ protected function nodeForm() { /* Permission check */ $class = \IPS\Request::i()->type; if ( !$this->club->isLeader() or !in_array( $class, \IPS\Member\Club::availableNodeTypes( \IPS\Member::loggedIn() ) ) or ( \IPS\Settings::i()->clubs_require_approval and !$this->club->approved ) ) { \IPS\Output::i()->error( 'no_module_permission', '2C350/T', 403, '' ); } /* Load if editing */ if ( isset( \IPS\Request::i()->node ) ) { 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/O', 404, '' ); } } else { $node = new $class; } /* Build Form */ $form = new \IPS\Helpers\Form; $form->class = 'ipsForm_vertical'; $node->clubForm( $form ); /* Handle submissions */ if ( $values = $form->values() ) { $node->saveClubForm( $this->club, $values ); \IPS\Output::i()->redirect( $this->club->url() ); } /* Display */ \IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('club_create_node'); \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; } /* !Cover Photo */ /** * Get Cover Photo Storage Extension * * @return string */ protected function _coverPhotoStorageExtension() { return 'core_Clubs'; } /** * Set Cover Photo * * @param \IPS\Helpers\CoverPhoto $photo New Photo * @return void */ protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo ) { $this->club->cover_photo = (string) $photo->file; $this->club->cover_offset = (int) $photo->offset; $this->club->save(); } /** * Get Cover Photo * * @return \IPS\Helpers\CoverPhoto */ protected function _coverPhotoGet() { return $this->club->coverPhoto(); } /** * Embed * * @return void */ protected function embed() { $title = \IPS\Member::loggedIn()->language()->addToStack( 'error_title' ); try { $club = \IPS\Member\Club::load( \IPS\Request::i()->id ); if ( !$club->canView() ) { $output = \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->embedNoPermission(); } else { $output = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->embedClub( $club ); } } catch( \Exception $e ) { $output = \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->embedUnavailable(); } /* Make sure our iframe contents get the necessary elements and JS */ $js = array( \IPS\Output::i()->js( 'js/commonEmbedHandler.js', 'core', 'interface' ), \IPS\Output::i()->js( 'js/internalEmbedHandler.js', 'core', 'interface' ) ); \IPS\Output::i()->base = '_parent'; /* We need to keep any embed.css files that have been specified so that we can re-add them after we re-fetch the css framework */ $embedCss = array(); foreach( \IPS\Output::i()->cssFiles as $cssFile ) { if( \mb_stristr( $cssFile, 'embed.css' ) ) { $embedCss[] = $cssFile; } } /* We need to reset the included CSS files because by this point the responsive files are already in the output CSS array */ \IPS\Output::i()->cssFiles = array(); \IPS\Theme::i()->settings = array_merge( \IPS\Theme::i()->settings, array( 'responsive' => FALSE ) ); \IPS\Dispatcher\Front::baseCss(); \IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, $embedCss ); \IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/embeds.css', 'core', 'front' ) ); \IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->embedInternal( $output, $js ), 200, 'text/html', \IPS\Output::i()->httpHeaders ); } }