jenkins-bot has submitted this change and it was merged.
Change subject: Add topic participants' info, amount of comment
......................................................................
Add topic participants' info, amount of comment
* Added "Anonymous" as reserved username
* getCreatorName() now returns false (instead of message) if username is not
available
* Display "Anonymous" as username instead of IPs
* Added post method and registerParticipants()
* Added post method and registerDescendantCount()
* Added message to display topic participants' info
* Added message to display amount of topic comments
* Added registerDescendant()
* Removed findDescendant(); use getRecursiveResult() after registerDescendant()
* Added registerRecursive(), getRecursiveResult() & descendRecursive()
These latter functions will make sure that descendant trees are not iterated
over too much. Multiple callbacks can be registered to descend the tree
recursively. Once the result for either of these is requests, all of them will
be executed in one go.
Change-Id: I3d1aedeebd595d24abbdb362e103860821d37a6f
---
M Flow.i18n.php
M Flow.php
M Hooks.php
M includes/Block/Topic.php
M includes/Model/PostRevision.php
M includes/Notifications/Controller.php
M includes/Templating.php
M modules/discussion/styles/topic.less
M modules/discussion/ui.js
M templates/post.html.php
M templates/topic.html.php
11 files changed, 429 insertions(+), 59 deletions(-)
Approvals:
EBernhardson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/Flow.i18n.php b/Flow.i18n.php
index d51cc43..29e71dd 100644
--- a/Flow.i18n.php
+++ b/Flow.i18n.php
@@ -11,6 +11,9 @@
'flow-desc' => 'Workflow management system',
'flow-specialpage' => '$1 – Flow',
+ 'flow-user-anonymous' => 'Anonymous',
+ 'flow-user-moderated' => 'Moderated user',
+
'flow-edit-header-link' => 'Edit header',
'flow-header-empty' => 'This talk page currently has no header.',
@@ -91,6 +94,8 @@
'flow-rev-message-censored-post' => 'Censored post',
'flow-topic-history' => 'Topic history',
+ 'flow-topic-participants' => '{{PLURAL:$1|0=No participation yet|$3
started this topic|{{GENDER:$3|$3}} and {{GENDER:$4|$4}}|{{GENDER:$3|$3}},
{{GENDER:$4|$4}} and $2 others}}',
+ 'flow-topic-comments' => '{{PLURAL:$1|0=Be the first to
comment!|Comment ($1)}}',
'flow-comment-restored' => 'Restored comment',
'flow-comment-deleted' => 'Deleted comment',
@@ -146,6 +151,8 @@
*/
$messages['qqq'] = array(
'flow-desc' =>
'{{desc|name=Flow|url=http://www.mediawiki.org/wiki/Extension:Flow}}',
+ 'flow-user-anonymous' => 'Name to display for anonymous users',
+ 'flow-user-moderated' => 'Name to display instead of a moderated user
name',
'flow-specialpage' => 'Used as page title in [[Special:Flow]].
Parameters:
* $1 - page title',
'flow-edit-header-link' => 'Used as text for the link which points to
the "Edit header" page.',
@@ -295,6 +302,13 @@
'flow-rev-message-censored-post' => 'Used as revision comment when a
post has been censored(oversighted)',
'flow-topic-history' => 'Used as <code><nowiki><h2></nowiki></code>
heading in the "Topic history" page.
{{Identical|Topic history}}',
+ 'flow-topic-participants' => 'Message to display the amount of
participants in this discussion (and potentially a couple of names). Parameters:
+* $1: The total amount of participants in the conversation, can be used for
PLURAL
+* $2: The total amount of participants minus 2, can be used to generate a
message like (X, Y and $2 others)
+* $3: Username of the topic starter, can be used for GENDER
+* $4: Username of a second participant (if there is a second, otherwise not
available), can be used for GENDER',
+ 'flow-topic-comments' => 'Message to display the amount of comments in
this discussion. Parameters:
+* $1: The amount of comments on this topic, can be used for PLURAL',
'flow-comment-restored' => 'Used as revision comment when the post has
been restored.
See also:
diff --git a/Flow.php b/Flow.php
index 00f5a05..3609312 100755
--- a/Flow.php
+++ b/Flow.php
@@ -148,6 +148,7 @@
$wgHooks['ApiTokensGetTokenTypes'][] = 'FlowHooks::onApiTokensGetTokenTypes';
$wgHooks['MediaWikiPerformAction'][] = 'FlowHooks::onPerformAction';
$wgHooks['OldChangesListRecentChangesLine'][] =
'FlowHooks::onOldChangesListRecentChangesLine';
+$wgHooks['UserGetReservedNames'][] = 'FlowHooks::onUserGetReservedNames';
// Extension initialization
$wgExtensionFunctions[] = 'FlowHooks::initFlowExtension';
diff --git a/Hooks.php b/Hooks.php
index affc1b6..cf78a1d 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -152,4 +152,13 @@
return true;
}
+
+ /**
+ * @param array $names
+ * @return bool
+ */
+ public static function onUserGetReservedNames( &$names ) {
+ $names[] = 'msg:flow-user-anonymous';
+ return true;
+ }
}
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index 7df215d..6cec6dc 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -289,7 +289,11 @@
$root = $this->loadRootPost();
if ( isset( $options['postId'] ) ) {
- $post = $root->findDescendant(
$options['postId'] );
+ $indexDescendant = $root->registerDescendant(
$options['postId'] );
+ $post = $root->getRecursiveResult(
$indexDescendant );
+ if ( $post === false ) {
+ throw new \MWException( 'Requested
postId is not available within post tree' );
+ }
return $templating->renderPost(
$post,
@@ -335,7 +339,12 @@
public function renderAPI( Templating $templating, array $options ) {
if ( isset( $options['postId'] ) ) {
$rootPost = $this->loadRootPost();
- $post = $rootPost->findDescendant( $options['postId'] );
+
+ $indexDescendant = $rootPost->registerDescendant(
$options['postId'] );
+ $post = $rootPost->getRecursiveResult( $indexDescendant
);
+ if ( $post === false ) {
+ throw new \MWException( 'Requested postId is
not available within post tree' );
+ }
if ( ! $post ) {
throw new MWException( "Requested post could
not be found" );
diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php
index f5fabcc..9f878c5 100644
--- a/includes/Model/PostRevision.php
+++ b/includes/Model/PostRevision.php
@@ -17,6 +17,14 @@
// Data that is loaded externally and set
protected $children;
+ /**
+ * Variables callback functions & their results will be saved to.
+ *
+ * @var array
+ */
+ protected $recursiveCallbacks = array();
+ protected $recursiveResults = array();
+
// Create a brand new root post for a brand new topic. Creating
replies to
// an existing post(incl topic root) should use self::reply.
// @param Workflow $topic
@@ -78,26 +86,65 @@
return $this->postId;
}
- public function getCreatorId() {
- return $this->origUserId;
+ /**
+ * Get the user ID of the user who created this post.
+ * Checks permissions and returns false
+ *
+ * @param $user User The user to check permissions for.
+ * @return int|bool The user ID, or false
+ */
+ public function getCreatorId( $user = null ) {
+ $creator = $this->getCreator( $user );
+
+ // Not using $creator->getId() to avoid having to fetch the id
if that
+ // User object was created via newFromName
+ return $creator === false ? false : $this->getCreatorIdRaw();
}
+ /**
+ * Get the username of the User who created this post.
+ * Checks permissions, and returns false if the current user is not
permitted
+ * to access that information
+ *
+ * @param User $user The user to check permissions for.
+ * @return string|bool The username of the User who created this post.
+ */
public function getCreatorName( $user = null ) {
- if ( $this->isAllowed( $user ) ) {
- return $this->getCreatorNameRaw();
- } else {
- $moderatedAt = new MWTimestamp(
$this->moderationTimestamp );
+ $creator = $this->getCreator( $user );
- return wfMessage(
- self::$perms[$this->moderationState]['content'],
- $this->moderatedByUserText,
- $moderatedAt->getHumanTimestamp()
- );
+ // Not using $creator->getName() to avoid having to fetch the
name if
+ // that User object was created via newFromId
+ return $creator === false ? false : $this->getCreatorNameRaw();
+ }
+
+ /**
+ * Get the User who created this post.
+ * Checks permissions, and returns false if the current user is not
permitted
+ * to access that information
+ *
+ * @param User $user The user to check permissions for.
+ * @return User|bool The username of the User who created this post.
+ */
+ public function getCreator( $user = null ) {
+ if ( $this->isAllowed( $user ) ) {
+ if ( $this->getCreatorIdRaw() !== 0 ) {
+ $user = User::newFromId(
$this->getCreatorIdRaw() );
+ } else {
+ $user = User::newFromName(
$this->getCreatorNameRaw() );
+ }
+
+ return $user;
+ } else {
+ return false;
}
}
public function getCreatorNameRaw() {
return $this->origUserText;
+ }
+
+ public function getCreatorIdRaw() {
+ return $this->origUserId;
}
public function isTopicTitle() {
@@ -114,28 +161,204 @@
public function getChildren() {
if ( $this->children === null ) {
- throw new \Exception( 'Children not loaded for post: '
. $this->postId->getHex() );
+ throw new \MWException( 'Children not loaded for post:
' . $this->postId->getHex() );
}
return $this->children;
}
- public function findDescendant( $postId ) {
- if ( ! $postId instanceof UUID ) {
+ /**
+ * Get the amount of posts in this topic.
+ *
+ * @return int
+ */
+ public function getChildCount() {
+ return count( $this->getChildren() );
+ }
+
+ /**
+ * Runs all registered callback on every descendant of this post.
+ *
+ * Used to defer going recursive more than once: if all recursive
+ * functionality is first registered, we can fetch all results in one
go.
+ *
+ * @param callable $callback The callback to call. 2 parameters:
+ * PostRevision (the post being iterated) & $result (the current result
at
+ * time of iteration). They must respond with [ $result, $continue ],
+ * where $result is the result after that post's iteration & $continue a
+ * boolean value indicating if the iteration still needs to continue
+ * @param mixed $init The initial $result value to be fed to the
callback
+ * @return int $i Identifier to pass to getRecursiveResult() to retrieve
+ * the callback's result
+ */
+ public function registerRecursive( $callback, $init ) {
+ $i = count( $this->recursiveResults );
+
+ $this->recursiveCallbacks[$i] = $callback;
+ $this->recursiveResults[$i] = $init;
+
+ return $i;
+ }
+
+ /**
+ * Returns the result of a specific callback, after having iterated over
+ * all children.
+ *
+ * @param int $registered The identifier that was returned when
registering
+ * the callback via PostRevision::registerRecursive()
+ * @return mixed
+ */
+ public function getRecursiveResult( $registered ) {
+ $this->recursiveResults = $this->descendRecursive(
+ $this->recursiveCallbacks,
+ $this->recursiveResults
+ );
+
+ // Once all callbacks have run, null the callbacks to make sure
they won't run again
+ $this->recursiveCallbacks = array_fill( 0, count(
$this->recursiveResults ), null );
+
+ return $this->recursiveResults[$registered];
+ }
+
+ /**
+ * Runs all registered callback on every descendant of this post &
recursive
+ * from there on, until $maxDepth has been reached.
+ *
+ * @param array $callbacks Array of callbacks to execute. Callbacks are
fed
+ * 2 parameters: PostRevision (the post being iterated) & $result (the
current
+ * result at time of iteration). They must respond with [ $result,
$continue ],
+ * where $result is the result after that post's iteration & $continue a
+ * boolean value indicating if the iteration still needs to continue
+ * @param array $results Array of (initial or temporary) results per
callback
+ * @param int[optional] $maxDepth The maximum depth to travel
+ * @return array $results All final results of the callbacks
+ */
+ protected function descendRecursive( array $callbacks, array $results,
$maxDepth = 10 ) {
+ if ( $maxDepth <= 0 ) {
+ return;
+ }
+
+ foreach ( $this->getChildren() as $child ) {
+ $continue = false;
+
+ foreach ( $callbacks as $i => $callback ) {
+ if ( is_callable( $callback ) ) {
+ $return = $callback( $child,
$results[$i] );
+
+ // Callbacks respond with: [ result,
continue ]
+ // Continue can be set to false if a
callback has completed
+ // what it set out to do, then we can
stop running it.
+ $results[$i] = $return[0];
+ $continue |= $return[1];
+
+ // If this specific callback has
responded it should no longer
+ // continue, get rid of it.
+ if ( $return[1] === false ) {
+ $callbacks[$i] = null;
+ }
+ }
+ }
+
+ // All of the callbacks have completed what they set
out to do = quit
+ if ( !$continue ) {
+ break;
+ }
+
+ $results = $child->descendRecursive( $callbacks,
$results, $maxDepth - 1 );
+ }
+
+ return $results;
+ }
+
+ /**
+ * Registers callback function to calculate the total number of
descendants.
+ *
+ * @return int $registered The identifier that was returned when
registering
+ * the callback via PostRevision::registerRecursive()
+ */
+ public function registerDescendantCount() {
+ /**
+ * Adds 1 to the total value per post that's iterated over.
+ *
+ * @param PostRevision $post
+ * @param int $result
+ * @return array Return array in the format of [result,
continue]
+ */
+ $callback = function( PostRevision $post, $result ) {
+ return array( $result + 1, true );
+ };
+
+ return $this->registerRecursive( $callback, 0 );
+ }
+
+ /**
+ * Registers callback function to compile a list of participants.
+ *
+ * @param string[optional] $anonymousBehaviour string Behaviour to use
for anonymous users. Options:
+ * once: Include all anonymous users as one combined user.
+ * each: Include each anonymous user separately.
+ * none: Do not include anonymous users
+ * @return int $registered The identifier that was returned when
registering
+ * the callback via PostRevision::registerRecursive()
+ */
+ public function registerParticipants( $anonymousBehaviour = 'each' ) {
+ /**
+ * Adds the user object of this post's creator.
+ *
+ * @param PostRevision $post
+ * @param int $result
+ * @return array Return array in the format of [result,
continue]
+ */
+ $callback = function( $post, $result ) use (
$anonymousBehaviour ) {
+ $creator = $post->getCreator();
+
+ if ( $creator instanceof User ) {
+ if ( $creator->isAnon() ) {
+ if ( $anonymousBehaviour === 'once' ) {
+ $result['anon'] = $creator;
+ } elseif ( $anonymousBehaviour ===
'each' ) {
+
$result[$post->getCreatorName()] = $creator;
+ } elseif ( $anonymousBehaviour ===
'none' ) {
+ // Do nothing
+ } else {
+ throw new MWException( "Unknown
anonymous behaviour $anonymousBehaviour" );
+ }
+ } else {
+ $result[$post->getCreatorId()] =
$creator;
+ }
+ }
+
+ return array( $result, true );
+ };
+
+ return $this->registerRecursive( $callback, array() );
+ }
+
+ /**
+ * Registers callback function to find a specific post within a post's
children.
+ *
+ * @param UUID $postId The id of the post to find.
+ * @return int $registered The identifier that was returned when
registering
+ * the callback via PostRevision::registerRecursive()
+ */
+ public function registerDescendant( $postId ) {
+ if ( !$postId instanceof UUID ) {
$postId = UUID::create( $postId );
}
- $stack = array( $this );
- while( $stack ) {
- $post = array_pop( $stack );
+ /**
+ * Rrturns the found post.
+ *
+ * @param PostRevision $post
+ * @param int $result
+ * @return array Return array in the format of [result,
continue]
+ */
+ $callback = function( $post, $result ) use ( &$postId ) {
if ( $post->getPostId()->equals( $postId ) ) {
- return $post;
+ return array( $post, false );
}
- foreach ( $post->getChildren() as $child ) {
- $stack[] = $child;
- }
- }
+ };
- throw new \Exception( 'Requested postId is not available within
post tree' );
+ return $this->registerRecursive( $callback, false );
}
/**
@@ -167,5 +390,3 @@
return $user->getId() == $this->getCreatorId() ||
$user->isAllowed( 'flow-edit-post' );
}
}
-
-
diff --git a/includes/Notifications/Controller.php
b/includes/Notifications/Controller.php
index 713efaf..8abc2e5 100644
--- a/includes/Notifications/Controller.php
+++ b/includes/Notifications/Controller.php
@@ -394,7 +394,7 @@
$post = reset( $post );
if ( $post ) {
- $user = User::newFromName(
$post->getCreatorName() );
+ $user = $post->getCreator();
if ( $user && !$user->isAnon() ) {
$users[$user->getId()] = $user;
diff --git a/includes/Templating.php b/includes/Templating.php
index c9d72ac..250404c 100644
--- a/includes/Templating.php
+++ b/includes/Templating.php
@@ -161,4 +161,94 @@
return Linker::userLink( $userId, $userText ) .
Linker::userToolLinks( $userId, $userText );
}
+
+ /**
+ * Returns a message that displays information on the participants of a
topic.
+ *
+ * @param PostRevision $post
+ * @param int[optional] $registered The identifier that was returned
when
+ * registering the callback via PostRevision::registerRecursive()
+ * @return string
+ */
+ public function printParticipants( PostRevision $post, $registered =
null ) {
+ $participants = $post->getRecursiveResult( $registered );
+ $participantCount = count( $participants );
+
+ $participant1 = false;
+ $participant2 = false;
+ $haveAnon = false;
+
+ while(
+ ( $participant1 === false || $participant2 === false )
&&
+ count( $participants )
+ ) {
+ $participant = array_shift( $participants );
+
+ if ( // Special conditions for anonymous users
+ $participant->isAnon() &&
+ $haveAnon && // Try not to show two anonymous
users
+ count( $participants ) // Unless we have no
other option
+ ) {
+ continue;
+ } elseif ( $participant->isAnon() ) {
+ $haveAnon = true;
+ }
+
+ $text = $this->getUserText( $participant );
+
+ if ( !$text || !$participant ) {
+ continue;
+ }
+
+ if ( $participant1 === false ) {
+ $participant1 = $text;
+ } else {
+ $participant2 = $text;
+ }
+ }
+
+ return wfMessage(
+ 'flow-topic-participants',
+ $participantCount,
+ max( 0, $participantCount - 2 ),
+ $participant1,
+ $participant2
+ )->parse();
+ }
+
+ /**
+ * Gets a Flow-formatted plaintext human-readable identifier for a user.
+ * Usually the user's name, but it can also return "an anonymous user",
+ * or information about an item's moderation state.
+ *
+ * @param User $user The User object to get a
description for.
+ * @param AbstractRevision $rev An AbstractRevision object to
retrieve moderation state from.
+ * @param bool $showIPs Whether or not to show IP
addresses for anonymous users
+ * @return String A human-readable identifier for
the given User.
+ */
+ public function getUserText( $user, $rev = null, $showIPs = false ) {
+ if ( $user === false && $rev instanceof AbstractRevision ) {
+ $state = $rev->getModerationState();
+
+ if ( $rev->getModeratedByUserId() ) {
+ $user = User::newFromId(
$rev->getModeratedByUserId() );
+ } else {
+ $user = User::newFromName(
$rev->getModeratedByUserName() );
+ }
+
+ $moderatedAt = new MWTimestamp(
$rev->getModerationTimestamp );
+
+ return wfMessage(
+
AbstractRevision::$perms[$state]['content'],
+ $this->getUserText( $user ),
+ $moderatedAt->getHumanTimestamp()
+ );
+ } elseif ( $user === false ) {
+ return wfMessage( 'flow-user-moderated' );
+ } elseif ( $user->isAnon() && !$showIPs ) {
+ return wfMessage( 'flow-user-anonymous' );
+ } else {
+ return $user->getName();
+ }
+ }
}
diff --git a/modules/discussion/styles/topic.less
b/modules/discussion/styles/topic.less
index c57fbae..f307318 100644
--- a/modules/discussion/styles/topic.less
+++ b/modules/discussion/styles/topic.less
@@ -80,6 +80,10 @@
&:last-child {
padding: 0;
}
+
+ a {
+ color: inherit;
+ }
}
}
diff --git a/modules/discussion/ui.js b/modules/discussion/ui.js
index d7ff64a..567f5ad 100644
--- a/modules/discussion/ui.js
+++ b/modules/discussion/ui.js
@@ -54,6 +54,9 @@
// We're in a tangent
$form = $( this ).closest(
'.flow-post-replies' ).siblings( 'form.flow-reply-form' );
$( this ).closest(
'.flow-topic-container' ).find( '.flow-topic-reply-container' ).hide();
+ } else if ( $(this).is( '.flow-topic-comments
.flow-reply-link' ) ) {
+ // We're in the topic title
+ $form = $( this ).closest(
'.flow-topic-container').find( '.flow-topic-reply-form');
} else {
// Not in a tangent
$form = $( this ).closest( '.flow-post'
).siblings( 'form.flow-reply-form' );
@@ -177,15 +180,18 @@
} );
// Set up the scroll to new topic reply form
- $container.find( '.flow-topic-posts-meta .flow-post-number'
).click(
+ $container.find( '.flow-topic-comments .flow-reply-link'
).click(
function( e ) {
var $hideElement = $( this ).closest(
'.flow-topic-container' ).children( '.flow-post-container' ), self = this;
e.stopPropagation();
+
$hideElement.slideDown( function() {
var $viewport = $( 'html,body' ),
$replyContainer = $(
'#flow-topic-reply-' + $( self ).data( 'topic-id' ) );
+
$viewport.animate( {
- 'scrollTop':
$replyContainer.offset().top - $viewport.height()/2
+ 'scrollTop':
$replyContainer.offset().top - $viewport.height()/2,
+ 'complete':
$replyContainer.find( '.flow-topic-reply-content' ).click()
}, 500 );
} );
}
@@ -205,7 +211,8 @@
'.flow-actions',
'.flow-icon-permalink',
'.flow-icon-watchlist',
- '.flow-action-history-link'
+ '.flow-action-history-link',
+ '.flow-topic-comments'
];
if ( $( e.target ).closest( ignore.join( ',' )
).length > 0 ) {
return true;
diff --git a/templates/post.html.php b/templates/post.html.php
index 76794a5..829cfe0 100644
--- a/templates/post.html.php
+++ b/templates/post.html.php
@@ -23,7 +23,7 @@
) ) .
Html::textarea( $block->getName() . '[content]', '', array(
'placeholder' => wfMessage( 'flow-reply-placeholder',
- $post->getCreatorName( $user ) )->text(),
+ $this->getUserText( $post->getCreator( $user ),
$post ) )->text(),
'class' => 'flow-reply-content flow-input mw-ui-input',
) ) .
// NOTE: cancel button will be added via JS, makes no sense in
non-JS context
@@ -31,7 +31,7 @@
Html::openElement( 'div', array( 'class' =>
'flow-post-form-controls' ) ) .
Html::element( 'input', array(
'type' => 'submit',
- 'value' => wfMessage( 'flow-reply-submit',
$post->getCreatorName( $user ) )->text(),
+ 'value' => wfMessage( 'flow-reply-submit',
$this->getUserText( $post->getCreator( $user ), $post ) )->text(),
'class' => 'mw-ui-button mw-ui-constructive
flow-reply-submit',
) ) .
Html::closeElement( 'div' ) .
@@ -63,10 +63,10 @@
<div class="flow-post-title">
<span class="flow-creator">
<span class="flow-creator-simple"
style="display: inline">
- <?php echo
$post->getCreatorName( $user ); ?>
+ <?php echo $this->getUserText(
$post->getCreator( $user ), $post ); ?>
</span>
<span class="flow-creator-full"
style="display: none">
- <?php echo
$this->userToolLinks( $post->getCreatorId(), $post->getCreatorName() ); ?>
+ <?php echo
$this->userToolLinks( $post->getCreatorId( $user ), $post->getCreatorName(
$user ) ); ?>
</span>
</span>
</div>
@@ -97,8 +97,8 @@
<div class="flow-post-interaction">
<?php if ( !$post->isModerated() ): ?>
- <a class="flow-reply-link mw-ui-button"
href="#"><span><?php echo wfMessage( 'flow-reply-link', $post->getCreatorName(
$user ) )->escaped(); ?></span></a>
- <a class="flow-thank-link mw-ui-button"
href="#" onclick="alert( '@todo: Not yet implemented!' ); return
false;"><span><?php echo wfMessage( 'flow-thank-link', $post->getCreatorName(
$user ) )->escaped(); ?></span></a>
+ <a class="flow-reply-link mw-ui-button"
href="#"><span><?php echo wfMessage( 'flow-reply-link', $this->getUserText(
$post->getCreator( $user ), $post ) )->escaped(); ?></span></a>
+ <a class="flow-thank-link mw-ui-button"
href="#" onclick="alert( '@todo: Not yet implemented!' ); return
false;"><span><?php echo wfMessage( 'flow-thank-link', $this->getUserText(
$post->getCreator( $user ), $post ) )->escaped(); ?></span></a>
<?php else: ?>
<?php
$user = User::newFromId(
$post->getModeratedByUserId() );
diff --git a/templates/topic.html.php b/templates/topic.html.php
index d00e401..0adade3 100644
--- a/templates/topic.html.php
+++ b/templates/topic.html.php
@@ -3,6 +3,11 @@
// treat title like unparsed (wiki)text
$title = $root->getContent( $user, 'wikitext' );
+// pre-register recursive callbacks; will then be fetched all at once when the
+// first one's result is requested
+$indexDescendantCount = $root->registerDescendantCount();
+$indexParticipants = $root->registerParticipants();
+
echo Html::openElement( 'div', array(
'class' => 'flow-topic-container flow-topic-full',
'id' => 'flow-topic-' . $topic->getId()->getHex(),
@@ -42,6 +47,24 @@
</div>
</div>
+ <p class="flow-datestamp">
+ <?php
+ // timestamp html
+ $content = '
+ <span class="flow-agotime"
style="display: inline">'. $topic->getLastModifiedObj()->getHumanTimestamp()
.'</span>
+ <span class="flow-utctime"
style="display: none">'. $topic->getLastModifiedObj()->getTimestamp( TS_RFC2822
) .'</span>';
+
+ // build history button with timestamp html as
content
+ echo Html::rawElement( 'a',
+ array(
+ 'class' =>
'flow-action-history-link',
+ 'href' => $this->generateUrl(
$root->getPostId(), 'topic-history' ),
+ ),
+ $content
+ );
+ ?>
+ </p>
+
<?php
echo Html::element(
'a',
@@ -55,8 +78,18 @@
?>
<ul class="flow-topic-posts-meta">
- <li>@todo: participants</li>
- <li class="flow-post-number" data-topic-id="<?php echo
$topic->getId()->getHex() ?>">@todo: # comments</li>
+ <li class="flow-topic-participants">
+ <?php echo $this->printParticipants( $root,
$indexParticipants ); ?>
+ </li>
+ <li class="flow-topic-comments">
+ <a href="#" class="flow-reply-link"
data-topic-id="<?php echo $topic->getId()->getHex() ?>">
+ <?php
+ // get total number of posts in
topic
+ $comments =
$root->getRecursiveResult( $indexDescendantCount );
+ echo wfMessage(
'flow-topic-comments', $comments )->text();
+ ?>
+ </a>
+ </li>
</ul>
<?php
@@ -75,24 +108,6 @@
wfMessage( 'flow-topic-action-watchlist'
)->text()
);
?>
-
- <p class="flow-datestamp">
- <?php
- // timestamp html
- $content = '
- <span class="flow-agotime"
style="display: inline">'. $topic->getLastModifiedObj()->getHumanTimestamp()
.'</span>
- <span class="flow-utctime"
style="display: none">'. $topic->getLastModifiedObj()->getTimestamp( TS_RFC2822
) .'</span>';
-
- // build history button with timestamp html as
content
- echo Html::rawElement( 'a',
- array(
- 'class' =>
'flow-action-history-link',
- 'href' => $this->generateUrl(
$root->getPostId(), 'topic-history' ),
- ),
- $content
- );
- ?>
- </p>
</div>
</div>
<?php
@@ -109,7 +124,7 @@
?>
<span class="flow-creator">
<span class="flow-creator-simple" style="display: inline">
- <?php echo htmlspecialchars( $user->getName() ); ?>
+ <?php echo $this->getUserText( $user ); ?>
</span>
<span class="flow-creator-full" style="display: none">
<?php echo $this->userToolLinks( $user->getId(),
$user->getName() ); ?>
@@ -138,7 +153,7 @@
Html::openElement( 'div', array( 'class' => 'flow-post-form-controls' )
),
Html::element( 'input', array(
'type' => 'submit',
- 'value' => wfMessage( 'flow-reply-submit',
$root->getCreatorName( $user ) )->text(),
+ 'value' => wfMessage( 'flow-reply-submit', $this->getUserText(
$root->getCreator( $user ), $root ) )->text(),
'class' => 'mw-ui-button mw-ui-constructive
flow-topic-reply-submit',
) ),
Html::closeElement( 'div' ),
--
To view, visit https://gerrit.wikimedia.org/r/89220
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I3d1aedeebd595d24abbdb362e103860821d37a6f
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Bsitu <[email protected]>
Gerrit-Reviewer: EBernhardson <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Spage <[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