Version 4.7.23
This commit is contained in:
1 parent
7124a02564
commit
25ddeb65d6
1791 files changed
+76990
-44452
No files matched your search
@@ -26,7 +26,14 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
* @brief Const No type selected
|
||||
*/
|
||||
const TYPE_MESSAGE = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Const Reported content statuses
|
||||
*/
|
||||
const STATUS_NEW = 1;
|
||||
const STATUS_OPEN = 2;
|
||||
const STATUS_CLOSED = 3;
|
||||
const STATUS_REJECTED = 4;
|
||||
|
||||
/* !\IPS\Patterns\ActiveRecord */
|
||||
|
||||
@@ -141,7 +148,208 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
throw new \OutofRangeException;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the report types for this report index
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReportedTypes(): array
|
||||
{
|
||||
$reportedTypes = [];
|
||||
$reportTypes = [];
|
||||
foreach ( \IPS\core\Reports\Types::roots() as $type )
|
||||
{
|
||||
$reportTypes[ $type->id ] = $type->_title;
|
||||
}
|
||||
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_rc_reports', ['rid=? and report_type > 0', $this->id] ) as $report )
|
||||
{
|
||||
if ( isset( $reportTypes[ $report['report_type'] ] ) )
|
||||
{
|
||||
$reportedTypes[ $report['report_type'] ] = $reportTypes[ $report['report_type'] ];
|
||||
}
|
||||
}
|
||||
|
||||
return $reportedTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the status of the report
|
||||
*
|
||||
* @param int $status
|
||||
* @param $member
|
||||
* @return void
|
||||
*/
|
||||
public function changeStatus( int $status, int $authorNotification=0, $member=null )
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
$this->status = $status;
|
||||
$this->save();
|
||||
|
||||
/* We only need to notify if there is an outcome */
|
||||
if ( $status == static::STATUS_CLOSED or static::STATUS_REJECTED )
|
||||
{
|
||||
$forNotifications = [];
|
||||
$forEmails = [];
|
||||
|
||||
/* Now go through all the individual reports and see if we need to notify anyone */
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_rc_reports', ['rid=?', $this->id] ) as $report )
|
||||
{
|
||||
if ( !$report['report_type'] )
|
||||
{
|
||||
/* We have not selected a reason, no nothing to worry about */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the report type object */
|
||||
try
|
||||
{
|
||||
$reportType = \IPS\core\Reports\Types::load( $report['report_type'] );
|
||||
$reportMember = \IPS\Member::load( $report['report_by'] );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $report['report_by'] )
|
||||
{
|
||||
/* We have a member */
|
||||
$forNotifications[$report['report_type']][] = [$reportMember, $reportType, $report];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $report['guest_email'] )
|
||||
{
|
||||
/* We have an email */
|
||||
$forEmails[$report['report_type']][] = [$reportType, $report];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Members */
|
||||
foreach ( $forNotifications as $typeId => $data )
|
||||
{
|
||||
foreach ( $data as $reportData )
|
||||
{
|
||||
$reportMember = $reportData[0];
|
||||
$reportType = $reportData[1];
|
||||
$userReport = $reportData[2];
|
||||
|
||||
if ( $this->getReportOutcomeBlurb( $userReport['id'] ) )
|
||||
{
|
||||
$notification = new \IPS\Notification( \IPS\Application::load( 'core' ), 'report_outcome', $this, [$this, $reportType, $userReport], ['reportType' => $reportType->id, 'userReport' => $userReport] );
|
||||
$notification->recipients->attach( $reportMember );
|
||||
$notification->send();
|
||||
\IPS\Log::debug( "Sent notification to {$reportMember->name}", 'reports_notification' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Guests */
|
||||
foreach ( $forEmails as $typeId => $data )
|
||||
{
|
||||
foreach ( $data as $reportData )
|
||||
{
|
||||
$reportType = $reportData[0];
|
||||
$guestEmail = $reportData[1]['guest_email'];
|
||||
$userReport = $reportData[1];
|
||||
|
||||
if ( $guestEmail and $this->getReportOutcomeBlurb( $userReport['id'] ) )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'notification_report_outcome', [$this, $reportType, $userReport], \IPS\Email::TYPE_LIST )->send( $guestEmail );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Content author? */
|
||||
if ( $authorNotification )
|
||||
{
|
||||
try
|
||||
{
|
||||
$class = $this->_data['class'];
|
||||
$thing = $class::load( $this->_data['content_id'] );
|
||||
$content = ( $thing instanceof \IPS\Content\Comment ) ? $thing->truncated() : $thing->mapped( 'title' );
|
||||
|
||||
if ( $thing->author() and $thing->author()->email )
|
||||
{
|
||||
$authorContent = static::getAuthorNotifications();
|
||||
|
||||
if ( isset( $authorContent[ $authorNotification ] ) )
|
||||
{
|
||||
$notificationContent = $authorContent[$authorNotification]['text'];
|
||||
|
||||
/* Substitutions */
|
||||
$subs = [
|
||||
'name' => $thing->author()->name,
|
||||
'content' => trim( $content ),
|
||||
'link' => (string) $thing->url(),
|
||||
'reason' => implode( ', ', $this->getReportedTypes() )
|
||||
];
|
||||
|
||||
foreach( $subs as $key => $value )
|
||||
{
|
||||
$notificationContent = str_replace( '{' . $key . '}', $value, $notificationContent );
|
||||
}
|
||||
|
||||
\IPS\Email::buildFromTemplate( 'core', 'notification_report_content_author', [$this, $thing, $notificationContent], \IPS\Email::TYPE_LIST )->send( $thing->author()->email );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Post a comment on the report */
|
||||
$content = $member->language()->addToStack( 'update_report_status_content', FALSE, array( 'sprintf' => array( $member->language()->addToStack( 'report_status_' . $this->status ) ) ) );
|
||||
$member->language()->parseOutputForDisplay( $content );
|
||||
|
||||
$comment = \IPS\core\Reports\Comment::create( $this, $content, TRUE, NULL, NULL, $member, new \IPS\DateTime );
|
||||
$comment->save();
|
||||
|
||||
/* And add to the moderator log */
|
||||
\IPS\Session::i()->modLog( 'modlog__action_update_report_status', array( $this->url()->__toString() => FALSE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the author notifications
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAuthorNotifications(): array
|
||||
{
|
||||
$return = [];
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_rc_author_notification_text', [], 'title ASC' ) as $row )
|
||||
{
|
||||
$return[ $row['id'] ] = $row;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the report outcome blurb
|
||||
*
|
||||
* @param int $userReportId
|
||||
* @return string
|
||||
*/
|
||||
public function getReportOutcomeBlurb( int $userReportId ): string
|
||||
{
|
||||
try
|
||||
{
|
||||
$userReport = \IPS\Db::i()->select( '*', 'core_rc_reports', array( 'id=?', $userReportId ) )->first();
|
||||
$reportType = \IPS\core\Reports\Types::load( $userReport['report_type'] );
|
||||
return $this->status === static::STATUS_REJECTED ? $reportType->getRejectedNotificationText( \IPS\Member::load( $userReport['report_by'] ) ) : $reportType->getCompletedNotificationText( \IPS\Member::load( $userReport['report_by'] ) );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapped value
|
||||
*
|
||||
@@ -359,18 +567,7 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
{
|
||||
if ( mb_substr( $action, 0, -1 ) === 'report_status_' )
|
||||
{
|
||||
$this->status = mb_substr( $action, -1 );
|
||||
$this->save();
|
||||
|
||||
/* Post a comment on the report */
|
||||
$content = \IPS\Member::loggedIn()->language()->addToStack( 'update_report_status_content', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'report_status_' . $this->status ) ) ) );
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $content );
|
||||
|
||||
$comment = \IPS\core\Reports\Comment::create( $this, $content, TRUE, NULL, NULL, \IPS\Member::loggedIn(), new \IPS\DateTime );
|
||||
$comment->save();
|
||||
|
||||
/* And add to the moderator log */
|
||||
\IPS\Session::i()->modLog( 'modlog__action_update_report_status', array( $this->url()->__toString() => FALSE ) );
|
||||
$this->changeStatus( (int) mb_substr( $action, -1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -385,7 +582,7 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
*/
|
||||
public function customMultimodActions()
|
||||
{
|
||||
return array_diff( array( 'report_status_1', 'report_status_2', 'report_status_3', ), array( 'report_status_' . $this->status ) );
|
||||
return array_diff( array( 'report_status_1', 'report_status_2', 'report_status_3', 'report_status_4'), array( 'report_status_' . $this->status ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,6 +613,11 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
'action' => 'report_status_3',
|
||||
'icon' => 'check-circle',
|
||||
'label' => 'report_status_3'
|
||||
),
|
||||
array(
|
||||
'action' => 'report_status_4',
|
||||
'icon' => 'archive',
|
||||
'label' => 'report_status_4'
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -574,6 +776,7 @@ class _Report extends \IPS\Content\Item implements \IPS\Content\ReadMarkers
|
||||
$typeCounts = array();
|
||||
$total = 0;
|
||||
$seen = array();
|
||||
/* @note SELECT_FROM_WRITE_SERVER added in 7fd46ad949b0a9b03a5c67c70afee26184c2930c pull #316 (The problem was, that the R/W separation.The new report was added and in the same step we fetched(counted) the existing reports, where the recent one wasn't taken into account.) */
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_rc_reports', array( 'rid=? and report_type > 0', $this->id ), NULL, NULL, NULL, NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER ) as $row )
|
||||
{
|
||||
if ( isset( $seen[ $row['report_by'] ] ) )
|
||||
|
||||
@@ -86,12 +86,14 @@ class _Rules extends \IPS\Node\Model
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'automaticmoderation_points', $this->id ? $this->points_needed : 10, TRUE, array( 'min' => 1, 'max' => 9999 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('automaticmoderation_points_suffix') ) );
|
||||
|
||||
$options = array();
|
||||
foreach( \IPS\core\Reports\Types::roots() as $type )
|
||||
if( count( \IPS\core\Reports\Types::roots() ) > 0 )
|
||||
{
|
||||
$options[ $type->id ] = $type->_title;
|
||||
foreach( \IPS\core\Reports\Types::roots() as $type )
|
||||
{
|
||||
$options[ $type->id ] = $type->_title;
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'automaticmoderation_type', $this->types ? explode( ',', $this->types ) : array(), TRUE, array( 'options' => $options ) ) );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'automaticmoderation_type', $this->types ? explode( ',', $this->types ) : array(), TRUE, array( 'options' => $options ) ) );
|
||||
|
||||
/* Loop over our member filters */
|
||||
$form->addHeader( 'automaticmoderation_generic_filters' );
|
||||
@@ -183,7 +185,11 @@ class _Rules extends \IPS\Node\Model
|
||||
$values['rule_filters'] = json_encode( $_options );
|
||||
$values['rule_points_needed'] = $values['automaticmoderation_points'];
|
||||
$values['rule_enabled'] = $values['automaticmoderation_enabled'];
|
||||
$values['rule_types'] = $values['automaticmoderation_type'];
|
||||
if( isset( $values['automaticmoderation_type'] ) )
|
||||
{
|
||||
$values['rule_types'] = $values['automaticmoderation_type'];
|
||||
}
|
||||
|
||||
|
||||
/* Now we have to remove any fields that aren't valid... */
|
||||
foreach( $values as $k => $v )
|
||||
@@ -360,17 +366,21 @@ class _Rules extends \IPS\Node\Model
|
||||
|
||||
/* Loop over the filters */
|
||||
$descriptions = array();
|
||||
foreach( $this->_filters as $key => $filter )
|
||||
if( $this->_filters )
|
||||
{
|
||||
if( isset( static::$extensions[ $key ] ) )
|
||||
foreach( $this->_filters as $key => $filter )
|
||||
{
|
||||
/* Ask the extension if this member matches the defined rule...if not, just return FALSE now */
|
||||
if( method_exists( static::$extensions[ $key ], 'getDescription' ) and $description = static::$extensions[ $key ]->getDescription( $filter ) )
|
||||
if( isset( static::$extensions[ $key ] ) )
|
||||
{
|
||||
$descriptions[] = $description; /* Is this descriptive enough? */
|
||||
/* Ask the extension if this member matches the defined rule...if not, just return FALSE now */
|
||||
if( method_exists( static::$extensions[ $key ], 'getDescription' ) and $description = static::$extensions[ $key ]->getDescription( $filter ) )
|
||||
{
|
||||
$descriptions[] = $description; /* Is this descriptive enough? */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'automaticmoderation_row_desc', TRUE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->formatList( $descriptions ) ) ) );
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
namespace IPS\core\Reports;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
|
||||
use IPS\Member;
|
||||
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
@@ -66,7 +69,29 @@ class _Types extends \IPS\Node\Model
|
||||
* @brief [Node] Title prefix. If specified, will look for a language key with "{$key}_title" as the key
|
||||
*/
|
||||
public static $titleLangPrefix = 'automaticmod_types_';
|
||||
|
||||
|
||||
/**
|
||||
* Get the completed notification text (hits the DB to get the real value, not the hash key)
|
||||
* @param Member|null $member
|
||||
* @return string
|
||||
*/
|
||||
public function getCompletedNotificationText( \IPS\Member|null $member=null ): string
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
return $member->language()->get( 'automaticmod_types_notify_complete_' . $this->id, 'core' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rejected notification text (hits the DB to get the real value, not the hash key)
|
||||
* @param Member|null $member
|
||||
* @return string
|
||||
*/
|
||||
public function getRejectedNotificationText( \IPS\Member|null $member=null ): string
|
||||
{
|
||||
$member = $member ?: \IPS\Member::loggedIn();
|
||||
return $member->language()->get( 'automaticmod_types_notify_reject_' . $this->id, 'core' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Form
|
||||
*
|
||||
@@ -76,6 +101,8 @@ class _Types extends \IPS\Node\Model
|
||||
public function form( &$form )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'automaticmod_types_title', NULL, TRUE, array( 'app' => 'core', 'key' => ( $this->id ? 'automaticmod_types_' . $this->id : NULL ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'automaticmod_types_notify_complete', NULL, FALSE, array( 'textArea' => true, 'app' => 'core', 'key' => ( $this->id ? 'automaticmod_types_notify_complete_' . $this->id : NULL ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'automaticmod_types_notify_reject', NULL, FALSE, array( 'textArea' => true, 'app' => 'core', 'key' => ( $this->id ? 'automaticmod_types_notify_reject_' . $this->id : NULL ) ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,8 +120,12 @@ class _Types extends \IPS\Node\Model
|
||||
|
||||
/* Save the title */
|
||||
\IPS\Lang::saveCustom( 'core', 'automaticmod_types_' . $this->id, $values['automaticmod_types_title'] );
|
||||
|
||||
/* Save the notification text */
|
||||
\IPS\Lang::saveCustom( 'core', 'automaticmod_types_notify_complete_' . $this->id, $values['automaticmod_types_notify_complete'] );
|
||||
\IPS\Lang::saveCustom( 'core', 'automaticmod_types_notify_reject_' . $this->id, $values['automaticmod_types_notify_reject'] );
|
||||
|
||||
unset( $values['automaticmod_types_title'] );
|
||||
unset( $values['automaticmod_types_title'], $values['automaticmod_types_notify_complete'], $values['automaticmod_types_notify_reject'] );
|
||||
|
||||
return parent::formatFormValues( $values );
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user