Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 18 Jul 2013 */ namespace IPS\core\modules\front\system; /* To prevent PHP errors (extending class does not exist) revealing path */ use DateInterval; use IPS\Content\Controller; use IPS\core\DataLayer; use IPS\core\Warnings\Reason; use IPS\core\Warnings\Warning; use IPS\DateTime; use IPS\Db; use IPS\Helpers\Table\Content; use IPS\Http\Url; use IPS\Member; use IPS\Output; use IPS\Platform\Bridge; use IPS\Request; use IPS\Session; use IPS\Settings; use IPS\Theme; use OutOfRangeException; use UnderflowException; use function count; use function defined; if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' ); exit; } /** * Member Warnings */ class warnings extends Controller { /** * [Content\Controller] Class */ protected static string $contentModel = 'IPS\core\Warnings\Warning'; /** * Execute * * @return void */ public function execute() : void { parent::execute(); if ( !Settings::i()->warn_on ) { Output::i()->error( 'warning_system_disabled', '2C184/7', 403, '' ); } } /** * View List * * @return mixed */ protected function manage() : mixed { /* Load the member */ $member = Member::load( Request::i()->id ); if ( !$member->member_id ) { Output::i()->error( 'node_error', '2C135/A', 403, '' ); } /* Check permission */ if ( !( Settings::i()->warn_on AND ( Member::loggedIn()->modPermission('mod_see_warn') or ( Settings::i()->warn_show_own and Member::loggedIn()->member_id == $member->member_id ) ) ) ) { Output::i()->error( 'no_module_permission', '2C135/9', 403, '' ); } $table = new Content( 'IPS\core\Warnings\Warning', Url::internal( "app=core&module=system&controller=warnings&id={$member->member_id}", 'front', 'warn_list', $member->members_seo_name ), array( array( 'wl_member=?', $member->member_id ) ) ); $table->rowsTemplate = array( Theme::i()->getTemplate( 'system', 'core', 'front' ), 'warningRow' ); Output::i()->title = Member::loggedIn()->language()->addToStack('members_warnings', FALSE, array( 'sprintf' => array( $member->name ) ) ); Output::i()->breadcrumb[] = array( $member->url(), $member->name ); if( !Request::i()->isAjax() ) { Output::i()->output = Theme::i()->getTemplate( 'tables', 'core' )->container( (string) $table ); } else { Output::i()->output = (string) $table; } return null; } /** * View Warning * * @return void */ protected function view() : void { /* Load the member */ $member = Member::load( Request::i()->id ); if ( !$member->member_id ) { Output::i()->error( 'node_error', '2C135/4', 403, '' ); } /* Load it */ try { $warning = Warning::loadAndCheckPerms( Request::i()->w ); } catch ( OutOfRangeException $e ) { Output::i()->error( 'node_error', '2C184/3', 404, '' ); return; } /* If the member viewing this is the member who was warned, log a data layer event */ if ( Member::loggedIn()->member_id === $warning->member and DataLayer::enabled( "analytics_full" ) ) { DataLayer::i()->addEvent( 'warning_viewed', $warning->getDataLayerProperties() ); } /* Show it */ Output::i()->title = Member::loggedIn()->language()->addToStack( 'view_warning_details' ); Output::i()->breadcrumb[] = array( $member->url(), $member->name ); Output::i()->breadcrumb[] = array( Url::internal( "app=core&module=system&controller=warnings&id={$member->member_id}", NULL, 'warn_list', $member->members_seo_name ), Member::loggedIn()->language()->addToStack('members_warnings', FALSE, array( 'sprintf' => array( $member->name ) ) ) ); Output::i()->breadcrumb[] = array( NULL, Member::loggedIn()->language()->addToStack( 'view_warning_details' ) ); Output::i()->output = Theme::i()->getTemplate('modcp')->warnHovercard( $warning ); } /** * Warn * * @return void */ protected function warn() : void { /* Load the member */ $member = Member::load( Request::i()->id ); if ( !$member->member_id ) { Output::i()->error( 'node_error', '2C135/2', 403, '' ); } /* Permission Check */ if ( !Member::loggedIn()->canWarn( $member ) ) { Output::i()->error( 'no_module_permission', '2C184/6', 403, '' ); } /* Build the form */ $form = Warning::create(); $form->class = 'ipsForm--vertical ipsForm--warn'; $form->attributes = array( 'data-controller' => 'core.front.modcp.warnForm', 'data-member' => $member->member_id ); $form->hiddenValues['ref'] = Request::i()->ref; $form->hiddenValues['member'] = $member->member_id; /* Display */ Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'front_modcp.js', 'core' ) ); $actions = Db::i()->select( '*', 'core_members_warn_actions', NULL, 'wa_points ASC' ); if ( count( $actions ) ) { $min = NULL; foreach ( $actions as $a ) { if ( ( $a['wa_points'] - $member->warn_level ) > 1 ) { $min = $a['wa_points'] - $member->warn_level; } break; } $form->addSidebar( Theme::i()->getTemplate( 'modcp' )->warnActions( $actions, $member, $min ) ); } Output::i()->title = Member::loggedIn()->language()->addToStack('warn_member', FALSE, array( 'sprintf' => array( $member->name ) ) ); Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ); } /** * Acknowledge Warning * * @return void */ protected function acknowledge() : void { Session::i()->csrfCheck(); /* Load the member */ $member = Member::load( Request::i()->id ); if ( !$member->member_id ) { Output::i()->error( 'node_error', '2C184/4', 403, '' ); } /* Load it */ try { $warning = Warning::loadAndCheckPerms( Request::i()->w ); if ( $warning->member !== $member->member_id ) { throw new OutOfRangeException; } } catch ( OutOfRangeException $e ) { Output::i()->error( 'node_error', '2C184/5', 404, '' ); } /* Acknowledge it */ $alreadyAcknowledged = $warning->acknowledged; $warning->acknowledged = TRUE; $warning->save(); $member->members_bitoptions['unacknowledged_warnings'] = (bool) Db::i()->select( 'COUNT(*)', 'core_members_warn_logs', array( "wl_member=? AND wl_acknowledged=0", $member->member_id ), NULL, NULL, NULL, NULL, Db::SELECT_FROM_WRITE_SERVER )->first(); $member->save(); /* Data Layer */ if ( !$alreadyAcknowledged and DataLayer::enabled( "analytics_full" ) ) { DataLayer::i()->addEvent( 'warning_acknowledged', $warning->getDataLayerProperties() ); } /* Redirect */ if ( $redirectTo = Request::i()->referrer() ) { Output::i()->redirect( $redirectTo ); } else { Output::i()->redirect( $warning->url() ); } } /** * Revoke Warning * * @return void */ protected function delete() : void { $class = static::$contentModel; try { /* @var Warning $class */ $item = $class::loadAndCheckPerms( Request::i()->w ); $member = Member::load( $item->member ); if ( $item->canDelete() ) { if ( isset( Request::i()->undo ) ) { Session::i()->csrfCheck(); if ( Request::i()->undo ) { $item->undo(); } $item->delete(); Output::i()->redirect( $member->url(), 'warn_revoked' ); } else { Output::i()->output = Theme::i()->getTemplate('modcp')->warningRevoke( $item ); } } else { Output::i()->error( 'generic_error', '2C184/1', 403, '' ); } } catch( OutOfRangeException $e ) { Output::i()->error( 'node_error', '2C184/2', 404, '' ); } } /** * Add Warning Form - AJAX response to reason select * * @return void */ protected function reasonAjax() : void { /* Check permission */ if ( ! ( Settings::i()->warn_on AND Member::loggedIn()->modPermission('mod_see_warn') ) ) { Output::i()->error( 'no_module_permission', '2C135/9', 403, '' ); } $remove = array( 'date' => NULL, 'time' => NULL, 'unlimited' => TRUE, ); if ( Request::i()->id == 'other' ) { Output::i()->json( array( 'points' => 0, 'points_override' => TRUE, 'remove' => $remove, 'remove_override' => TRUE, 'notes' => NULL, 'cheev_point_reduction' => 0, 'cheev_override' => TRUE ) ); } try { $reason = Reason::load( Request::i()->id ); /* Add in the remove properties */ if ( $reason->remove AND $reason->remove != -1 ) { $date = DateTime::create(); if ( $reason->remove_unit == 'h' ) { $date->add( new DateInterval( "PT{$reason->remove}H" ) ); } else { $date->add( new DateInterval( "P{$reason->remove}D" ) ); } $remove = array( 'date' => $date->format( 'Y-m-d' ), 'time' => $date->format( 'H:i' ), 'unlimited' => FALSE ); } Output::i()->json( array( 'points' => $reason->points, 'points_override' => $reason->points_override, 'remove' => $remove, 'remove_override' => $reason->remove_override, 'notes' => $reason->notes, 'cheev_point_reduction' => $reason->cheev_point_reduction, 'cheev_override' => $reason->cheev_override ) ); } catch ( OutOfRangeException $e ) { Output::i()->json( array( 'points' => 0, 'points_override' => FALSE, 'remove' => $remove, 'remove_override' => FALSE, 'notes' => NULL, 'cheev_point_reduction' => 0, 'cheev_override' => FALSE ) ); } } /** * Add Warning Form - AJAX response to points change * * @return void */ protected function actionAjax() : void { $actions = array( 'mq' => array( 'date' => NULL, 'time' => NULL, 'unlimited' => FALSE, ), 'rpa' => array( 'date' => NULL, 'time' => NULL, 'unlimited' => FALSE, ), 'suspend' => array( 'date' => NULL, 'time' => NULL, 'unlimited' => FALSE, ), ); $member = Member::load( Request::i()->member ); /* Check permission */ if ( !( Settings::i()->warn_on AND ( Member::loggedIn()->modPermission('mod_see_warn') or ( Settings::i()->warn_show_own and Member::loggedIn()->member_id == $member->member_id ) ) ) ) { Output::i()->error( 'no_module_permission', '2C135/9', 403, '' ); } try { $action = Db::i()->select( '*', 'core_members_warn_actions', array( 'wa_points<=?', ( $member->warn_level + (int) Request::i()->points ) ), 'wa_points DESC', 1 )->first(); foreach ( array( 'mq', 'rpa', 'suspend' ) as $k ) { if ( $action[ 'wa_' . $k ] == -1 ) { $actions[ $k ]['unlimited'] = TRUE; } elseif ( $action[ 'wa_' . $k ] ) { $date = DateTime::ts( time() )->add( new DateInterval( $action[ 'wa_' . $k . '_unit' ] == 'h' ? "PT{$action[ 'wa_' . $k ]}H" : "P{$action[ 'wa_' . $k ]}D" ) ); $actions[ $k ]['date'] = $date->format( 'Y-m-d' ); $actions[ $k ]['time'] = $date->format( 'H:i' ); } } } catch ( UnderflowException $e ) { } Output::i()->json( array( 'actions' => $actions, 'override' => isset( $action ) ? $action['wa_override'] : Member::loggedIn()->modPermission('warning_custom_noaction') ) ); } }