jenkins-bot has submitted this change and it was merged.

Change subject: [SCHEMA CHANGE] Refactor of moderation logging.
......................................................................


[SCHEMA CHANGE] Refactor of moderation logging.

* Store moderation reason in object.
* Use a LifecycleHandler to do logging rather than doing it directly.
* Includes permalink handling for the logging class. Unfortunately not 
backwards compatible.

Bug: 57055
Bug: 57056
Change-Id: Idd5a6570268e480c9cbe2c9620dfbb587db71ee4
---
M Flow.php
M Hooks.php
M Resources.php
M container.php
A db_patches/patch-moderation_reason.sql
M flow.sql
M includes/Block/Topic.php
M includes/Data/RevisionStorage.php
M includes/Log/Formatter.php
A includes/Log/PostModerationLogger.php
M includes/Model/AbstractRevision.php
M modules/moderation/moderation.js
12 files changed, 132 insertions(+), 17 deletions(-)

Approvals:
  Matthias Mullie: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Flow.php b/Flow.php
index 60c2431..ffd16e8 100755
--- a/Flow.php
+++ b/Flow.php
@@ -122,6 +122,7 @@
 $wgAutoloadClasses['Flow\RecentChanges\Formatter'] = $dir . 
'includes/RecentChanges/Formatter.php';
 $wgAutoloadClasses['Flow\Log\Logger'] = $dir . 'includes/Log/Logger.php';
 $wgAutoloadClasses['Flow\Log\Formatter'] = $dir . 'includes/Log/Formatter.php';
+$wgAutoloadClasses['Flow\Log\PostModerationLogger'] = $dir . 
'includes/Log/PostModerationLogger.php';
 
 // database interaction for singular models
 $wgAutoloadClasses['Flow\Data\RevisionStorage'] = $dir . 
'includes/Data/RevisionStorage.php';
diff --git a/Hooks.php b/Hooks.php
index 8c8599e..b481802 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -27,6 +27,7 @@
                $baseSQLFile = "$dir/flow.sql";
                $updater->addExtensionTable( 'flow_revision', $baseSQLFile );
                $updater->addExtensionField( 'flow_revision', 
'rev_last_edit_id', "$dir/db_patches/patch-revision_last_editor.sql" );
+               $updater->addExtensionField( 'flow_revision', 'rev_mod_reason', 
"$dir/db_patches/patch-moderation_reason.sql" );
                if ( $updater->getDB()->getType() === 'sqlite' ) {
                        $updater->modifyExtensionField( 
'flow_summary_revision', 'summary_workflow_id', 
"$dir/db_patches/patch-summary2header.sqlite.sql" );
                        $updater->modifyExtensionField( 'flow_revision', 
'rev_comment', "$dir/db_patches/patch-rev_change_type.sqlite.sql" );
diff --git a/Resources.php b/Resources.php
index d05785d..51ef8a4 100644
--- a/Resources.php
+++ b/Resources.php
@@ -129,6 +129,7 @@
                        'ext.flow.base',
                        'jquery.ui.dialog',
                        'jquery.spinner',
+                       'jquery.byteLimit',
                ),
        ),
        'ext.flow.editor' => $flowResourceTemplate + array(
diff --git a/container.php b/container.php
index c7372b1..0a590f1 100644
--- a/container.php
+++ b/container.php
@@ -287,6 +287,7 @@
        );
 
        $handlers = array(
+               new Flow\Log\PostModerationLogger( $c['storage'], 
$c['repository.tree'], $c['logger'] ),
                new Flow\Data\PostRevisionRecentChanges( $c['storage'], 
$c['repository.tree'], $wgContLang ),
                $c['storage.board_history.index'],
        );
diff --git a/db_patches/patch-moderation_reason.sql 
b/db_patches/patch-moderation_reason.sql
new file mode 100644
index 0000000..8bf2a24
--- /dev/null
+++ b/db_patches/patch-moderation_reason.sql
@@ -0,0 +1,3 @@
+-- Patch to add the "moderated reason" field to revision table
+
+ALTER TABLE /*_*/flow_revision ADD COLUMN rev_mod_reason varchar(255) binary;
\ No newline at end of file
diff --git a/flow.sql b/flow.sql
index b0c7ac7..e54f618 100644
--- a/flow.sql
+++ b/flow.sql
@@ -122,6 +122,8 @@
        rev_mod_user_id bigint unsigned,
        rev_mod_user_text varchar(255) binary,
        rev_mod_timestamp varchar(14) binary,
+       -- moderated why? (coming soon: how?, where? and what?)
+       rev_mod_reason varchar(255) binary,
 
        -- track who made the most recent content edit
        rev_last_edit_id binary(16) null,
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index ae15731..0905ad3 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -228,27 +228,16 @@
                        $this->errors['moderate'] = wfMessage( 
'flow-error-invalid-moderation-reason' );
                        return;
                }
+
+               $reason = $this->submitted['reason'];
+
                if ( $post->needsModerateHistorical( $newState ) ) {
                        $this->relatedRevisions = $this->loadHistorical( $post 
);
                }
 
-               $this->newRevision = $post->moderate( $this->user, $newState, 
$action, $this->relatedRevisions );
+               $this->newRevision = $post->moderate( $this->user, $newState, 
$action, $reason, $this->relatedRevisions );
                if ( !$this->newRevision ) {
                        $this->errors['moderate'] = wfMessage( 
'flow-error-not-allowed' );
-               } else {
-                       // @todo: would be nice to get this logging into a 
LifecycleHandler
-                       $logger = Container::get( 'logger' );
-                       if ( $logger->canLog( $post, $action ) ) {
-                               $logger->log(
-                                       $post,
-                                       $action,
-                                       $this->submitted['reason'],
-                                       $this->getWorkflow(),
-                                       array(
-                                               $this->getName() . '[postId]' 
=> $post->getPostId()->getHex(),
-                                       )
-                               );
-                       }
                }
        }
 
diff --git a/includes/Data/RevisionStorage.php 
b/includes/Data/RevisionStorage.php
index b8b0547..5d6c202 100644
--- a/includes/Data/RevisionStorage.php
+++ b/includes/Data/RevisionStorage.php
@@ -11,7 +11,11 @@
 
 abstract class RevisionStorage implements WritableObjectStorage {
        static protected $allowedUpdateColumns = array(
-               'rev_mod_state', 'rev_mod_user_id', 'rev_mod_user_text', 
'rev_mod_timestamp',
+               'rev_mod_state',
+               'rev_mod_user_id',
+               'rev_mod_user_text',
+               'rev_mod_timestamp',
+               'rev_mod_reason',
        );
        protected $dbFactory;
        protected $externalStores;
diff --git a/includes/Log/Formatter.php b/includes/Log/Formatter.php
index 659cf28..88dfd8d 100644
--- a/includes/Log/Formatter.php
+++ b/includes/Log/Formatter.php
@@ -2,6 +2,7 @@
 
 namespace Flow\Log;
 
+use Flow\Model\UUID;
 use Message;
 
 class Formatter extends \LogFormatter {
@@ -19,6 +20,29 @@
                $skin = $this->plaintext ? null : $this->context->getSkin();
                $params = $this->entry->getParameters();
 
+               // FIXME this is ugly. Why were we treating log parameters as
+               // URL GET parameters in the first place?
+               if ( isset( $params['postId'] ) ) {
+                       $title = clone $title;
+                       $postId = $params['postId'];
+                       if ( $postId instanceof UUID ) {
+                               $postId = $postId->getHex();
+                       }
+                       $title->setFragment( '#flow-post-' . $postId );
+                       unset( $params['postId'] );
+               }
+
+               if ( isset( $params['topicId'] ) ) {
+                       $title = clone $title;
+                       $topicId = $params['topicId'];
+                       if ( $topicId instanceof UUID ) {
+                               $topicId = $topicId->getHex();
+                       }
+
+                       $title->setFragment( '#flow-topic-' . $topicId );
+                       unset( $params['topicId'] );
+               }
+
                // Give grep a chance to find the usages:
                // logentry-delete-flow-delete-post, 
logentry-delete-flow-restore-post,
                // logentry-suppress-flow-restore-post, 
logentry-suppress-flow-censor-post,
diff --git a/includes/Log/PostModerationLogger.php 
b/includes/Log/PostModerationLogger.php
new file mode 100644
index 0000000..29ffc89
--- /dev/null
+++ b/includes/Log/PostModerationLogger.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Flow\Log;
+
+use Flow\Data\LifecycleHandler;
+use Flow\Data\ManagerGroup;
+use Flow\Log\Logger;
+use Flow\Model\AbstractRevision;
+use Flow\Repository\TreeRepository;
+
+class PostModerationLogger implements LifecycleHandler {
+       function __construct( ManagerGroup $storage, TreeRepository $treeRepo, 
Logger $logger ) {
+               $this->storage = $storage;
+               $this->treeRepo = $treeRepo;
+               $this->logger = $logger;
+       }
+
+       function onAfterInsert( $object, array $row ) {
+               $moderationChangeTypes = self::getModerationChangeTypes();
+               if ( ! in_array( $object->getChangeType(), 
$moderationChangeTypes ) ) {
+                       // Do nothing for non-moderation actions
+                       return;
+               }
+
+               if ( $this->logger->canLog( $object, $object->getChangeType() ) 
) {
+                       // This is awful but it's all I can think of
+                       $rootPost = $this->treeRepo->findRoot( 
$object->getPostId() );
+                       $workflow = $this->storage->get( 'Workflow', $rootPost 
);
+                       $logParams = array();
+
+                       if ( $object->isTopicTitle() ) {
+                               $logParams['topicId'] = $workflow->getId();
+                       } else {
+                               $logParams['postId'] = $object->getRevisionId();
+                       }
+
+                       $this->logger->log(
+                               $object,
+                               $object->getChangeType(),
+                               $object->getModeratedReason(),
+                               $workflow,
+                               $logParams
+                       );
+               }
+       }
+
+       function onAfterLoad( $object, array $old ) {
+                // You don't need to see my identification
+       }
+
+       function onAfterUpdate( $object, array $old, array $new ) {
+               // These aren't the droids you're looking for
+       }
+
+       function onAfterRemove( $object, array $old ) {
+               // Move along
+       }
+
+       protected static function getModerationChangeTypes() {
+               static $changeTypes = false;
+
+               if ( ! $changeTypes ) {
+                       $changeTypes = array();
+                       foreach( AbstractRevision::$perms as $perm => $info ) {
+                               if ( $perm != '' ) {
+                                       $changeTypes[] = "{$perm}-topic";
+                                       $changeTypes[] = "{$perm}-post";
+                               }
+                       }
+
+                       $changeTypes[] = 'restore-topic';
+                       $changeTypes[] = 'restore-post';
+               }
+
+               return $changeTypes;
+       }
+}
\ No newline at end of file
diff --git a/includes/Model/AbstractRevision.php 
b/includes/Model/AbstractRevision.php
index c8f4268..475a432 100644
--- a/includes/Model/AbstractRevision.php
+++ b/includes/Model/AbstractRevision.php
@@ -77,6 +77,7 @@
        protected $moderationTimestamp;
        protected $moderatedByUserId;
        protected $moderatedByUserText;
+       protected $moderatedReason;
 
        protected $lastEditId;
        protected $lastEditUserId;
@@ -103,6 +104,7 @@
                $obj->moderatedByUserId = $row['rev_mod_user_id'];
                $obj->moderatedByUserText = $row['rev_mod_user_text'];
                $obj->moderationTimestamp = $row['rev_mod_timestamp'];
+               $obj->moderatedReason = isset( $row['rev_mod_reason'] ) ? 
$row['rev_mod_reason'] : null;
 
                // isset required because there is a possible db migration, 
cached data will not have it
                $obj->lastEditId = isset( $row['rev_last_edit_id'] ) ? 
UUID::create( $row['rev_last_edit_id'] ) : null;
@@ -129,6 +131,7 @@
                        'rev_mod_user_id' => $obj->moderatedByUserId,
                        'rev_mod_user_text' => $obj->moderatedByUserText,
                        'rev_mod_timestamp' => $obj->moderationTimestamp,
+                       'rev_mod_reason' => $obj->moderatedReason,
 
                        'rev_last_edit_id' => $obj->lastEditId ? 
$obj->lastEditId->getBinary() : null,
                        'rev_edit_user_id' => $obj->lastEditUserId,
@@ -180,7 +183,7 @@
         * $historical revisions must be provided when 
self::needsModerateHistorical
         * returns true.
         */
-       public function moderate( User $user, $state, $changeType, array 
$historical = array() ) {
+       public function moderate( User $user, $state, $changeType, $reason, 
array $historical = array() ) {
                if ( ! $this->isValidModerationState( $state ) ) {
                        wfWarn( __METHOD__ . ': Provided moderation state does 
not exist : ' . $state );
                        return null;
@@ -209,10 +212,14 @@
                                $rev->moderatedByUserId = null;
                                $rev->moderatedByUserText = null;
                                $rev->moderationTimestamp = null;
+                               // This is a bit hacky, but we store the 
restore reason
+                               // in the "moderated reason" field. Hmmph.
+                               $rev->moderatedReason = $reason;
                        } else {
                                $rev->moderatedByUserId = $user->getId();
                                $rev->moderatedByUserText = $user->getName();
                                $rev->moderationTimestamp = $timestamp;
+                               $rev->moderatedReason = $reason;
                        }
                }
 
@@ -396,6 +403,10 @@
                return $this->moderationState;
        }
 
+       public function getModeratedReason() {
+               return $this->moderatedReason;
+       }
+
        public function isModerated() {
                return $this->moderationState !== self::MODERATED_NONE;
        }
diff --git a/modules/moderation/moderation.js b/modules/moderation/moderation.js
index 77d52c2..9968aff 100644
--- a/modules/moderation/moderation.js
+++ b/modules/moderation/moderation.js
@@ -88,6 +88,7 @@
                                .append(
                                        $( '<textarea/>' )
                                                .attr( 'id', 
'flow-moderation-reason' )
+                                               .byteLimit( 255 )
                                                .attr( 'placeholder', mw.msg( 
'flow-moderation-reason-placeholder' ) )
                                )
                                .appendTo( $dialog );

-- 
To view, visit https://gerrit.wikimedia.org/r/95985
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Idd5a6570268e480c9cbe2c9620dfbb587db71ee4
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Werdna <[email protected]>
Gerrit-Reviewer: EBernhardson <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Werdna <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to