r87399 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r87398‎ | r87399 | r87400 >
Date:13:42, 4 May 2011
Author:werdna
Status:deferred
Tags:
Comment:
LiquidThreads rewrite: Polished off display code. Wrote a Formatter class for Topic objects; refactored toolbar code into its own class hierarchy.
Modified paths:
  • /branches/lqt-updates/extensions/LiquidThreads/LiquidThreads.php (modified) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/model/PostVersion.php (modified) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/model/Topic.php (modified) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/view/PostFormatter.php (modified) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/view/PostToolbar.php (added) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/view/Toolbar.php (added) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/view/TopicFormatter.php (added) (history)
  • /branches/lqt-updates/extensions/LiquidThreads/classes/view/TopicToolbar.php (added) (history)

Diff [purge]

Index: branches/lqt-updates/extensions/LiquidThreads/LiquidThreads.php
@@ -260,7 +260,14 @@
261261 $wgAutoloadClasses['LiquidThreadsFormatterContext'] = "$dir/classes/view/Formatter.php";
262262 $wgAutoloadClasses['LiquidThreadsPostFormatter'] = "$dir/classes/view/PostFormatter.php";
263263 $wgAutoloadClasses['LiquidThreadsPostFormatterContext'] = "$dir/classes/view/PostFormatter.php";
 264+$wgAutoloadClasses['LiquidThreadsTopicFormatter'] = "$dir/classes/view/TopicFormatter.php";
 265+$wgAutoloadClasses['LiquidThreadsTopicFormatterContext'] = "$dir/classes/view/TopicFormatter.php";
264266
 267+// Toolbars
 268+$wgAutoloadClasses['LiquidThreadsToolbar'] = "$dir/classes/view/Toolbar.php";
 269+$wgAutoloadClasses['LiquidThreadsPostToolbar'] = "$dir/classes/view/PostToolbar.php";
 270+$wgAutoloadClasses['LiquidThreadsTopicToolbar'] = "$dir/classes/view/TopicToolbar.php";
 271+
265272 /** CONFIGURATION SECTION */
266273
267274 $wgDefaultUserOptions['lqt-watch-threads'] = true;
Index: branches/lqt-updates/extensions/LiquidThreads/classes/model/PostVersion.php
@@ -140,6 +140,10 @@
141141 throw new MWException( "Invalid argument to ".__METHOD__ );
142142 }
143143
 144+ if ( $timestamp == null ) {
 145+ return $post->getCurrentVersion();
 146+ }
 147+
144148 $dbr = wfGetDB( DB_SLAVE );
145149
146150 $conds = array( 'lpv_post' => $post->getID() );
Index: branches/lqt-updates/extensions/LiquidThreads/classes/model/Topic.php
@@ -27,6 +27,9 @@
2828 /** Array of LiquidThreadsPost objects, the posts in this topic **/
2929 protected $posts;
3030
 31+ /** Array of LiquidThreadsPost objects, the direct responses to this topic. **/
 32+ protected $directResponses;
 33+
3134 /** The number of replies that this topic has **/
3235 protected $replyCount;
3336
@@ -341,6 +344,29 @@
342345 return $this->posts;
343346 }
344347
 348+ /**
 349+ * Retrieves direct responses to this topic.
 350+ * Basically, all posts with no parentID set
 351+ * @return Array of LiquidThreadsPost objects.
 352+ */
 353+ public function getDirectResponses() {
 354+ if ( is_array( $this->directResponses ) ) {
 355+ return $this->directResponses;
 356+ } // else
 357+
 358+ $posts = $this->getPosts();
 359+
 360+ $this->directResponses = array();
 361+
 362+ foreach( $posts as $post ) {
 363+ if ( ! $post->getParentID() ) {
 364+ $this->directResponses[$post->getID()] = $post;
 365+ }
 366+ }
 367+
 368+ return $this->directResponses;
 369+ }
 370+
345371 /* PROPERTY SETTERS */
346372
347373 /**
Index: branches/lqt-updates/extensions/LiquidThreads/classes/view/PostFormatter.php
@@ -1,7 +1,21 @@
22 <?php
33
44 class LiquidThreadsPostFormatter extends LiquidThreadsFormatter {
 5+
56 /**
 7+ * Get a shared instance of this class.
 8+ */
 9+ public static function singleton() {
 10+ static $singleton = null;
 11+
 12+ if ( !$singleton ) {
 13+ $singleton = new self;
 14+ }
 15+
 16+ return $singleton;
 17+ }
 18+
 19+ /**
620 * Returns the correct class for the context object
721 */
822 public function getContextClass() {
@@ -40,11 +54,9 @@
4155 }
4256
4357 $timestamp = $context->get('timestamp');
44 - if ( !is_null($timestamp) ) {
45 - $version = PostVersion::newPointInTime( $post, $timestamp );
46 - } else {
47 - $version = $object->getCurrentVersion();
48 - }
 58+ // NULL means current version
 59+ $version = LiquidThreadsPostVersion::newPointInTime( $object, $timestamp );
 60+ $context->set('version', $version);
4961
5062 if ( $context->get('single') ) {
5163 return $this->formatSingleComment( $object, $version, $context );
@@ -122,7 +134,7 @@
123135
124136 $html .= Xml::closeElement( 'div' );
125137
126 - $html .= $this->getToolbar( $object, $version, $context );
 138+ $html .= $this->getToolbar( $object, $context );
127139 $html .= $this->getPostSignature( $object, $version, $context );
128140 $html .= Xml::closeElement( 'div' );
129141 }
@@ -158,237 +170,11 @@
159171 * @param $context A LiquidThreadsPostFormatterContext object.
160172 * @return HTML
161173 */
162 - protected function getToolbar( $post, $version, $context ) {
163 - $html = '';
164 -
165 - $headerParts = array();
166 -
167 - foreach ( $this->getMajorCommands( $post, $version, $context ) as $key => $cmd ) {
168 - $content = $this->formatCommand( $cmd, false /* No icon divs */ );
169 - $headerParts[] = Xml::tags( 'li',
170 - array( 'class' => "lqt-command lqt-command-$key" ),
171 - $content );
172 - }
173 -
174 - // Drop-down menu
175 - $commands = $this->getMinorCommands( $post, $version, $context );
176 - $menuHTML = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-command-list' ),
177 - $this->formatCommands( $commands ) );
178 -
179 - $triggerText = Xml::tags( 'a', array( 'class' => 'lqt-thread-actions-icon',
180 - 'href' => '#' ),
181 - wfMsgHTML( 'lqt-menu-trigger' ) );
182 - $dropDownTrigger = Xml::tags( 'div',
183 - array( 'class' => 'lqt-thread-actions-trigger ' .
184 - 'lqt-command-icon', 'style' => 'display: none;' ),
185 - $triggerText );
186 -
187 - if ( count( $commands ) ) {
188 - $headerParts[] = Xml::tags( 'li',
189 - array( 'class' => 'lqt-thread-toolbar-menu' ),
190 - $dropDownTrigger );
191 - }
192 -
193 - $html .= implode( ' ', $headerParts );
194 -
195 - $html = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-commands' ), $html );
196 -
197 - $html = Xml::tags( 'div', array( 'class' => 'lqt-thread-toolbar' ), $html ) .
198 - $menuHTML;
199 -
200 - return $html;
201 - }
202 -
203 - /**
204 - * Formats a list of toolbar commands.
205 - * @param $commands Associative array of commands.
206 - * @return HTML
207 - * @see LiquidThreadsPostFormatter::formatCommand
208 - */
209 - function formatCommands( $commands ) {
210 - $result = array();
211 - foreach ( $commands as $key => $command ) {
212 - $thisCommand = $this->formatCommand( $command );
213 -
214 - $thisCommand = Xml::tags(
215 - 'li',
216 - array( 'class' => 'lqt-command lqt-command-' . $key ),
217 - $thisCommand
218 - );
219 -
220 - $result[] = $thisCommand;
221 - }
222 - return join( ' ', $result );
223 - }
224 -
225 - /**
226 - * Formats a toolbar command
227 - * @param $command Associative array describing this command
228 - * Valid keys:
229 - * label: The text to show for this command.
230 - * href: The URL to link to.
231 - * enabled: Whether or not this command is enabled.
232 - * tooltip: If specified, the tooltip to show for this command.
233 - * icon: If specified, an icon is shown.
234 - * showlabel: Whether or not to show the label. Default: on.
235 - * @param $icon_divs Boolean: If false, do not insert <divs> to style with an icon.
236 - * @return HTML: Command formatted in a <div>
237 - */
238 - function formatCommand( $command, $icon_divs = true ) {
239 - $label = $command['label'];
240 - $href = $command['href'];
241 - $enabled = $command['enabled'];
242 - $tooltip = isset( $command['tooltip'] ) ? $command['tooltip'] : '';
243 -
244 - if ( isset( $command['icon'] ) ) {
245 - $icon = Xml::tags( 'div', array( 'title' => $label,
246 - 'class' => 'lqt-command-icon' ), '&#160;' );
247 - if ( $icon_divs ) {
248 - if ( !empty( $command['showlabel'] ) ) {
249 - $label = $icon . '&#160;' . $label;
250 - } else {
251 - $label = $icon;
252 - }
253 - } else {
254 - if ( empty( $command['showlabel'] ) ) {
255 - $label = '';
256 - }
257 - }
258 - }
259 -
260 - if ( $enabled ) {
261 - $thisCommand = Xml::tags( 'a', array( 'href' => $href, 'title' => $tooltip ),
262 - $label );
263 - } else {
264 - $thisCommand = Xml::tags( 'span', array( 'class' => 'lqt_command_disabled',
265 - 'title' => $tooltip ), $label );
266 - }
267 -
268 - return $thisCommand;
269 - }
270 -
271 - /**
272 - * Gets the commands to show in the dropdown of a post.
273 - * @param $post The LiquidThreadsPost to show a dropdown for.
274 - * @param $version The LiquidThreadsPostVersion to show the dropdown for.
275 - * @param $context A LiquidThreadsPostFormatterContext object.
276 - * @return An associative array of arguments suitable for
277 - * LiquidThreadsPostFormatter::formatCommand
278 - * @see LiquidThreadsPostFormatter::formatCommand
279 - */
280 - function getMinorCommands( $post, $version, $context ) {
281 - $commands = array();
282 -
283 - // TODO make this link operate properly
284 - $history_url = SpecialPage::getTitleFor( 'PostHistory', $post->getID() );
285 - $commands['history'] = array(
286 - 'label' => wfMsgExt( 'history_short', 'parseinline' ),
287 - 'href' => $history_url,
288 - 'enabled' => true,
289 - );
 174+ protected function getToolbar( $post, $context ) {
 175+ $toolbar = LiquidThreadsPostToolbar::singleton();
290176
291 - // TODO permissions checking
292 - $edit_url = SpecialPage::getTitleFor( 'EditPost', $post->getID() );
293 - $commands['edit'] = array(
294 - 'label' => wfMsgExt( 'edit', 'parseinline' ),
295 - 'href' => $edit_url,
296 - 'enabled' => true
297 - );
298 -
299 - if ( $context->get('user')->isAllowed( 'lqt-split' ) ) {
300 - $splitUrl = SpecialPage::getTitleFor( 'SplitThread', $post->getID() )->getFullURL();
301 - $commands['split'] = array(
302 - 'label' => wfMsgExt( 'lqt-thread-split', 'parseinline' ),
303 - 'href' => $splitUrl,
304 - 'enabled' => true
305 - );
306 - }
307 -
308 - // TODO implement merging
309 -// if ( $context->get('user')->isAllowed( 'lqt-merge' ) ) {
310 -// $mergeParams = $_GET;
311 -// $mergeParams['lqt_merge_from'] = $thread->id();
312 -//
313 -// unset( $mergeParams['title'] );
314 -//
315 -// $mergeUrl = $this->title->getLocalURL( wfArrayToCGI( $mergeParams ) );
316 -// $label = wfMsgExt( 'lqt-thread-merge', 'parseinline' );
317 -//
318 -// $commands['merge'] = array(
319 -// 'label' => $label,
320 -// 'href' => $mergeUrl,
321 -// 'enabled' => true
322 -// );
323 -// }
324 -
325 - $commands['link'] = array(
326 - 'label' => wfMsgExt( 'lqt_permalink', 'parseinline' ),
327 - 'href' => SpecialPage::getTitleFor( 'Post', $post->getID() ),
328 - 'enabled' => true,
329 - 'showlabel' => true,
330 - 'tooltip' => wfMsgExt( 'lqt_permalink', 'parseinline' )
331 - );
332 -
333 - wfRunHooks( 'LiquidThreadsPostMinorCommands',
334 - array( $post, $version, $context, &$commands ) );
335 -
336 - return $commands;
 177+ return $toolbar->getHTML( $post, $context );
337178 }
338 -
339 - /**
340 - * Gets the main commands in the main (non-dropdown) part of the toolbar.
341 - * @param $post The LiquidThreadsPost to show a toolbar for.
342 - * @param $version The LiquidThreadsPostVersion to show the toolbar for.
343 - * @param $context A LiquidThreadsPostFormatterContext object.
344 - * @return An associative array of arguments suitable for
345 - * LiquidThreadsPostFormatter::formatCommand
346 - * @see LiquidThreadsPostFormatter::formatCommand
347 - */
348 - function getMajorCommands( $post, $version, $context ) {
349 - $commands = array();
350 -
351 -// if ( $this->user->isAllowed( 'lqt-merge' ) &&
352 -// $this->request->getCheck( 'lqt_merge_from' ) ) {
353 -// $srcThread = Threads::withId( $this->request->getVal( 'lqt_merge_from' ) );
354 -// $par = $srcThread->title()->getPrefixedText();
355 -// $mergeTitle = SpecialPage::getTitleFor( 'MergeThread', $par );
356 -// $mergeUrl = $mergeTitle->getLocalURL( 'dest=' . $thread->id() );
357 -// $label = wfMsgExt( 'lqt-thread-merge-to', 'parseinline' );
358 -//
359 -// $commands['merge-to'] = array(
360 -// 'label' => $label, 'href' => $mergeUrl,
361 -// 'enabled' => true,
362 -// 'tooltip' => $label
363 -// );
364 -// }
365 -
366 - // TODO permissions checking, proper URL
367 - $commands['reply'] = array(
368 - 'label' => wfMsgExt( 'lqt_reply', 'parseinline' ),
369 - 'href' => SpecialPage::getTitleFor('Reply', $post->getID() )->getFullURL(),
370 - 'enabled' => true,
371 - 'showlabel' => 1,
372 - 'tooltip' => wfMsg( 'lqt_reply' ),
373 - 'icon' => 'reply.png',
374 - );
375 -
376 - // Parent post link
377 - if ( $version->getParentID() ) {
378 - $parentID = $version->getParentID();
379 -
380 - $commands['parent'] = array(
381 - 'label' => wfMsgExt( 'lqt-parent', 'parseinline' ),
382 - 'href' => '#' . $this->getAnchor($parentID),
383 - 'enabled' => true,
384 - 'showlabel' => 1,
385 - );
386 - }
387 -
388 - wfRunHooks( 'LiquidThreadsPostMajorCommands',
389 - array( $post, $version, $context, &$commands ) );
390 -
391 - return $commands;
392 - }
393179
394180 function getPostSignature( $post, $version, $context ) {
395181 $lang = $context->get('language');
@@ -451,5 +237,6 @@
452238 'language',
453239 'nesting-level',
454240 'post-callbacks',
 241+ 'version',
455242 );
456243 }
Index: branches/lqt-updates/extensions/LiquidThreads/classes/view/TopicToolbar.php
@@ -0,0 +1,97 @@
 2+<?php
 3+
 4+class LiquidThreadsTopicToolbar extends LiquidThreadsToolbar {
 5+ /**
 6+ * Get a shared instance of this class.
 7+ */
 8+ public static function singleton() {
 9+ static $singleton = null;
 10+
 11+ if ( !$singleton ) {
 12+ $singleton = new self;
 13+ }
 14+
 15+ return $singleton;
 16+ }
 17+
 18+ /**
 19+ * Returns the correct class for the context object
 20+ */
 21+ public function getContextClass() {
 22+ return 'LiquidThreadsTopicFormatterContext';
 23+ }
 24+
 25+ /**
 26+ * Returns the class that can be formatted by this object.
 27+ */
 28+ public function getObjectClass() {
 29+ return 'LiquidThreadsTopic';
 30+ }
 31+
 32+ /**
 33+ * Returns the commands to be shown in this toolbar.
 34+ * @param $object The object that the toolbar is for.
 35+ * @param $context A context object, usually for a related formatter.
 36+ * @return An array suitable for LiquidThreadsToolbar::formatCommands
 37+ */
 38+ function getCommands( $topic, $context = null ) {
 39+ $commands = array();
 40+
 41+ $commands['history'] = array(
 42+ 'label' => wfMsg( 'history_short' ),
 43+ 'href' => SpecialPage::getTitleFor('TopicHistory', $topic->getID())->getFullURL(),
 44+ 'enabled' => true
 45+ );
 46+
 47+ if ( $context->get('user')->isAllowed( 'move' ) ) {
 48+ $move_href = SpecialPage::getTitleFor( 'MoveTopic', $topic->getID() )->getFullURL();
 49+ $commands['move'] = array(
 50+ 'label' => wfMsg( 'lqt-movethread' ),
 51+ 'href' => $move_href,
 52+ 'enabled' => true
 53+ );
 54+ }
 55+
 56+// if ( $this->user->isAllowed( 'protect' ) ) {
 57+// $protect_href = $thread->title()->getLocalURL( 'action=protect' );
 58+//
 59+// // Check if it's already protected
 60+// if ( !$thread->title()->isProtected() ) {
 61+// $label = wfMsg( 'protect' );
 62+// } else {
 63+// $label = wfMsg( 'unprotect' );
 64+// }
 65+//
 66+// $commands['protect'] = array(
 67+// 'label' => $label,
 68+// 'href' => $protect_href,
 69+// 'enabled' => true
 70+// );
 71+// }
 72+
 73+// if ( !$this->user->isAnon() && !$thread->title()->userIsWatching() ) {
 74+// $commands['watch'] = array(
 75+// 'label' => wfMsg( 'watch' ),
 76+// 'href' => self::permalinkUrlWithQuery( $thread, 'action=watch' ),
 77+// 'enabled' => true
 78+// );
 79+// } else if ( !$this->user->isAnon() ) {
 80+// $commands['unwatch'] = array(
 81+// 'label' => wfMsg( 'unwatch' ),
 82+// 'href' => self::permalinkUrlWithQuery( $thread, 'action=unwatch' ),
 83+// 'enabled' => true
 84+// );
 85+// }
 86+
 87+ $summarizeUrl = SpecialPage::getTitleFor('SummarizeTopic', $topic->getID())->getFullURL();
 88+ $commands['summarize'] = array(
 89+ 'label' => wfMsgExt( 'lqt_summarize_link', 'parseinline' ),
 90+ 'href' => $summarizeUrl,
 91+ 'enabled' => true,
 92+ );
 93+
 94+ wfRunHooks( 'LiquidThreadsTopicCommands', array( $topic, $context, &$commands ) );
 95+
 96+ return $commands;
 97+ }
 98+}
Index: branches/lqt-updates/extensions/LiquidThreads/classes/view/Toolbar.php
@@ -0,0 +1,104 @@
 2+<?php
 3+
 4+abstract class LiquidThreadsToolbar extends LiquidThreadsFormatter {
 5+ /**
 6+ * Gets the HTML for this toolbar.
 7+ * @param $object The object that the toolbar is for.
 8+ * @param $context A context object, usually for a related formatter.
 9+ * @return HTML result
 10+ */
 11+ public function getHTML( $object, $context = null ) {
 12+ $commands = $this->getCommands( $object, $context );
 13+
 14+ $formattedCommands = $this->formatCommands( $commands );
 15+
 16+ $list = Xml::tags( 'ul', array( 'class' => $this->getCSSClass() ),
 17+ $formattedCommands );
 18+
 19+ return $list;
 20+ }
 21+
 22+ /**
 23+ * Gets the class to be applied to the toolbar.
 24+ */
 25+ protected function getCSSClass() {
 26+ return 'lqt-toolbar';
 27+ }
 28+
 29+ /**
 30+ * Returns the commands to be shown in this toolbar.
 31+ * @param $object The object that the toolbar is for.
 32+ * @param $context A context object, usually for a related formatter.
 33+ * @return An array suitable for LiquidThreadsToolbar::formatCommands
 34+ */
 35+ abstract protected function getCommands( $object, $context = null );
 36+
 37+ /**
 38+ * Formats a list of toolbar commands.
 39+ * @param $commands Associative array of commands.
 40+ * @return HTML
 41+ * @see LiquidThreadsPostFormatter::formatCommand
 42+ */
 43+ public function formatCommands( $commands ) {
 44+ $result = array();
 45+ foreach ( $commands as $key => $command ) {
 46+ $thisCommand = $this->formatCommand( $command );
 47+
 48+ $thisCommand = Xml::tags(
 49+ 'li',
 50+ array( 'class' => 'lqt-command lqt-command-' . $key ),
 51+ $thisCommand
 52+ );
 53+
 54+ $result[] = $thisCommand;
 55+ }
 56+ return join( ' ', $result );
 57+ }
 58+
 59+ /**
 60+ * Formats a toolbar command
 61+ * @param $command Associative array describing this command
 62+ * Valid keys:
 63+ * label: The text to show for this command.
 64+ * href: The URL to link to.
 65+ * enabled: Whether or not this command is enabled.
 66+ * tooltip: If specified, the tooltip to show for this command.
 67+ * icon: If specified, an icon is shown.
 68+ * showlabel: Whether or not to show the label. Default: on.
 69+ * @param $icon_divs Boolean: If false, do not insert <divs> to style with an icon.
 70+ * @return HTML: Command formatted in a <div>
 71+ */
 72+ public function formatCommand( $command, $icon_divs = true ) {
 73+ $label = $command['label'];
 74+ $href = $command['href'];
 75+ $enabled = $command['enabled'];
 76+ $tooltip = isset( $command['tooltip'] ) ? $command['tooltip'] : '';
 77+
 78+ if ( isset( $command['icon'] ) ) {
 79+ $icon = Xml::tags( 'div', array( 'title' => $label,
 80+ 'class' => 'lqt-command-icon' ), '&#160;' );
 81+ if ( $icon_divs ) {
 82+ if ( !empty( $command['showlabel'] ) ) {
 83+ $label = $icon . '&#160;' . $label;
 84+ } else {
 85+ $label = $icon;
 86+ }
 87+ } else {
 88+ if ( empty( $command['showlabel'] ) ) {
 89+ $label = '';
 90+ }
 91+ }
 92+ }
 93+
 94+ if ( $enabled ) {
 95+ $thisCommand = Xml::tags( 'a', array( 'href' => $href, 'title' => $tooltip ),
 96+ $label );
 97+ } else {
 98+ $thisCommand = Xml::tags( 'span', array( 'class' => 'lqt_command_disabled',
 99+ 'title' => $tooltip ), $label );
 100+ }
 101+
 102+ return $thisCommand;
 103+ }
 104+
 105+}
Index: branches/lqt-updates/extensions/LiquidThreads/classes/view/TopicFormatter.php
@@ -0,0 +1,167 @@
 2+<?php
 3+
 4+class LiquidThreadsTopicFormatter extends LiquidThreadsFormatter {
 5+
 6+ /**
 7+ * Get a shared instance of this class.
 8+ */
 9+ public static function singleton() {
 10+ static $singleton = null;
 11+
 12+ if ( !$singleton ) {
 13+ $singleton = new self;
 14+ }
 15+
 16+ return $singleton;
 17+ }
 18+
 19+ /**
 20+ * Returns the correct class for the context object
 21+ */
 22+ public function getContextClass() {
 23+ return 'LiquidThreadsTopicFormatterContext';
 24+ }
 25+
 26+ /**
 27+ * Returns the class that can be formatted by this object.
 28+ */
 29+ public function getObjectClass() {
 30+ return 'LiquidThreadsTopic';
 31+ }
 32+
 33+ /**
 34+ * Convert a LiquidThreadsPost to HTML.
 35+ * @param $object The LiquidThreadsPost to convert.
 36+ * @param $context LiquidThreadsPostFormatterContext object.
 37+ * @return HTML result
 38+ */
 39+ public function getHTML( $object, $context = null ) {
 40+ // Error checking
 41+ $this->checkArguments( $object, $context );
 42+
 43+ if ( ! $context->get('language') ) {
 44+ global $wgLang;
 45+ $context->set( 'language', $wgLang );
 46+ }
 47+
 48+ if ( ! $context->get('user') ) {
 49+ global $wgUser;
 50+ $context->set('user', $wgUser );
 51+ }
 52+
 53+ $html = Xml::openElement( 'div',
 54+ array( 'class' => 'lqt-topic',
 55+ 'id' => 'lqt-topic-id-'.$object->getID() ) );
 56+
 57+ // Show topic heading
 58+ $html .= $this->getHeading( $object, $context );
 59+
 60+ // Now show the comments
 61+
 62+ // TODO Show only comments as they appeared at $timestamp
 63+ $directResponses = $object->getDirectResponses();
 64+
 65+ $postContext = $context->get('post-context');
 66+
 67+ if ( is_null($postContext) ) {
 68+ $postContext = new LiquidThreadsPostFormatterContext();
 69+
 70+ $postContext->set( 'timestamp', $context->get('timestamp') );
 71+ $postContext->set( 'user', $context->get('user') );
 72+ $postContext->set( 'language', $context->get('language') );
 73+ }
 74+
 75+ // Set up formatter
 76+ $postFormatter = LiquidThreadsPostFormatter::singleton();
 77+
 78+ foreach( $directResponses as $reply ) {
 79+ $html .= $postFormatter->getHTML( $reply, $postContext );
 80+ }
 81+
 82+ $html .= Xml::closeElement( 'div' );
 83+
 84+ return $html;
 85+ }
 86+
 87+ /**
 88+ * Gets the heading and its included topic-level toolbar.
 89+ * @param $object The LiquidThreadsTopic for which to get a heading.
 90+ * @param $context The context object.
 91+ * @return HTML result.
 92+ */
 93+ protected function getHeading( $object, $context ) {
 94+ $version = $context->get('version');
 95+
 96+ if ( !($version instanceof LiquidThreadsTopicVersion) ||
 97+ $version->getTopicID() != $object->getID() )
 98+ {
 99+ $version = LiquidThreadsTopicVersion::newPointInTime( $object,
 100+ $context->get('timestamp') );
 101+ }
 102+
 103+ $toolbar = LiquidThreadsTopicToolbar::singleton();
 104+ $toolbarHTML = $toolbar->getHTML( $object, $context );
 105+
 106+ $subject = $version->getSubject();
 107+
 108+ $formattedSubject = $this->formatSubject( $subject );
 109+
 110+ $formattedSubject = Xml::tags( 'span', array( 'class' => 'mw-headline' ),
 111+ $formattedSubject );
 112+
 113+ $formattedSubject = Xml::tags( 'h2',
 114+ array(
 115+ 'class' => 'lqt-header',
 116+ 'id' => 'lqt-header-id-'.$object->getID(),
 117+ ), $formattedSubject );
 118+
 119+ $html = $formattedSubject . "\n" . $toolbarHTML;
 120+
 121+ $html = Xml::tags( 'div', array( 'class' => 'lqt-heading' ), $html );
 122+
 123+ return $html;
 124+ }
 125+
 126+ /**
 127+ * Formats a topic subject.
 128+ * @param $subject String: The subject source to format.
 129+ * @return The subject, lightly formatted, as HTML.
 130+ */
 131+ protected function formatSubject( $subject ) {
 132+ wfProfileIn( __METHOD__ );
 133+ global $wgUser;
 134+ $sk = $wgUser->getSkin();
 135+
 136+ # Sanitize text a bit:
 137+ $subject = str_replace( "\n", " ", $subject );
 138+ # Allow HTML entities
 139+ $subject = Sanitizer::escapeHtmlAllowEntities( $subject );
 140+
 141+ # Render links:
 142+ $subject = $sk->formatLinksInComment( $subject, null, false );
 143+
 144+ wfProfileOut( __METHOD__ );
 145+ return $subject;
 146+ }
 147+
 148+}
 149+
 150+/**
 151+ * This class provides context for formatting a LiquidThreadsTopic object.
 152+ * Valid fields are:
 153+ * timestamp: The point in time at which to show this LiquidThreadsTopic.
 154+ * user: The User object for which to show this LiquidThreadsTopic.
 155+ * language: Override the Language object that the topic is shown in.
 156+ * post-callbacks: If set, an associative array of callbacks used to replace display of
 157+ * individual posts. Key is the post ID, value is a callback. Used for
 158+ * edit forms and the like.
 159+ */
 160+class LiquidThreadsTopicFormatterContext extends LiquidThreadsFormatterContext {
 161+ protected $validFields = array(
 162+ 'timestamp',
 163+ 'user',
 164+ 'language',
 165+ 'post-context',
 166+ 'version',
 167+ );
 168+}
Index: branches/lqt-updates/extensions/LiquidThreads/classes/view/PostToolbar.php
@@ -0,0 +1,219 @@
 2+<?php
 3+
 4+class LiquidThreadsPostToolbar extends LiquidThreadsToolbar {
 5+
 6+ /**
 7+ * Returns the correct class for the context object
 8+ */
 9+ public function getContextClass() {
 10+ return 'LiquidThreadsPostFormatterContext';
 11+ }
 12+
 13+ /**
 14+ * Returns the class that can be formatted by this object.
 15+ */
 16+ public function getObjectClass() {
 17+ return 'LiquidThreadsPost';
 18+ }
 19+
 20+ /**
 21+ * Get a shared instance of this class.
 22+ */
 23+ public static function singleton() {
 24+ static $singleton = null;
 25+
 26+ if ( !$singleton ) {
 27+ $singleton = new self;
 28+ }
 29+
 30+ return $singleton;
 31+ }
 32+
 33+ /**
 34+ * Generates a toolbar for a post.
 35+ * @param $post The LiquidThreadsPost being shown.
 36+ * @param $version The LiquidThreadsPostVersion to show the dropdown for.
 37+ * @param $context A LiquidThreadsPostFormatterContext object.
 38+ * @return HTML
 39+ */
 40+ public function getHTML( $post, $context = null ) {
 41+ $this->checkArguments( $post, $context );
 42+
 43+ $html = '';
 44+
 45+ $version = $context->get('version');
 46+ // Retrieve the appropriate version if necessary
 47+ if ( is_null($version) || $version->getPostID() != $post->getID() ) {
 48+ $timestamp = $context->get('timestamp');
 49+ $version = LiquidThreadsPostVersion::newPointInTime( $post, $timestamp );
 50+ $context->set('version', $version);
 51+ }
 52+
 53+ $headerParts = array();
 54+
 55+ foreach ( $this->getCommands( $post, $context ) as $key => $cmd ) {
 56+ $content = $this->formatCommand( $cmd, false /* No icon divs */ );
 57+ $headerParts[] = Xml::tags( 'li',
 58+ array( 'class' => "lqt-command lqt-command-$key" ),
 59+ $content );
 60+ }
 61+
 62+ // Drop-down menu
 63+ $commands = $this->getMinorCommands( $post, $context );
 64+ $menuHTML = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-command-list' ),
 65+ $this->formatCommands( $commands ) );
 66+
 67+ $triggerText = Xml::tags( 'a', array( 'class' => 'lqt-thread-actions-icon',
 68+ 'href' => '#' ),
 69+ wfMsgHTML( 'lqt-menu-trigger' ) );
 70+ $dropDownTrigger = Xml::tags( 'div',
 71+ array( 'class' => 'lqt-thread-actions-trigger ' .
 72+ 'lqt-command-icon', 'style' => 'display: none;' ),
 73+ $triggerText );
 74+
 75+ if ( count( $commands ) ) {
 76+ $headerParts[] = Xml::tags( 'li',
 77+ array( 'class' => 'lqt-thread-toolbar-menu' ),
 78+ $dropDownTrigger );
 79+ }
 80+
 81+ $html .= implode( ' ', $headerParts );
 82+
 83+ $html = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-commands' ), $html );
 84+
 85+ $html = Xml::tags( 'div', array( 'class' => 'lqt-thread-toolbar' ), $html ) .
 86+ $menuHTML;
 87+
 88+ return $html;
 89+ }
 90+
 91+ /**
 92+ * Gets the main commands in the main (non-dropdown) part of the toolbar.
 93+ * @param $post The LiquidThreadsPost to show a toolbar for.
 94+ * @param $version The LiquidThreadsPostVersion to show the toolbar for.
 95+ * @param $context A LiquidThreadsPostFormatterContext object.
 96+ * @return An associative array of arguments suitable for
 97+ * LiquidThreadsToolbar::formatCommand
 98+ * @see LiquidThreadsToolbar::formatCommand
 99+ */
 100+ protected function getCommands( $post, $context = null ) {
 101+ $commands = array();
 102+
 103+ // Will have been set in getToolbar()
 104+ $version = $context->get('version');
 105+
 106+// if ( $this->user->isAllowed( 'lqt-merge' ) &&
 107+// $this->request->getCheck( 'lqt_merge_from' ) ) {
 108+// $srcThread = Threads::withId( $this->request->getVal( 'lqt_merge_from' ) );
 109+// $par = $srcThread->title()->getPrefixedText();
 110+// $mergeTitle = SpecialPage::getTitleFor( 'MergeThread', $par );
 111+// $mergeUrl = $mergeTitle->getLocalURL( 'dest=' . $thread->id() );
 112+// $label = wfMsgExt( 'lqt-thread-merge-to', 'parseinline' );
 113+//
 114+// $commands['merge-to'] = array(
 115+// 'label' => $label, 'href' => $mergeUrl,
 116+// 'enabled' => true,
 117+// 'tooltip' => $label
 118+// );
 119+// }
 120+
 121+ // TODO permissions checking, proper URL
 122+ $commands['reply'] = array(
 123+ 'label' => wfMsgExt( 'lqt_reply', 'parseinline' ),
 124+ 'href' => SpecialPage::getTitleFor('Reply', $post->getID() )->getFullURL(),
 125+ 'enabled' => true,
 126+ 'showlabel' => 1,
 127+ 'tooltip' => wfMsg( 'lqt_reply' ),
 128+ 'icon' => 'reply.png',
 129+ );
 130+
 131+ // Parent post link
 132+ if ( $version->getParentID() ) {
 133+ $parentID = $version->getParentID();
 134+
 135+ $commands['parent'] = array(
 136+ 'label' => wfMsgExt( 'lqt-parent', 'parseinline' ),
 137+ 'href' => '#' . $this->getAnchor($parentID),
 138+ 'enabled' => true,
 139+ 'showlabel' => 1,
 140+ );
 141+ }
 142+
 143+ wfRunHooks( 'LiquidThreadsPostMajorCommands',
 144+ array( $post, $version, $context, &$commands ) );
 145+
 146+ return $commands;
 147+ }
 148+
 149+
 150+ /**
 151+ * Gets the commands to show in the dropdown of a post.
 152+ * @param $post The LiquidThreadsPost to show a dropdown for.
 153+ * @param $version The LiquidThreadsPostVersion to show the dropdown for.
 154+ * @param $context A LiquidThreadsPostFormatterContext object.
 155+ * @return An associative array of arguments suitable for
 156+ * LiquidThreadsToolbar::formatCommand
 157+ * @see LiquidThreadsToolbar::formatCommand
 158+ */
 159+ protected function getMinorCommands( $post, $context ) {
 160+ $commands = array();
 161+
 162+ // Will have been set in getToolbar()
 163+ $version = $context->get('version');
 164+
 165+ // TODO make this link operate properly
 166+ $history_url = SpecialPage::getTitleFor( 'PostHistory', $post->getID() );
 167+ $commands['history'] = array(
 168+ 'label' => wfMsgExt( 'history_short', 'parseinline' ),
 169+ 'href' => $history_url,
 170+ 'enabled' => true,
 171+ );
 172+
 173+ // TODO permissions checking
 174+ $edit_url = SpecialPage::getTitleFor( 'EditPost', $post->getID() );
 175+ $commands['edit'] = array(
 176+ 'label' => wfMsgExt( 'edit', 'parseinline' ),
 177+ 'href' => $edit_url,
 178+ 'enabled' => true
 179+ );
 180+
 181+ if ( $context->get('user')->isAllowed( 'lqt-split' ) ) {
 182+ $splitUrl = SpecialPage::getTitleFor( 'SplitThread', $post->getID() )->getFullURL();
 183+ $commands['split'] = array(
 184+ 'label' => wfMsgExt( 'lqt-thread-split', 'parseinline' ),
 185+ 'href' => $splitUrl,
 186+ 'enabled' => true
 187+ );
 188+ }
 189+
 190+ // TODO implement merging
 191+// if ( $context->get('user')->isAllowed( 'lqt-merge' ) ) {
 192+// $mergeParams = $_GET;
 193+// $mergeParams['lqt_merge_from'] = $thread->id();
 194+//
 195+// unset( $mergeParams['title'] );
 196+//
 197+// $mergeUrl = $this->title->getLocalURL( wfArrayToCGI( $mergeParams ) );
 198+// $label = wfMsgExt( 'lqt-thread-merge', 'parseinline' );
 199+//
 200+// $commands['merge'] = array(
 201+// 'label' => $label,
 202+// 'href' => $mergeUrl,
 203+// 'enabled' => true
 204+// );
 205+// }
 206+
 207+ $commands['link'] = array(
 208+ 'label' => wfMsgExt( 'lqt_permalink', 'parseinline' ),
 209+ 'href' => SpecialPage::getTitleFor( 'Post', $post->getID() ),
 210+ 'enabled' => true,
 211+ 'showlabel' => true,
 212+ 'tooltip' => wfMsgExt( 'lqt_permalink', 'parseinline' )
 213+ );
 214+
 215+ wfRunHooks( 'LiquidThreadsPostMinorCommands',
 216+ array( $post, $version, $context, &$commands ) );
 217+
 218+ return $commands;
 219+ }
 220+}

Status & tagging log