r73604 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r73603‎ | r73604 | r73605 >
Date:14:12, 23 September 2010
Author:werdna
Status:deferred (Comments)
Tags:
Comment:
LiquidThreads: Allow embedding threads and discussion pages in wikitext.
Modified paths:
  • /trunk/extensions/LiquidThreads/LiquidThreads.php (modified) (history)
  • /trunk/extensions/LiquidThreads/LqtFunctions.php (modified) (history)
  • /trunk/extensions/LiquidThreads/api/ApiThreadAction.php (modified) (history)
  • /trunk/extensions/LiquidThreads/classes/ParserFunctions.php (modified) (history)
  • /trunk/extensions/LiquidThreads/classes/View.php (modified) (history)
  • /trunk/extensions/LiquidThreads/lqt.js (modified) (history)
  • /trunk/extensions/LiquidThreads/pages/TalkpageView.php (modified) (history)

Diff [purge]

Index: trunk/extensions/LiquidThreads/LqtFunctions.php
@@ -47,6 +47,13 @@
4848 'lqtpagelimit',
4949 array( 'LqtParserFunctions', 'lqtPageLimit' )
5050 );
 51+
 52+ global $wgLiquidThreadsAllowEmbedding;
 53+
 54+ if ($wgLiquidThreadsAllowEmbedding) {
 55+ $parser->setHook( 'talkpage', array( 'LqtParserFunctions', 'lqtTalkPage' ) );
 56+ $parser->setHook( 'thread', array( 'LqtParserFunctions', 'lqtThread' ) );
 57+ }
5158
5259 return true;
5360 }
Index: trunk/extensions/LiquidThreads/LiquidThreads.php
@@ -124,6 +124,10 @@
125125 // $wgSpecialPages['HotTopics'] = 'SpecialHotTopics';
126126 $wgSpecialPageGroups['NewMessages'] = 'wiki';
127127
 128+// Embedding
 129+$wgHooks['OutputPageParserOutput'][] = 'LqtParserFunctions::onAddParserOutput';
 130+$wgHooks['OutputPageBeforeHTML'][] = 'LqtParserFunctions::onAddHTML';
 131+
128132 // Classes
129133 $wgAutoloadClasses['LqtDispatch'] = $dir . 'classes/Dispatch.php';
130134 $wgAutoloadClasses['LqtView'] = $dir . 'classes/View.php';
@@ -248,3 +252,6 @@
249253 in specific namespaces. NULL means either all or none, depending
250254 on the above. */
251255 $wgLiquidThreadsAllowUserControlNamespaces = null;
 256+
 257+/** Allow LiquidThreads embedding */
 258+$wgLiquidThreadsAllowEmbedding = true;
Index: trunk/extensions/LiquidThreads/classes/View.php
@@ -308,6 +308,13 @@
309309 $operand = $this->request->getVal( 'lqt_operand' );
310310
311311 $thread = Threads::withId( intval( $operand ) );
 312+
 313+ // Yuck.
 314+ global $wgOut, $wgRequest;
 315+ $oldOut = $wgOut;
 316+ $oldRequest = $wgRequest;
 317+ $wgOut = $this->output;
 318+ $wgRequest = $this->request;
312319
313320 $hookResult = wfRunHooks( 'LiquidThreadsDoInlineEditForm',
314321 array(
@@ -324,10 +331,41 @@
325332 $this->showNewThreadForm( $this->article );
326333 } elseif ( $method == 'edit' ) {
327334 $this->showPostEditingForm( $thread );
 335+ } else {
 336+ throw new MWException( "Invalid thread method $method" );
328337 }
 338+
 339+ $wgOut = $oldOut;
 340+ $wgRequest = $oldRequest;
329341
330342 $this->output->setArticleBodyOnly( true );
331343 }
 344+
 345+ static function getInlineEditForm( $talkpage, $method, $operand ) {
 346+ $output = new OutputPage;
 347+ $request = new FauxRequest( array() );
 348+ $title = null;
 349+
 350+ if ( $talkpage ) {
 351+ $title = $talkpage->getTitle();
 352+ } elseif ( $operand ) {
 353+ $thread = Threads::withId( $operand );
 354+ if ( $thread ) {
 355+ $talkpage = $thread->article();
 356+ $title = $talkpage->getTitle();
 357+ }
 358+ }
 359+
 360+ $request->setVal( 'lqt_method', $method );
 361+ $request->setVal( 'lqt_operand', $operand );
 362+
 363+ global $wgUser;
 364+ $view = new LqtView( $output, $talkpage, $title, $wgUser, $request );
 365+
 366+ $view->doInlineEditForm();
 367+
 368+ return $output->getHTML();
 369+ }
332370
333371 function showNewThreadForm( $talkpage ) {
334372 $submitted_nonce = $this->request->getVal( 'lqt_nonce' );
@@ -1931,6 +1969,14 @@
19321970 $thread->sortkey(),
19331971 array( 'id' => 'lqt-thread-sortkey-' . $thread->id() )
19341972 );
 1973+
 1974+ $html .= Xml::hidden(
 1975+ 'lqt-thread-talkpage-' . $thread->id(),
 1976+ $thread->article()->getTitle()->getPrefixedText(),
 1977+ array(
 1978+ 'class' => 'lqt-thread-talkpage-metadata',
 1979+ )
 1980+ );
19351981 }
19361982
19371983 if ( ! $thread->title() ) {
Index: trunk/extensions/LiquidThreads/classes/ParserFunctions.php
@@ -19,4 +19,171 @@
2020 $parser->mOutput->setProperty( 'lqt-page-limit', $param );
2121 }
2222 }
 23+
 24+ /** To bypass the parser cache just for the LiquidThreads part, we have a cute trick.
 25+ * We leave a placeholder comment in the HTML, which we expand out in a hook. This way,
 26+ * most of the page can be cached, but the LiquidThreads dynamicism still works.
 27+ * Thanks to Tim for the idea. */
 28+ static function lqtTalkPage( $parser, $args, $parser, $frame ) {
 29+ global $wgStyleVersion;
 30+
 31+ $pout = $parser->getOutput();
 32+
 33+ // Prepare information.
 34+ $title = null;
 35+ if ( $args['talkpage'] ) {
 36+ $title = Title::newFromText( $args['talkpage'] );
 37+ }
 38+ if ( is_null($title) ) {
 39+ $title = $parser->getTitle();
 40+ }
 41+
 42+ $talkpage = new Article( $title );
 43+ $article = new Article( $parser->getTitle() );
 44+
 45+ $data = array(
 46+ 'type' => 'talkpage',
 47+ 'args' => $args,
 48+ 'article' => $article,
 49+ 'title' => $article->getTitle(),
 50+ 'talkpage' => $talkpage,
 51+ );
 52+
 53+ if ( !isset( $pout->mLqtReplacements ) ) {
 54+ $pout->mLqtReplacements = array();
 55+ }
 56+
 57+ // Generate a token
 58+ $tok = wfGenerateToken();
 59+ $text = '<!--LQT-PAGE-'.$tok.'-->';
 60+ $pout->mLqtReplacements[$text] = $data;
 61+
 62+ return $text;
 63+ }
 64+
 65+ static function lqtThread( $parser, $args, $parser, $frame ) {
 66+ global $wgStyleVersion;
 67+
 68+ $pout = $parser->getOutput();
 69+
 70+ // Prepare information.
 71+ $title = Title::newFromText( $args['thread'] );
 72+ $thread = null;
 73+ if ( $args['thread'] ) {
 74+ if ( is_numeric( $args['thread'] ) ) {
 75+ $thread = Threads::withId( $args['thread'] );
 76+ } elseif ( $title ) {
 77+ $article = new Article( $title );
 78+ $thread = Threads::withRoot( $article );
 79+ }
 80+ }
 81+
 82+ if ( is_null( $thread ) ) {
 83+ return '';
 84+ }
 85+
 86+ $data = array(
 87+ 'type' => 'thread',
 88+ 'args' => $args,
 89+ 'thread' => $thread->id(),
 90+ 'title' => $thread->title(),
 91+ );
 92+
 93+ if ( !isset( $pout->mLqtReplacements ) ) {
 94+ $pout->mLqtReplacements = array();
 95+ }
 96+
 97+ // Generate a token
 98+ $tok = wfGenerateToken();
 99+ $text = '<!--LQT-THREAD-'.$tok.'-->';
 100+ $pout->mLqtReplacements[$text] = $data;
 101+
 102+ return $text;
 103+ }
 104+
 105+ static function runLqtTalkPage( $details ) {
 106+ extract($details);
 107+
 108+ global $wgUser, $wgRequest, $wgOut;
 109+ $oldOut = $wgOut->getHTML();
 110+ $wgOut->clearHTML();
 111+
 112+ $view = new TalkpageView( $wgOut, $article, $title, $wgUser, $wgRequest );
 113+ $view->setTalkpage( $talkpage );
 114+
 115+ // Handle show/hide preferences. Header gone by default.
 116+ $view->hideItems( 'header' );
 117+
 118+ if ( array_key_exists( 'show', $args ) ) {
 119+ $show = explode( ' ', $args['show'] );
 120+ $view->setShownItems( $show );
 121+ }
 122+
 123+ $view->show();
 124+
 125+ $html = $wgOut->getHTML();
 126+ $wgOut->clearHTML();
 127+ $wgOut->getHTML( $oldOut );
 128+
 129+ return $html;
 130+ }
 131+
 132+ static function showLqtThread( $details ) {
 133+ extract($details);
 134+
 135+ global $wgUser, $wgRequest, $wgOut;
 136+ $oldOut = $wgOut->getHTML();
 137+ $wgOut->clearHTML();
 138+
 139+ $thread = Threads::withId( $thread );
 140+
 141+ $view = new LqtView( $wgOut, $article, $title, $wgUser, $wgRequest );
 142+
 143+ $view->showThread( $thread );
 144+
 145+ $html = $wgOut->getHTML();
 146+ $wgOut->clearHTML();
 147+ $wgOut->getHTML( $oldOut );
 148+
 149+ return $html;
 150+ }
 151+
 152+ static function onAddParserOutput( &$out, $pout ) {
 153+ if ( !isset($pout->mLqtReplacements ) ) {
 154+ return true;
 155+ }
 156+
 157+ if ( !isset($out->mLqtReplacements) ) {
 158+ $out->mLqtReplacements = array();
 159+ }
 160+
 161+ $processedReplacements = array();
 162+ foreach( $pout->mLqtReplacements as $text => $details ) {
 163+ $result = '';
 164+
 165+ if ( $details['type'] == 'talkpage' ) {
 166+ $result = self::runLqtTalkPage( $details );
 167+ } elseif ( $details['type'] == 'thread' ) {
 168+ $result = self::showLqtThread( $details );
 169+ }
 170+
 171+ $out->mLqtReplacements[$text] = $result;
 172+ LqtView::addJsAndCss();
 173+ }
 174+
 175+ return true;
 176+ }
 177+
 178+ static function onAddHTML( &$out, &$text ) {
 179+ if ( !isset($out->mLqtReplacements) || !count($out->mLqtReplacements) ) {
 180+ return true;
 181+ }
 182+
 183+ $replacements = $out->mLqtReplacements;
 184+
 185+ $replacer = new ReplacementArray( $replacements );
 186+ $text = $replacer->replace( $text );
 187+
 188+ return true;
 189+ }
23190 }
Index: trunk/extensions/LiquidThreads/pages/TalkpageView.php
@@ -2,6 +2,19 @@
33 if ( !defined( 'MEDIAWIKI' ) ) die;
44
55 class TalkpageView extends LqtView {
 6+ protected $mShowItems = array( 'toc', 'options', 'header' );
 7+ protected $talkpage;
 8+
 9+ function __construct( &$output, &$article, &$title, &$user, &$request ) {
 10+ parent::__construct( $output, $article, $title, $user, $request );
 11+
 12+ $this->talkpage = $article;
 13+ }
 14+
 15+ function setTalkPage($tp) {
 16+ $this->talkpage = $tp;
 17+ }
 18+
619 /* Added to SkinTemplateTabs hook in TalkpageView::show(). */
720 static function customizeTalkpageTabs( $skintemplate, &$content_actions, $view ) {
821 // The arguments are passed in by reference.
@@ -262,7 +275,9 @@
263276 $this->output->redirect( $url );
264277 }
265278
266 - $this->showHeader();
 279+ if ( $this->shouldShow('header') ) {
 280+ $this->showHeader();
 281+ }
267282
268283 $html = '';
269284
@@ -274,16 +289,18 @@
275290 $newThreadText = wfMsgExt( 'lqt_new_thread', 'parseinline' );
276291 $newThreadLink = $sk->link(
277292 $this->title, $newThreadText,
278 - array( ),
 293+ array( 'lqt_talkpage' => $this->talkpage->getTitle()->getPrefixedText() ),
279294 array( 'lqt_method' => 'talkpage_new_thread' ),
280295 array( 'known' )
281296 );
282297
283 - $talkpageHeader .= Xml::tags(
 298+ $newThreadLink = Xml::tags(
284299 'strong',
285300 array( 'class' => 'lqt_start_discussion' ),
286301 $newThreadLink
287302 );
 303+
 304+ $talkpageHeader .= $newThreadLink;
288305 }
289306
290307 $talkpageHeader .= $this->getSearchBox();
@@ -294,7 +311,11 @@
295312 $talkpageHeader
296313 );
297314
298 - $this->output->addHTML( $talkpageHeader );
 315+ if ( $this->shouldShow('options') ) {
 316+ $this->output->addHTML( $talkpageHeader );
 317+ } elseif ( $this->shouldShow('simplenew') ) {
 318+ $this->output->addHTML( $newThreadLink );
 319+ }
299320
300321 if ( $this->methodApplies( 'talkpage_new_thread' ) ) {
301322 $params = array( 'class' => 'lqt-new-thread lqt-edit-form' );
@@ -310,9 +331,9 @@
311332
312333 $threads = $this->getPageThreads( $pager );
313334
314 - if ( count( $threads ) > 0 ) {
 335+ if ( count( $threads ) > 0 && $this->shouldShow('toc') ) {
315336 $html .= $this->getTOC( $threads );
316 - } else {
 337+ } elseif ( count($threads) == 0 ) {
317338 $html .= Xml::tags( 'div', array( 'class' => 'lqt-no-threads' ),
318339 wfMsgExt( 'lqt-no-threads', 'parseinline' ) );
319340 }
@@ -363,7 +384,7 @@
364385 function getPager() {
365386
366387 $sortType = $this->getSortType();
367 - return new LqtDiscussionPager( $this->article, $sortType );
 388+ return new LqtDiscussionPager( $this->talkpage, $sortType );
368389 }
369390
370391 function getPageThreads( $pager ) {
@@ -390,6 +411,28 @@
391412 // Default
392413 return LQT_NEWEST_CHANGES;
393414 }
 415+
 416+ // Hide a number of items from the view
 417+ // Valid values: toc, options, header
 418+ function hideItems( $items ) {
 419+ $this->mShowItems = array_diff( $this->mShowItems, (array)$items );
 420+ }
 421+
 422+ // Show a number of items in the view
 423+ // Valid values: toc, options, header
 424+ function showItems( $items ) {
 425+ $this->mShowItems = array_merge( $this->mShowItems, (array)$items );
 426+ }
 427+
 428+ // Whether or not to show an item
 429+ function shouldShow( $item ) {
 430+ return in_array( $item, $this->mShowItems );
 431+ }
 432+
 433+ // Set the items shown
 434+ function setShownItems( $items ) {
 435+ $this->mShowItems = $items;
 436+ }
394437 }
395438
396439 class LqtDiscussionPager extends IndexPager {
Index: trunk/extensions/LiquidThreads/api/ApiThreadAction.php
@@ -774,6 +774,35 @@
775775 $this->getResult()->addValue( null, 'threadaction', $result );
776776 }
777777
 778+ public function actionInlineEditForm( $threads, $params ) {
 779+ $method = $talkpage = $operand = null;
 780+
 781+ if ( isset($params['method']) ) {
 782+ $method = $params['method'];
 783+ }
 784+
 785+ if ( isset( $params['talkpage'] ) ) {
 786+ $talkpage = $params['talkpage'];
 787+ }
 788+
 789+ if ( $talkpage ) {
 790+ $talkpage = new Article( Title::newFromText( $talkpage ) );
 791+ } else {
 792+ $talkpage = null;
 793+ }
 794+
 795+ if ( count($threads) ) {
 796+ $operand = $threads[0];
 797+ $operand = $operand->id();
 798+ }
 799+
 800+ $output = LqtView::getInlineEditForm( $talkpage, $method, $operand );
 801+
 802+ $result = array( 'inlineeditform' => array( 'html' => $output ) );
 803+
 804+ $this->getResult()->addValue( null, 'threadaction', $result );
 805+ }
 806+
778807 public function getDescription() {
779808 return 'Allows actions to be taken on threads and posts in threaded discussions.';
780809 }
@@ -791,6 +820,7 @@
792821 'edit' => 'actionEdit',
793822 'addreaction' => 'actionAddReaction',
794823 'deletereaction' => 'actionDeleteReaction',
 824+ 'inlineeditform' => 'actionInlineEditForm',
795825 );
796826 }
797827
@@ -818,6 +848,7 @@
819849 'NULL to specify the default signature',
820850 'type' => 'Specifies the type of reaction to add',
821851 'value' => 'Specifies the value associated with the reaction to add',
 852+ 'method' => 'For getting inline edit forms, the method to get a form for',
822853 );
823854 }
824855
@@ -877,6 +908,8 @@
878909 'signature' => null,
879910 'type' => null,
880911 'value' => null,
 912+ 'method' => null,
 913+ 'operand' => null,
881914 );
882915 }
883916
Index: trunk/extensions/LiquidThreads/lqt.js
@@ -25,7 +25,7 @@
2626 return;
2727 }
2828
29 - var query = '&lqt_method=reply&lqt_operand='+thread_id;
 29+ var params = { 'method' : 'reply', 'thread' : thread_id };
3030
3131 var repliesElement = $j(container).contents().filter('.lqt-thread-replies');
3232 var replyDiv = repliesElement.contents().filter('.lqt-reply-form');
@@ -45,7 +45,7 @@
4646
4747 replyDiv = replyDiv[0];
4848
49 - liquidThreads.injectEditForm( query, replyDiv, e.preload );
 49+ liquidThreads.injectEditForm( params, replyDiv, e.preload );
5050 liquidThreads.currentReplyThread = thread_id;
5151 },
5252
@@ -88,11 +88,12 @@
8989 'handleNewLink' : function(e) {
9090 e.preventDefault();
9191
92 - var query = '&lqt_method=talkpage_new_thread';
 92+ var talkpage = $j(this).attr('lqt_talkpage');
 93+ var params = {'talkpage' : talkpage, 'method' : 'talkpage_new_thread' };
9394
94 - var container = $j('.lqt-new-thread' );
 95+ var container = $j('.lqt-new-thread' ).data('lqt-talkpage', talkpage);
9596
96 - liquidThreads.injectEditForm( query, container );
 97+ liquidThreads.injectEditForm( params, container );
9798 liquidThreads.currentReplyThread = 0;
9899 },
99100
@@ -105,14 +106,17 @@
106107 var container = $j('<div/>').addClass('lqt-edit-form');
107108 parent.contents().fadeOut();
108109 parent.append(container);
109 - var query='&lqt_method=edit&lqt_operand='+parent.data('thread-id');
 110+ var params = { 'method' : 'edit', 'thread' : parent.data('thread-id') };
110111
111 - liquidThreads.injectEditForm( query, container );
 112+ liquidThreads.injectEditForm( params, container );
112113 },
113114
114 - 'injectEditForm' : function(query, container, preload) {
115 - var url = wgServer+wgScript+'?lqt_inline=1&title='+encodeURIComponent(wgPageName)+
116 - query;
 115+ 'injectEditForm' : function(params, container, preload) {
 116+ var page = $j(container).closest('.lqt-thread-topmost')
 117+ .find('.lqt-thread-talkpage-metadata').val();
 118+ if ( !page ) {
 119+ page = $j(container).data('lqt-talkpage');
 120+ }
117121
118122 liquidThreads.cancelEdit( container );
119123
@@ -197,17 +201,23 @@
198202 function() {
199203 if ( isIE7 ) {
200204 $j(container).empty().show();
201 - $j(container).load(wgServer+wgScript,
202 - 'title='+encodeURIComponent(wgPageName)+
203 - query+'&lqt_inline=1', finishSetup );
204 - } else {
205 - $j(container).load(wgServer+wgScript,
206 - 'title='+encodeURIComponent(wgPageName)+
207 - query+'&lqt_inline=1', finishSetup );
208205 }
 206+ liquidThreads.loadInlineEditForm( params, container, finishSetup );
209207 } );
210208
211209 },
 210+
 211+ 'loadInlineEditForm' : function( params, container, callback ) {
 212+ params['action'] = 'threadaction';
 213+ params['threadaction'] = 'inlineeditform';
 214+
 215+ liquidThreads.apiRequest( params,
 216+ function(result) {
 217+ var content = $j(result.threadaction.inlineeditform.html);
 218+ $j(container).empty().append(content);
 219+ callback();
 220+ } );
 221+ },
212222
213223 'doLivePreview' : function( e ) {
214224 e.preventDefault();
@@ -952,7 +962,9 @@
953963
954964 e.preventDefault();
955965 } else if ( type == 'talkpage_new_thread' ) {
956 - liquidThreads.doNewThread( wgPageName, subject, text, summary,
 966+ var container = editform.closest('.lqt-new-thread');
 967+ var page = container.data('lqt-talkpage');
 968+ liquidThreads.doNewThread( page, subject, text, summary,
957969 doneCallback, bump, signature );
958970
959971 e.preventDefault();

Comments

#Comment by Nikerabbit (talk | contribs)   17:44, 23 September 2010
+$talkpage = new Article( $title );
+$article = new Article( $parser->getTitle() );

You should pass 0 as second argument to the constructor unless you want hard to debug bugs when oldid is fetched from the request (unless that is the intention :) There are other instances too.

+if ( array_key_exists( 'show', $args ) ) {

Is there some reason not to use isset() here?

+		if ( count( $threads ) > 0 && $this->shouldShow('toc') ) {
+		} elseif ( count($threads) == 0 ) {

Inconsistent spaces around parenthesis.

#Comment by Reedy (talk | contribs)   23:53, 19 March 2011

Need to set a description for the operand api parameter. Added blank description in r84359

Status & tagging log