EBernhardson has uploaded a new change for review. https://gerrit.wikimedia.org/r/91306
Change subject: Refactor much of the php code out of post.html.php ...................................................................... Refactor much of the php code out of post.html.php Attempts to refactor many of the longer and multi-line php statements out of post.html.php and into a helper class. This should help making it easier and more obvious what values we can reuse when rendering 50 different posts, and which need to be recalculated for each post. Change-Id: I6024f66becb8b858b824f9e9f5ca04e07d0f91f3 --- M Flow.php M includes/Block/Header.php M includes/Block/Topic.php M includes/Model/AbstractRevision.php M includes/Templating.php A includes/View/Post.php M modules/base/ext.flow.base.js M templates/post.html.php 8 files changed, 251 insertions(+), 64 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow refs/changes/06/91306/1 diff --git a/Flow.php b/Flow.php index 451b463..d40ca00 100755 --- a/Flow.php +++ b/Flow.php @@ -85,6 +85,7 @@ // Helpers for templating $wgAutoloadClasses['Flow\View\PostActionMenu'] = "$dir/includes/View/PostActionMenu.php"; +$wgAutoloadClasses['Flow\View\Post'] = "$dir/includes/View/Post.php"; // Classes that deal with database interaction between database and the models $wgAutoloadClasses['Flow\Repository\TreeRepository'] = $dir . 'includes/Repository/TreeRepository.php'; diff --git a/includes/Block/Header.php b/includes/Block/Header.php index 14f9540..b595b90 100644 --- a/includes/Block/Header.php +++ b/includes/Block/Header.php @@ -6,7 +6,6 @@ use Flow\Data\ObjectManager; use Flow\Model\Workflow; use Flow\Model\Header; -use Flow\Repository\HeaderRepository; use Flow\Templating; use User; diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php index 6cec6dc..5e7f782 100644 --- a/includes/Block/Topic.php +++ b/includes/Block/Topic.php @@ -347,7 +347,7 @@ } if ( ! $post ) { - throw new MWException( "Requested post could not be found" ); + throw new \MWException( "Requested post could not be found" ); } return array( $this->renderPostAPI( $templating, $post, $options ) ); diff --git a/includes/Model/AbstractRevision.php b/includes/Model/AbstractRevision.php index 89776a5..84df9eb 100644 --- a/includes/Model/AbstractRevision.php +++ b/includes/Model/AbstractRevision.php @@ -275,7 +275,11 @@ public function getContent( $user = null, $format = 'html' ) { if ( $this->isAllowed( $user ) ) { - return $this->getConvertedContent( $format ); + if ( $this->isFormatted() ) { + return $this->getConvertedContent( $format ); + } else { + return $this->getContentRaw(); + } } else { $moderatedAt = new MWTimestamp( $this->moderationTimestamp ); diff --git a/includes/Templating.php b/includes/Templating.php index 250404c..c0c0e3d 100644 --- a/includes/Templating.php +++ b/includes/Templating.php @@ -15,7 +15,6 @@ use RequestContext; use Title; use User; -use Flow\View\PostActionMenu; class Templating { protected $namespaces; @@ -88,21 +87,25 @@ public function renderPost( PostRevision $post, Block $block, $return = true ) { global $wgUser, $wgFlowTokenSalt; - + $view = new View\Post( + $wgUser, + $post, + new View\PostActionMenu( + $this->urlGenerator, + $wgUser, + $block, + $post, + $wgUser->getEditToken( $wgFlowTokenSalt ) + ) + ); return $this->render( 'flow:post.html.php', array( 'block' => $block, 'post' => $post, + 'postView' => $view, // An ideal world may pull this from the container, but for now this is fine. This templating // class has too many responsibilities to keep receiving all required objects in the constructor. - 'postActionMenu' => new PostActionMenu( - $this->urlGenerator, - $wgUser, - $block, - $post, - $wgUser->getEditToken( $wgFlowTokenSalt ) - ), ), $return ); @@ -153,13 +156,18 @@ public function userToolLinks( $userId, $userText ) { global $wgLang; + static $cache = array(); + if ( isset( $cache[$userId][$userText] ) ) { + return $cache[$userId][$userText]; + } if ( $userText instanceof MWMessage ) { // username was moderated away, we dont know who this is - return ''; + $res = ''; + } else { + $res = Linker::userLink( $userId, $userText ) . Linker::userToolLinks( $userId, $userText ); } - - return Linker::userLink( $userId, $userText ) . Linker::userToolLinks( $userId, $userText ); + return $cache[$userId][$userText] = $res; } /** @@ -194,7 +202,7 @@ $haveAnon = true; } - $text = $this->getUserText( $participant ); + $text = self::getUserText( $participant ); if ( !$text || !$participant ) { continue; @@ -220,13 +228,13 @@ * 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 User $user The User object to get a description of. * @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 ) { + static public function getUserText( $user, $rev = null, $showIPs = false ) { if ( $user === false && $rev instanceof AbstractRevision ) { $state = $rev->getModerationState(); @@ -240,7 +248,7 @@ return wfMessage( AbstractRevision::$perms[$state]['content'], - $this->getUserText( $user ), + self::getUserText( $user ), $moderatedAt->getHumanTimestamp() ); } elseif ( $user === false ) { diff --git a/includes/View/Post.php b/includes/View/Post.php new file mode 100644 index 0000000..560eb99 --- /dev/null +++ b/includes/View/Post.php @@ -0,0 +1,185 @@ +<?php + +namespace Flow\View; + +use Flow\Model\PostRevision; +use Flow\Templating; +use Linker; +use User; + +class Post { + protected $user; + protected $actions; + + /** + * @param User $user The User viewing posts + */ + public function __construct( User $user, PostRevision $post, PostActionMenu $actions ) { + $this->user = $user; + $this->post = $post; + $this->actions = $actions; + + $this->creatorUserText = Templating::getUserText( + $post->getCreator( $this->user ), + $post + ); + + } + + public function replyPlaceholder() { + static $cache; + if ( isset( $cache[$this->creatorUserText] ) ) { + return $cache[$this->creatorUserText]; + } + return $cache[$this->creatorUserText] = wfMessage( 'flow-reply-placeholder', $this->creatorUserText )->text(); + } + + public function replySubmit() { + static $cache; + if ( isset( $cache[$this->creatorUserText] ) ) { + return $this->creatorUserText; + } + return $cache[$this->creatorUserText] = wfMessage( 'flow-reply-submit', $this->creatorUserText )->text(); + } + + public function replyLink() { + static $cache; + if ( isset( $cache[$this->creatorUserText] ) ) { + return $cache[$this->creatorUserText]; + } + return $cache[$this->creatorUserText] = wfMessage( 'flow-reply-link', $this->creatorUserText )->escaped(); + } + + public function thankLink() { + static $cache; + if ( isset( $cache[$this->creatorUserText] ) ) { + return $cache[$this->creatorUserText]; + } + return $cache[$this->creatorUserText] = wfMessage( 'flow-thank-link', $this->creatorUserText)->escaped(); + } + + public function moderatedTalkLink() { + $user = User::newFromId( $this->post->getModeratedByUserId() ); + $title = $user->getTalkPage(); + + return array( + $title->getLinkUrl(), + wfMessage( + 'flow-talk-link', + $this->post->getModeratedByUserText() + )->escaped() + ); + } + + public function creator() { + return $this->creatorUserText; + } + + public function userToolLinks( $userId, $userText ) { + if ( $userText instanceof MWMessage ) { + // username was moderated away, we dont know who this is + return ''; + } else { + static $cache = array(); + if ( !isset( $cache[$userId][$userText] ) ) { + $cache[$userId][$userText] = Linker::userLink( $userId, $userText ) . Linker::userToolLinks( $userId, $userText ); + } + return $cache[$userId][$userText]; + } + } + + public function creatorToolLinks() { + return $this->userToolLinks( + $this->post->getCreatorId( $this->user ), + $this->post->getCreatorName( $this->user ) + ); + } + public function editPostButton( PostRevision $post, $buttonClass ) { + if ( !$this->actions->isAllowed( 'edit-post' ) ) { + return ''; + } + return $this->actions->getButton( + 'edit-post', + wfMessage( 'flow-post-action-edit-post' )->plain(), + $buttonClass + ); + } + + public function postHistoryButton( PostRevision $post, $content ) { + if ( $this->actions->isAllowed( 'post-history' ) ) { + return $this->actions->getButton( + 'post-history', + $content, + 'flow-action-history-link' + ); + } else { + return $content; + } + } + + public function hidePostButton( PostRevision $post, $buttonClass ) { + if ( !$this->actions->isAllowed( 'hide-post' ) ) { + return ''; + } + return $this->actions->getButton( + 'hide-post', + wfMessage( 'flow-post-action-hide-post' )->plain(), + $buttonClass + ); + } + + public function deletePostButton( PostRevision $post, $buttonClass ) { + if ( !$this->actions->isAllowed( 'delete-post' ) ) { + return ''; + } + return $this->actions->getButton( + 'delete-post', + wfMessage( 'flow-post-action-delete-post' )->plain(), + $buttonClass + ); + } + + public function suppressPostButton( PostRevision $post, $buttonClass ) { + if ( !$this->actions->isAllowed( 'censor-post' ) ) { + return ''; + } + return $this->actions->getButton( + 'censor-post', + wfMessage( 'flow-post-action-censor-post' )->plain(), + $buttonClass + ); + } + + public function restorePostButton( PostRevision $post, $buttonClass ) { + if ( !$this->actions->isAllowed( 'restore-post' ) ) { + return ''; + } + return $this->actions->getButton( + 'restore-post', + wfMessage( 'flow-post-action-restore-post' )->plain(), + $buttonClass + ); + } + + public function actions() { + return $this->actions; + } + + public function allowedAnyActions() { + return $this->actions->isAllowedAny( 'hide-post', 'delete-post', 'censor-post', 'restore-post' ); + } + + /** + * 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 of. + * @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 ) { + return Templating::getUserText( $user, $rev, $showIPs ); + } +} diff --git a/modules/base/ext.flow.base.js b/modules/base/ext.flow.base.js index 7ad5242..02391a6 100644 --- a/modules/base/ext.flow.base.js +++ b/modules/base/ext.flow.base.js @@ -268,4 +268,9 @@ ] ); +// random onclick handler moved from html template +mw.flow.notImplemented = function() { + alert( '@todo: Not yet implemented!' ); + return false; +}; } )( jQuery, mediaWiki ); diff --git a/templates/post.html.php b/templates/post.html.php index 829cfe0..4e989c9 100644 --- a/templates/post.html.php +++ b/templates/post.html.php @@ -22,16 +22,15 @@ 'value' => $post->getPostId()->getHex(), ) ) . Html::textarea( $block->getName() . '[content]', '', array( - 'placeholder' => wfMessage( 'flow-reply-placeholder', - $this->getUserText( $post->getCreator( $user ), $post ) )->text(), + 'placeholder' => $postView->replyPlaceholder( $post ), 'class' => 'flow-reply-content flow-input mw-ui-input', ) ) . // NOTE: cancel button will be added via JS, makes no sense in non-JS context Html::openElement( 'div', array( 'class' => 'flow-post-form-controls' ) ) . Html::element( 'input', array( - 'type' => 'submit', - 'value' => wfMessage( 'flow-reply-submit', $this->getUserText( $post->getCreator( $user ), $post ) )->text(), + 'c fed $/type' => 'submit', + 'value' => $postView->replySubmit( $post ), 'class' => 'mw-ui-button mw-ui-constructive flow-reply-submit', ) ) . Html::closeElement( 'div' ) . @@ -39,17 +38,11 @@ } -// The actual output -echo Html::openElement( 'div', array( - 'class' => 'flow-post-container', - 'data-post-id' => $post->getRevisionId()->getHex(), -) ); - echo Html::openElement( 'div', array( - 'class' => 'flow-post flow-element-container ' . ( $post->isModerated() ? 'flow-post-moderated' : 'flow-post-unmoderated' ), - 'data-post-id' => $post->getPostId()->getHex(), - 'id' => 'flow-post-' . $post->getPostId()->getHex(), - ) ); ?> - +?> +<div class='flow-post-container' + data-revision-id='<?php echo $post->getRevisionId()->getHex() ?>' + data-post-id='<?php echo $post->getPostId()->getHex() ?>' > + <div class='flow-post flow-element-container <?php echo $post->isModerated() ? 'flow-post-moderated' : 'fow-post-unmoderated' ?>' > <?php if ( $post->isModerated() ): ?> <p class="flow-post-moderated-message flow-post-moderated-<?php echo $post->getModerationState(); ?> flow-post-content-<?php echo $post->isAllowed( $user ) ? 'allowed' : 'disallowed'; ?>"> <?php @@ -63,21 +56,18 @@ <div class="flow-post-title"> <span class="flow-creator"> <span class="flow-creator-simple" style="display: inline"> - <?php echo $this->getUserText( $post->getCreator( $user ), $post ); ?> + <?php echo $postView->creator( $post ) ?> </span> <span class="flow-creator-full" style="display: none"> - <?php echo $this->userToolLinks( $post->getCreatorId( $user ), $post->getCreatorName( $user ) ); ?> + <?php echo $postView->creatorToolLinks( $post ) ?> </span> </span> - </div> + </div> <div class="flow-post-content"> <?php echo $post->getContent( $user, 'html' ); ?> </div> - <?php if ( $postActionMenu->isAllowed( 'edit-post' ) ) { - echo $postActionMenu->getButton( 'edit-post', wfMessage( 'flow-post-action-edit-post' )->plain(), 'flow-edit-post-link flow-icon flow-icon-bottom-aligned' ); - } - ?> + <?php echo $postView->editPostButton( $post, 'flow-edit-post-link flow-icon flow-icon-bottom-aligned' ); ?> <p class="flow-datestamp"> <?php @@ -87,48 +77,43 @@ <span class="flow-utctime" style="display: none">'. $post->getPostId()->getTimestampObj()->getTimestamp( TS_RFC2822 ) .'</span>'; // build history button with timestamp html as content - if ( $postActionMenu->isAllowed( 'post-history' ) ) { - echo $postActionMenu->getButton( 'post-history', $content, 'flow-action-history-link' ); - } else { - echo $content; - } + echo $postView->postHistoryButton( $post, $content ); ?> </p> <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', $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> + <a class="flow-reply-link mw-ui-button" href="#"><span><?php $postView->replyLink( $post ); ?></span></a> + <a class="flow-thank-link mw-ui-button" href="#" onclick="return mw.flow.notImplemented()"> + <span><?php $postView->thankLink( $post ); ?></span> + </a> <?php else: ?> - <?php - $user = User::newFromId( $post->getModeratedByUserId() ); - $title = $user->getTalkPage(); - ?> - <a class="flow-talk-link mw-ui-button" href="<?php echo $title->getLinkURL(); ?>"> - <span><?php echo wfMessage( 'flow-talk-link', $post->getModeratedByUserText() )->escaped(); ?></span> + <?php list( $talkUrl, $talkLink ) = $postView->moderatedTalkLink( $post ); ?> + <a class="flow-talk-link mw-ui-button" href="<?php echo $talkUrl; ?>"> + <span><?php echo $talkLink; ?></span> </a> <?php endif; ?> </div> </div> - <?php if ( $postActionMenu->isAllowedAny( 'hide-post', 'delete-post', 'censor-post', 'restore-post' ) ): ?> + <?php if ( $postView->actions()->isAllowedAny( 'hide-post', 'delete-post', 'censor-post', 'restore-post' ) ): ?> <div class="flow-actions"> <a class="flow-actions-link flow-icon flow-icon-bottom-aligned" href="#"><?php echo wfMessage( 'flow-post-actions' )->escaped(); ?></a> <div class="flow-actions-flyout"> <ul> <?php - if ( $postActionMenu->isAllowed( 'hide-post' ) ) { - echo '<li class="flow-action-hide">'. $postActionMenu->getButton( 'hide-post', wfMessage( 'flow-post-action-hide-post' )->plain(), 'flow-hide-post-link mw-ui-button' ) .'</li>'; + if ( $hidePost = $postView->hidePostButton( $post, 'flow-hide-post-link mw-ui-button' ) ) { + echo "<li class='flow-action-hide'>$hidePost</li>"; } - if ( $postActionMenu->isAllowed( 'delete-post' ) ) { - echo '<li class="flow-action-delete">'. $postActionMenu->getButton( 'delete-post', wfMessage( 'flow-post-action-delete-post' )->plain(), 'flow-delete-post-link mw-ui-button' ) .'</li>'; + if ( $deletePost = $postView->deletePostButton( $post, 'flow-delete-post-link mw-ui-button' ) ) { + echo "<li class='flow-action-delete'>$deletePost</li>"; } - if ( $postActionMenu->isAllowed( 'censor-post' ) ) { - echo '<li class="flow-action-censor">'. $postActionMenu->getButton( 'censor-post', wfMessage( 'flow-post-action-censor-post' )->plain(), 'flow-censor-post-link mw-ui-button' ) .'</li>'; + if ( $suppressPost = $postView->suppressPostButton( $post, 'flow-censor-post-link mw-ui-button' ) ) { + echo "<li class='flow-action-censor'>$suppressPost</li>"; } // @todo restore button will probably be moved somewhere else, some day - if ( $postActionMenu->isAllowed( 'restore-post' ) ) { - echo '<li class="flow-action-restore">'. $postActionMenu->getButton( 'restore-post', wfMessage( 'flow-post-action-restore-post' )->plain(), 'flow-restore-post-link mw-ui-button mw-ui-constructive' ) .'</li>'; + if ( $restorePost = $postView->restorePostButton( $post, 'flow-restore-post-link mw-ui-button mw-ui-constructive' ) ) { + echo "<li class='flow-action-restore'>$restorePost</li>"; } ?> </ul> -- To view, visit https://gerrit.wikimedia.org/r/91306 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6024f66becb8b858b824f9e9f5ca04e07d0f91f3 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Flow Gerrit-Branch: master Gerrit-Owner: EBernhardson <ebernhard...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits