Version 5.0.0 beta 4

This commit is contained in:
Neo committed 2025-12-19 16:57:00 -08:00
1 parent e86153356a
commit 2f24f9de48
276 files changed
+8614 -6044

No files matched your search

@@ -12,19 +12,26 @@ namespace IPS\core\extensions\core\ModCp;
/* To prevent PHP errors (extending class does not exist) revealing path */
use ErrorException;
use IPS\Api\Exception;
use IPS\Application;
use IPS\Content\Controller;
use IPS\core\DeletionLog;
use IPS\core\Reports\Comment;
use IPS\core\Reports\Report;
use IPS\core\Reports\Types;
use IPS\DateTime;
use IPS\Db;
use IPS\Helpers\Form;
use IPS\Helpers\Form\Select;
use IPS\Helpers\Form\YesNo;
use IPS\Helpers\Table\Content;
use IPS\Http\Url;
use IPS\Member;
use IPS\Output;
use IPS\Request;
use IPS\Session;
use IPS\Settings;
use IPS\Theme;
use OutOfRangeException;
use UnderflowException;
@@ -150,6 +157,7 @@ class Reports extends Controller
$table->filters['filter_report_status_2'] = [ 'status=2' ];
$table->filters['filter_report_status_3'] = [ 'status=3' ];
$table->filters['filter_report_status_4'] = [ 'status=4' ];
$table->title = Member::loggedIn()->language()->addToStack( 'report_center_header' );
if ( Request::i()->isAjax() and isset( Request::i()->overview ) )
@@ -206,24 +214,12 @@ class Reports extends Controller
}
/* Setting status? */
if( isset( Request::i()->setStatus ) and in_array( Request::i()->setStatus, range( 1, 3 ) ) )
if( isset( Request::i()->setStatus ) and in_array( Request::i()->setStatus, range( 1, 4 ) ) )
{
Session::i()->csrfCheck();
$report->changeStatus( (int) Request::i()->setStatus );
$report->status = (int) Request::i()->setStatus;
$report->save();
/* Post a comment on the report */
$content = Member::loggedIn()->language()->addToStack( 'update_report_status_content', FALSE, array( 'sprintf' => array( Member::loggedIn()->language()->addToStack( 'report_status_' . $report->status ) ) ) );
Member::loggedIn()->language()->parseOutputForDisplay( $content );
$comment = Comment::create( $report, $content, true, null, null, Member::loggedIn(), new DateTime );
$comment->save();
/* And add to the moderator log */
Session::i()->modLog( 'modlog__action_update_report_status', array( $report->url()->__toString() => FALSE ) );
Output::i()->redirect( $report->url() );
\IPS\Output::i()->redirect( $report->url()->setQueryString( 'changed', '1' ) );
}
/* Deleting? */
@@ -341,6 +337,12 @@ class Reports extends Controller
}
else
{
if ( isset( Request::i()->changed ) )
{
/* Show a flash message */
Output::i()->inlineMessage = Member::loggedIn()->language()->addToStack( 'report_status_changed');
}
$sprintf = $item ? htmlspecialchars( $item->mapped('title'), ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) : Member::loggedIn()->language()->addToStack('content_deleted');
Output::i()->title = Member::loggedIn()->language()->addToStack( 'modcp_reports_view', FALSE, array( 'sprintf' => array( $sprintf ) ) );
Output::i()->breadcrumb[] = array( Url::internal( 'app=core&module=modcp&controller=modcp&tab=reports', 'front', 'modcp_reports' ), Member::loggedIn()->language()->addToStack( 'modcp_reports' ) );
@@ -348,11 +350,138 @@ class Reports extends Controller
Output::i()->output = Theme::i()->getTemplate( 'modcp' )->report( $report, $comment, $item, $ref, $prevReport, $prevItem, $nextReport, $nextItem, $delLog );
}
}
/**
* Show the report center modal
*
* @return void
*/
public function reportCenterConfirmModal(): void
{
$id = intval( Request::i()->id );
try
{
$report = Report::load( $id );
}
catch( \OutOfRangeException $e )
{
Output::i()->error( 'node_error', '2S319/1', 404 );
}
$form = new Form( 'form', 'modal_author_notification_form_submit' );
$form->class .= 'ipsForm_vertical';
$form->addButton( 'cancel', 'link', $report->url() );
/* Get the optional notifications */
$notifications = [ 0 => 'modal_author_notification_none' ];
foreach( Report::getAuthorNotifications() as $notification )
{
$notifications[ $notification['id'] ] = $notification['title'];
}
$form->add( new Select( 'modal_author_notification', null, null, [ 'options' => $notifications ] ) );
/* Fix the language string */
Member::loggedIn()->language()->words['modal_author_notification'] = Member::loggedIn()->language()->addToStack('modal_author__notification', null, [ 'sprintf' => [ $report->author()->name ] ] );
if ( $values = $form->values() )
{
Session::i()->csrfCheck();
$report->changeStatus( (int) Request::i()->status, $values['modal_author_notification'] );
Output::i()->redirect( $report->url()->setQueryString( 'changed', '1' ) );
}
Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->genericBlock( (string) $form, null, 'ipsPadding' ) );
}
/**
* Change Report Reason (report_type)
*
* @return void
* @throws ErrorException
* @throws Exception
*/
public function changeType(): void
{
/* Load the report and the main object */
try
{
$report = Db::i()->select( '*', 'core_rc_reports', [ 'id=?', Request::i()->id ] )->first();
$item = Report::loadAndCheckPerms( $report['rid'] );
}
catch ( \Exception $e )
{
Output::i()->error( 'node_error', '2C139/6', 404, '' );
}
/* Build form */
$form = new Form;
$options = array( Report::TYPE_MESSAGE => Member::loggedIn()->language()->addToStack('report_message_comment') );
foreach( Types::roots() as $type )
{
$options[ $type->id ] = $type->_title;
}
if ( count( $options ) > 1 )
{
$form->add( new Select( 'report_type', $report['report_type'], null, [ 'options' => $options ] ) );
$form->add( new YesNo( 'report_type_change_log', true, null ) );
}
$form->class .= 'ipsForm_vertical';
/* Handle submissions */
if ( $values = $form->values() )
{
/* Update the new reason */
Db::i()->update( 'core_rc_reports', array( 'report_type' => $values['report_type'] ), [ 'id=?', $report['id'] ] );
if ( ! empty( $values['report_type_change_log'] ) )
{
$old = Member::loggedIn()->language()->get('none');
$new = Member::loggedIn()->language()->get('none');
if ( $values['report_type'] )
{
$new = Types::load( $values['report_type'] )->_title;
}
if ( $report['report_type'] )
{
try
{
$old = Types::load( $report['report_type'] )->_title;
}
catch ( \OutOfRangeException $e )
{
Output::i()->error( 'node_error', '2C139/7', 403, '' );
}
}
if ( $report['report_type'] != $values['report_type'] )
{
$url = $item->url()->setQueryString( 'tab', 'reports' )->setFragment( 'report' . $report['id'] );
$content = Member::loggedIn()->language()->addToStack('report_type_changed', FALSE, array( 'sprintf' => array( $new, $old, $url, $report['id'] ) ) );
Member::loggedIn()->language()->parseOutputForDisplay( $content );
$content = str_replace( rtrim( Settings::i()->base_url, '/' ), '<___base_url___>', $content );
$comment = Comment::create( $item, $content, TRUE, NULL, NULL, Member::loggedIn(), new DateTime );
$comment->save();
}
}
Output::i()->redirect( $item->url() );
}
/* Display form */
Output::i()->output = $form->customTemplate( array( Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
/**
* Redirect to the original content for a report
*
* @return void
* @return void
* @throws Exception
*/
public function find() : void
{
@@ -362,7 +491,7 @@ class Reports extends Controller
}
catch ( OutOfRangeException $e )
{
Output::i()->error( 'node_error', '2C139/4', 404, '' );
Output::i()->error( 'node_error', '2C139/2', 404, '' );
}
$reportClass = $report->class;
@@ -401,8 +530,7 @@ class Reports extends Controller
{
$url = $url->setPage( 'page', $page );
}
Output::i()->redirect( $url->setFragment( 'comment-' . $comment->$commentIdColumn ) );
}
}
@@ -17,6 +17,7 @@ use IPS\Content;
use IPS\Content\Comment;
use IPS\Content\Item;
use IPS\core\Reports\Report;
use IPS\core\Reports\Types;
use IPS\core\Warnings\Warning;
use IPS\DateTime;
use IPS\Db;
@@ -137,7 +138,21 @@ class Moderation extends NotificationsAbstract
'disabled' => array(),
);
}
/* Do we have any report types, and can we report things? ? */
if ( Db::i()->select( 'COUNT(*)', 'core_automatic_moderation_types' )->first() and ( ! $member or $member->group['g_can_report'] ) )
{
$return['reports'] = [
'type' => 'standard',
'notificationTypes' => ['report_outcome'],
'title' => 'notifications__core_Moderation_reports',
'showTitle' => true,
'description' => 'notifications__core_Moderation_reports_desc',
'default' => ['email'],
'disabled' => [ 'push', 'inline' ],
];
}
return $return;
}
@@ -200,7 +215,53 @@ class Moderation extends NotificationsAbstract
return $return;
}
/**
* Parse notification: Report outcomes
*
* @param \IPS\Notification\Inline $notification The notification
* @param bool $htmlEscape TRUE to escape HTML in title
* @return array
* @code
return array(
'title' => "Mark has replied to A Topic", // The notification title
'url' => \IPS\Http\Url::internal( ... ), // The URL the notification should link to
'content' => "Lorem ipsum dolar sit", // [Optional] Any appropriate content. Do not format this like an email where the text
// explains what the notification is about - just include any appropriate content.
// For example, if the notification is about a post, set this as the body of the post.
'author' => \IPS\Member::load( 1 ), // [Optional] The user whose photo should be displayed for this notification
);
* @endcode
*/
public function parse_report_outcome( $notification, $htmlEscape=TRUE )
{
if ( ! $notification->item_sub or ! count( $notification->extra ) )
{
throw new \OutOfRangeException;
}
$reported = $notification->item_sub;
$item = ( $reported instanceof Item ) ? $reported : $reported->item();
try
{
$reportType = Types::load( $notification->extra['reportType'] );
$class = $item->class;
$url = $class::load( $item->content_id )->url();
}
catch( \UnderflowException )
{
throw new \OutOfRangeException;
}
return array(
'title' => Member::loggedIn()->language()->addToStack( 'notification__report_outcome', FALSE, array(
( $htmlEscape ? 'sprintf' : 'htmlsprintf' ) => array( $item->mapped('title'), $reportType->_title, Member::loggedIn()->language()->addToStack( 'report_status_' . $item->status ) ) )
),
'url' => $url,
'author' => Member::loggedIn(),
);
}
/**
* Parse notification: unapproved_content_bulk
*
@@ -58,6 +58,12 @@ class ConvertOpenTags extends QueueAbstract
$tags = array_slice( $data['tags'], $offset, REBUILD_SLOW );
foreach( $tags as $text )
{
/* Fail-safe */
if( empty( $text ) )
{
continue;
}
try
{
$tag = Tag::load( $text, 'tag_text' );
@@ -57,6 +57,11 @@ class UpdateTaggedItems extends QueueAbstract
*/
public function run( array &$data, int $offset ): int
{
if( empty( $data['tag'] ) )
{
throw new QueueOutOfRangeException;
}
$rows = iterator_to_array(
Db::i()->select( '*', 'core_tags', [ 'tag_text=?', $data['tag'] ], 'tag_added', [ $offset, REBUILD_SLOW ] )
);