Index: branches/lqt-updates/extensions/LiquidThreads/classes/View.php |
— | — | @@ -1010,601 +1010,10 @@ |
1011 | 1011 | return Title::makeTitle( NS_LQT_THREAD, wfGenerateToken() ); |
1012 | 1012 | } |
1013 | 1013 | |
1014 | | - /** |
1015 | | - * Example return value: |
1016 | | - * array ( |
1017 | | - * edit => array( 'label' => 'Edit', |
1018 | | - * 'href' => 'http...', |
1019 | | - * 'enabled' => false ), |
1020 | | - * reply => array( 'label' => 'Reply', |
1021 | | - * 'href' => 'http...', |
1022 | | - * 'enabled' => true ) |
1023 | | - * ) |
1024 | | - */ |
1025 | | - function threadCommands( $thread ) { |
1026 | | - $commands = array(); |
1027 | | - |
1028 | | - $history_url = self::permalinkUrlWithQuery( $thread, array( 'action' => 'history' ) ); |
1029 | | - $commands['history'] = array( 'label' => wfMsgExt( |
1030 | | - 'history_short', 'parseinline' ), |
1031 | | - 'href' => $history_url, |
1032 | | - 'enabled' => true |
1033 | | - ); |
1034 | | - |
1035 | | - if ( $thread->isHistorical() ) { |
1036 | | - return array(); |
1037 | | - } |
1038 | | - $user_can_edit = $thread->root()->getTitle()->quickUserCan( 'edit' ); |
1039 | | - $editMsg = $user_can_edit ? 'edit' : 'viewsource'; |
1040 | | - |
1041 | | - $commands['edit'] = array( |
1042 | | - 'label' => wfMsgExt( $editMsg, 'parseinline' ), |
1043 | | - 'href' => $this->talkpageUrl( |
1044 | | - $this->title, |
1045 | | - 'edit', $thread, |
1046 | | - true, /* include fragment */ |
1047 | | - $this->request |
1048 | | - ), |
1049 | | - 'enabled' => true |
1050 | | - ); |
1051 | | - |
1052 | | - if ( $this->user->isAllowed( 'delete' ) ) { |
1053 | | - $delete_url = $thread->title()->getLocalURL( 'action=delete' ); |
1054 | | - $deleteMsg = $thread->type() == Threads::TYPE_DELETED ? 'lqt_undelete' : 'delete'; |
1055 | | - |
1056 | | - $commands['delete'] = array( |
1057 | | - 'label' => wfMsgExt( $deleteMsg, 'parseinline' ), |
1058 | | - 'href' => $delete_url, |
1059 | | - 'enabled' => true |
1060 | | - ); |
1061 | | - } |
1062 | | - |
1063 | | - if ( !$thread->isTopmostThread() && $this->user->isAllowed( 'lqt-split' ) ) { |
1064 | | - $splitUrl = SpecialPage::getTitleFor( 'SplitThread', |
1065 | | - $thread->title()->getPrefixedText() )->getLocalURL(); |
1066 | | - $commands['split'] = array( |
1067 | | - 'label' => wfMsgExt( 'lqt-thread-split', 'parseinline' ), |
1068 | | - 'href' => $splitUrl, |
1069 | | - 'enabled' => true |
1070 | | - ); |
1071 | | - } |
1072 | | - |
1073 | | - if ( $this->user->isAllowed( 'lqt-merge' ) ) { |
1074 | | - $mergeParams = $_GET; |
1075 | | - $mergeParams['lqt_merge_from'] = $thread->id(); |
1076 | | - |
1077 | | - unset( $mergeParams['title'] ); |
1078 | | - |
1079 | | - $mergeUrl = $this->title->getLocalURL( wfArrayToCGI( $mergeParams ) ); |
1080 | | - $label = wfMsgExt( 'lqt-thread-merge', 'parseinline' ); |
1081 | | - |
1082 | | - $commands['merge'] = array( |
1083 | | - 'label' => $label, |
1084 | | - 'href' => $mergeUrl, |
1085 | | - 'enabled' => true |
1086 | | - ); |
1087 | | - } |
1088 | | - |
1089 | | - $commands['link'] = array( |
1090 | | - 'label' => wfMsgExt( 'lqt_permalink', 'parseinline' ), |
1091 | | - 'href' => $thread->title()->getLocalURL(), |
1092 | | - 'enabled' => true, |
1093 | | - 'showlabel' => true, |
1094 | | - 'tooltip' => wfMsgExt( 'lqt_permalink', 'parseinline' ) |
1095 | | - ); |
1096 | | - |
1097 | | - wfRunHooks( 'LiquidThreadsThreadCommands', array( $thread, &$commands ) ); |
1098 | | - |
1099 | | - return $commands; |
1100 | | - } |
1101 | | - |
1102 | | - // Commands for the bottom. |
1103 | | - function threadMajorCommands( $thread ) { |
1104 | | - if ( $thread->isHistorical() ) { |
1105 | | - // No links for historical threads. |
1106 | | - $history_url = self::permalinkUrlWithQuery( $thread, |
1107 | | - array( 'action' => 'history' ) ); |
1108 | | - $commands = array(); |
1109 | | - |
1110 | | - $commands['history'] = array( |
1111 | | - 'label' => wfMsgExt( 'history_short', 'parseinline' ), |
1112 | | - 'href' => $history_url, |
1113 | | - 'enabled' => true ); |
1114 | | - |
1115 | | - return $commands; |
1116 | | - } |
1117 | | - |
1118 | | - $commands = array(); |
1119 | | - |
1120 | | - if ( $this->user->isAllowed( 'lqt-merge' ) && |
1121 | | - $this->request->getCheck( 'lqt_merge_from' ) ) { |
1122 | | - $srcThread = Threads::withId( $this->request->getVal( 'lqt_merge_from' ) ); |
1123 | | - $par = $srcThread->title()->getPrefixedText(); |
1124 | | - $mergeTitle = SpecialPage::getTitleFor( 'MergeThread', $par ); |
1125 | | - $mergeUrl = $mergeTitle->getLocalURL( 'dest=' . $thread->id() ); |
1126 | | - $label = wfMsgExt( 'lqt-thread-merge-to', 'parseinline' ); |
1127 | | - |
1128 | | - $commands['merge-to'] = array( |
1129 | | - 'label' => $label, 'href' => $mergeUrl, |
1130 | | - 'enabled' => true, |
1131 | | - 'tooltip' => $label |
1132 | | - ); |
1133 | | - } |
1134 | | - |
1135 | | - if ( $thread->canUserReply( $this->user ) === true ) { |
1136 | | - $commands['reply'] = array( |
1137 | | - 'label' => wfMsgExt( 'lqt_reply', 'parseinline' ), |
1138 | | - 'href' => $this->talkpageUrl( $this->title, 'reply', $thread, |
1139 | | - true /* include fragment */, $this->request ), |
1140 | | - 'enabled' => true, |
1141 | | - 'showlabel' => 1, |
1142 | | - 'tooltip' => wfMsg( 'lqt_reply' ), |
1143 | | - 'icon' => 'reply.png', |
1144 | | - ); |
1145 | | - } |
1146 | | - |
1147 | | - // Parent post link |
1148 | | - if ( !$thread->isTopmostThread() ) { |
1149 | | - $parent = $thread->superthread(); |
1150 | | - $anchor = $parent->getAnchorName(); |
1151 | | - |
1152 | | - $commands['parent'] = array( |
1153 | | - 'label' => wfMsgExt( 'lqt-parent', 'parseinline' ), |
1154 | | - 'href' => '#' . $anchor, |
1155 | | - 'enabled' => true, |
1156 | | - 'showlabel' => 1, |
1157 | | - ); |
1158 | | - } |
1159 | | - |
1160 | | - wfRunHooks( 'LiquidThreadsThreadMajorCommands', |
1161 | | - array( $thread, &$commands ) ); |
1162 | | - |
1163 | | - return $commands; |
1164 | | - } |
1165 | | - |
1166 | | - function topLevelThreadCommands( $thread ) { |
1167 | | - $commands = array(); |
1168 | | - |
1169 | | - $commands['history'] = array( |
1170 | | - 'label' => wfMsg( 'history_short' ), |
1171 | | - 'href' => self::permalinkUrl( $thread, 'thread_history' ), |
1172 | | - 'enabled' => true |
1173 | | - ); |
1174 | | - |
1175 | | - if ( $this->user->isAllowed( 'move' ) ) { |
1176 | | - $move_href = SpecialPage::getTitleFor( 'MoveThread', $thread->title()->getPrefixedText() )->getLocalURL(); |
1177 | | - $commands['move'] = array( |
1178 | | - 'label' => wfMsg( 'lqt-movethread' ), |
1179 | | - 'href' => $move_href, |
1180 | | - 'enabled' => true |
1181 | | - ); |
1182 | | - } |
1183 | | - |
1184 | | - if ( $this->user->isAllowed( 'protect' ) ) { |
1185 | | - $protect_href = $thread->title()->getLocalURL( 'action=protect' ); |
1186 | | - |
1187 | | - // Check if it's already protected |
1188 | | - if ( !$thread->title()->isProtected() ) { |
1189 | | - $label = wfMsg( 'protect' ); |
1190 | | - } else { |
1191 | | - $label = wfMsg( 'unprotect' ); |
1192 | | - } |
1193 | | - |
1194 | | - $commands['protect'] = array( |
1195 | | - 'label' => $label, |
1196 | | - 'href' => $protect_href, |
1197 | | - 'enabled' => true |
1198 | | - ); |
1199 | | - } |
1200 | | - |
1201 | | - if ( !$this->user->isAnon() && !$thread->title()->userIsWatching() ) { |
1202 | | - $commands['watch'] = array( |
1203 | | - 'label' => wfMsg( 'watch' ), |
1204 | | - 'href' => self::permalinkUrlWithQuery( $thread, 'action=watch' ), |
1205 | | - 'enabled' => true |
1206 | | - ); |
1207 | | - } else if ( !$this->user->isAnon() ) { |
1208 | | - $commands['unwatch'] = array( |
1209 | | - 'label' => wfMsg( 'unwatch' ), |
1210 | | - 'href' => self::permalinkUrlWithQuery( $thread, 'action=unwatch' ), |
1211 | | - 'enabled' => true |
1212 | | - ); |
1213 | | - } |
1214 | | - |
1215 | | - $summarizeUrl = self::permalinkUrl( $thread, 'summarize', $thread->id() ); |
1216 | | - $commands['summarize'] = array( |
1217 | | - 'label' => wfMsgExt( 'lqt_summarize_link', 'parseinline' ), |
1218 | | - 'href' => $summarizeUrl, |
1219 | | - 'enabled' => true, |
1220 | | - ); |
1221 | | - |
1222 | | - wfRunHooks( 'LiquidThreadsTopLevelCommands', array( $thread, &$commands ) ); |
1223 | | - |
1224 | | - return $commands; |
1225 | | - } |
1226 | | - |
1227 | | - /* @return False if the article and revision do not exist. The HTML of the page to |
1228 | | - * display if it exists. Note that this impacts the state out OutputPage by adding |
1229 | | - * all the other relevant parts of the parser output. If you don't want this, call |
1230 | | - * $post->getParserOutput. */ |
1231 | | - function showPostBody( $post, $oldid = null ) { |
1232 | | - global $wgOut; |
1233 | | - |
1234 | | - $parserOutput = $post->getParserOutput( $oldid ); |
1235 | | - |
1236 | | - // Remove title, so that it stays set correctly. |
1237 | | - $parserOutput->setTitleText( '' ); |
1238 | | - |
1239 | | - |
1240 | | - $wgOut->addParserOutputNoText( $parserOutput ); |
1241 | | - |
1242 | | - return $parserOutput->getText(); |
1243 | | - } |
1244 | | - |
1245 | | - function showThreadToolbar( $thread ) { |
1246 | | - $html = ''; |
1247 | | - |
1248 | | - $headerParts = array(); |
1249 | | - |
1250 | | - foreach ( $this->threadMajorCommands( $thread ) as $key => $cmd ) { |
1251 | | - $content = $this->contentForCommand( $cmd, false /* No icon divs */ ); |
1252 | | - $headerParts[] = Xml::tags( 'li', |
1253 | | - array( 'class' => "lqt-command lqt-command-$key" ), |
1254 | | - $content ); |
1255 | | - } |
1256 | | - |
1257 | | - // Drop-down menu |
1258 | | - $commands = $this->threadCommands( $thread ); |
1259 | | - $menuHTML = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-command-list' ), |
1260 | | - $this->listItemsForCommands( $commands ) ); |
1261 | | - |
1262 | | - $triggerText = Xml::tags( 'a', array( 'class' => 'lqt-thread-actions-icon', |
1263 | | - 'href' => '#' ), |
1264 | | - wfMsgHTML( 'lqt-menu-trigger' ) ); |
1265 | | - $dropDownTrigger = Xml::tags( 'div', |
1266 | | - array( 'class' => 'lqt-thread-actions-trigger ' . |
1267 | | - 'lqt-command-icon', 'style' => 'display: none;' ), |
1268 | | - $triggerText ); |
1269 | | - |
1270 | | - if ( count( $commands ) ) { |
1271 | | - $headerParts[] = Xml::tags( 'li', |
1272 | | - array( 'class' => 'lqt-thread-toolbar-menu' ), |
1273 | | - $dropDownTrigger ); |
1274 | | - } |
1275 | | - |
1276 | | - $html .= implode( ' ', $headerParts ); |
1277 | | - |
1278 | | - $html = Xml::tags( 'ul', array( 'class' => 'lqt-thread-toolbar-commands' ), $html ); |
1279 | | - |
1280 | | - $html = Xml::tags( 'div', array( 'class' => 'lqt-thread-toolbar' ), $html ) . |
1281 | | - $menuHTML; |
1282 | | - |
1283 | | - return $html; |
1284 | | - } |
1285 | | - |
1286 | | - function listItemsForCommands( $commands ) { |
1287 | | - $result = array(); |
1288 | | - foreach ( $commands as $key => $command ) { |
1289 | | - $thisCommand = $this->contentForCommand( $command ); |
1290 | | - |
1291 | | - $thisCommand = Xml::tags( |
1292 | | - 'li', |
1293 | | - array( 'class' => 'lqt-command lqt-command-' . $key ), |
1294 | | - $thisCommand |
1295 | | - ); |
1296 | | - |
1297 | | - $result[] = $thisCommand; |
1298 | | - } |
1299 | | - return join( ' ', $result ); |
1300 | | - } |
1301 | | - |
1302 | | - function contentForCommand( $command, $icon_divs = true ) { |
1303 | | - $label = $command['label']; |
1304 | | - $href = $command['href']; |
1305 | | - $enabled = $command['enabled']; |
1306 | | - $tooltip = isset( $command['tooltip'] ) ? $command['tooltip'] : ''; |
1307 | | - |
1308 | | - if ( isset( $command['icon'] ) ) { |
1309 | | - $icon = Xml::tags( 'div', array( 'title' => $label, |
1310 | | - 'class' => 'lqt-command-icon' ), ' ' ); |
1311 | | - if ( $icon_divs ) { |
1312 | | - if ( !empty( $command['showlabel'] ) ) { |
1313 | | - $label = $icon . ' ' . $label; |
1314 | | - } else { |
1315 | | - $label = $icon; |
1316 | | - } |
1317 | | - } else { |
1318 | | - if ( empty( $command['showlabel'] ) ) { |
1319 | | - $label = ''; |
1320 | | - } |
1321 | | - } |
1322 | | - } |
1323 | | - |
1324 | | - if ( $enabled ) { |
1325 | | - $thisCommand = Xml::tags( 'a', array( 'href' => $href, 'title' => $tooltip ), |
1326 | | - $label ); |
1327 | | - } else { |
1328 | | - $thisCommand = Xml::tags( 'span', array( 'class' => 'lqt_command_disabled', |
1329 | | - 'title' => $tooltip ), $label ); |
1330 | | - } |
1331 | | - |
1332 | | - return $thisCommand; |
1333 | | - } |
1334 | | - |
1335 | | - /** Shows a normal (i.e. not deleted or moved) thread body */ |
1336 | | - function showThreadBody( $thread ) { |
1337 | | - |
1338 | | - // Remove 'editsection', it won't work. |
1339 | | - $popts = $this->output->parserOptions(); |
1340 | | - $previous_editsection = $popts->getEditSection(); |
1341 | | - $popts->setEditSection( false ); |
1342 | | - $this->output->parserOptions( $popts ); |
1343 | | - |
1344 | | - $post = $thread->root(); |
1345 | | - |
1346 | | - $divClass = $this->postDivClass( $thread ); |
1347 | | - $html = ''; |
1348 | | - |
1349 | | - // This is a bit of a hack to have individual histories work. |
1350 | | - // We can grab oldid either from lqt_oldid (which is a thread rev), |
1351 | | - // or from oldid (which is a page rev). But oldid only applies to the |
1352 | | - // thread being requested, not any replies. |
1353 | | - $page_rev = $this->request->getVal( 'oldid', null ); |
1354 | | - if ( $page_rev !== null && $this->title->equals( $thread->root()->getTitle() ) ) { |
1355 | | - $oldid = $page_rev; |
1356 | | - } else { |
1357 | | - $oldid = $thread->isHistorical() ? $thread->rootRevision() : null; |
1358 | | - } |
1359 | | - |
1360 | | - // If we're editing the thread, show the editing form. |
1361 | | - $showAnything = wfRunHooks( 'LiquidThreadsShowThreadBody', |
1362 | | - array( $thread ) ); |
1363 | | - if ( $this->methodAppliesToThread( 'edit', $thread ) && $showAnything ) { |
1364 | | - $html = Xml::openElement( 'div', array( 'class' => $divClass ) ); |
1365 | | - $this->output->addHTML( $html ); |
1366 | | - $html = ''; |
1367 | | - |
1368 | | - // No way am I refactoring EditForm to return its output as HTML. |
1369 | | - // so I'm just flushing the HTML and displaying it as-is. |
1370 | | - $this->showPostEditingForm( $thread ); |
1371 | | - $html .= Xml::closeElement( 'div' ); |
1372 | | - } elseif ( $showAnything ) { |
1373 | | - $html .= Xml::openElement( 'div', array( 'class' => $divClass ) ); |
1374 | | - |
1375 | | - $show = wfRunHooks( 'LiquidThreadsShowPostContent', |
1376 | | - array( $thread, &$post ) ); |
1377 | | - if ( $show ) { |
1378 | | - $html .= $this->showPostBody( $post, $oldid ); |
1379 | | - } |
1380 | | - $html .= Xml::closeElement( 'div' ); |
1381 | | - wfRunHooks( 'LiquidThreadsShowPostThreadBody', |
1382 | | - array( $thread, $this->request, &$html ) ); |
1383 | | - |
1384 | | - |
1385 | | - $html .= $this->showThreadToolbar( $thread ); |
1386 | | - $html .= $this->threadSignature( $thread ); |
1387 | | - } |
1388 | | - |
1389 | | - $this->output->addHTML( $html ); |
1390 | | - |
1391 | | - $popts->setEditSection( $previous_editsection ); |
1392 | | - $this->output->parserOptions( $popts ); |
1393 | | - } |
1394 | | - |
1395 | | - function threadSignature( $thread ) { |
1396 | | - global $wgLang; |
1397 | | - |
1398 | | - $signature = $thread->signature(); |
1399 | | - $signature = LqtView::parseSignature( $signature ); |
1400 | | - |
1401 | | - $signature = Xml::tags( 'span', array( 'class' => 'lqt-thread-user-signature' ), |
1402 | | - $signature ); |
1403 | | - |
1404 | | - $timestamp = $wgLang->timeanddate( $thread->created(), true ); |
1405 | | - $signature .= Xml::element( 'span', |
1406 | | - array( 'class' => 'lqt-thread-toolbar-timestamp' ), |
1407 | | - $timestamp ); |
1408 | | - |
1409 | | - wfRunHooks( 'LiquidThreadsThreadSignature', array( $thread, &$signature ) ); |
1410 | | - |
1411 | | - $signature = Xml::tags( 'div', array( 'class' => 'lqt-thread-signature' ), |
1412 | | - $signature ); |
1413 | | - |
1414 | | - return $signature; |
1415 | | - } |
1416 | | - |
1417 | | - function threadInfoPanel( $thread ) { |
1418 | | - global $wgUser, $wgLang; |
1419 | | - |
1420 | | - $sk = $wgUser->getSkin(); |
1421 | | - |
1422 | | - $infoElements = array(); |
1423 | | - |
1424 | | - // Check for edited flag. |
1425 | | - $editedFlag = $thread->editedness(); |
1426 | | - $ebLookup = array( Threads::EDITED_BY_AUTHOR => 'author', |
1427 | | - Threads::EDITED_BY_OTHERS => 'others' ); |
1428 | | - $lastEdit = $thread->root()->getTimestamp(); |
1429 | | - $lastEditTime = $wgLang->time( $lastEdit, false, true, true ); |
1430 | | - $lastEditDate = $wgLang->date( $lastEdit, false, true, true ); |
1431 | | - $lastEdit = $wgLang->timeanddate( $lastEdit, true ); |
1432 | | - $editors = ''; |
1433 | | - $editorCount = 0; |
1434 | | - |
1435 | | - if ( $editedFlag > Threads::EDITED_BY_AUTHOR ) { |
1436 | | - $editors = $thread->editors(); |
1437 | | - $editorCount = count( $editors ); |
1438 | | - $formattedEditors = array(); |
1439 | | - |
1440 | | - foreach ( $editors as $ed ) { |
1441 | | - $id = IP::isIPAddress( $ed ) ? 0 : 1; |
1442 | | - $fEditor = $sk->userLink( $id, $ed ) . |
1443 | | - $sk->userToolLinks( $id, $ed ); |
1444 | | - $formattedEditors[] = $fEditor; |
1445 | | - } |
1446 | | - |
1447 | | - $editors = $wgLang->commaList( $formattedEditors ); |
1448 | | - } |
1449 | | - |
1450 | | - if ( isset( $ebLookup[$editedFlag] ) ) { |
1451 | | - $editedBy = $ebLookup[$editedFlag]; |
1452 | | - // Used messages: lqt-thread-edited-author, lqt-thread-edited-others |
1453 | | - $editedNotice = wfMsgExt( 'lqt-thread-edited-' . $editedBy, |
1454 | | - array( 'parseinline' ), |
1455 | | - array( $lastEdit, $editorCount, $lastEditTime, |
1456 | | - $lastEditDate ) ); |
1457 | | - $editedNotice = str_replace( '$3', $editors, $editedNotice ); |
1458 | | - $infoElements[] = Xml::tags( 'div', array( 'class' => |
1459 | | - 'lqt-thread-toolbar-edited-' . $editedBy ), |
1460 | | - $editedNotice ); |
1461 | | - } |
1462 | | - |
1463 | | - wfRunHooks( 'LiquidThreadsThreadInfoPanel', array( $thread, &$infoElements ) ); |
1464 | | - |
1465 | | - if ( ! count( $infoElements ) ) { |
1466 | | - return ''; |
1467 | | - } |
1468 | | - |
1469 | | - return Xml::tags( 'div', array( 'class' => 'lqt-thread-info-panel' ), |
1470 | | - implode( "\n", $infoElements ) ); |
1471 | | - } |
1472 | | - |
1473 | | - /** Shows the headING for a thread (as opposed to the headeER for a post within |
1474 | | - a thread). */ |
1475 | | - function showThreadHeading( $thread ) { |
1476 | | - if ( $thread->hasDistinctSubject() ) { |
1477 | | - if ( $thread->hasSuperthread() ) { |
1478 | | - $commands_html = ""; |
1479 | | - } else { |
1480 | | - $commands = $this->topLevelThreadCommands( $thread ); |
1481 | | - $lis = $this->listItemsForCommands( $commands ); |
1482 | | - $id = 'lqt-threadlevel-commands-' . $thread->id(); |
1483 | | - $commands_html = Xml::tags( 'ul', |
1484 | | - array( 'class' => 'lqt_threadlevel_commands', |
1485 | | - 'id' => $id ), |
1486 | | - $lis ); |
1487 | | - } |
1488 | | - |
1489 | | - $id = 'lqt-header-' . $thread->id(); |
1490 | | - |
1491 | | - $html = $thread->formattedSubject(); |
1492 | | - |
1493 | | - $show = wfRunHooks( 'LiquidThreadsShowThreadHeading', |
1494 | | - array( $thread, &$html ) ); |
1495 | | - |
1496 | | - if ( $show ) { |
1497 | | - $html = Xml::tags( 'span', array( 'class' => 'mw-headline' ), $html ); |
1498 | | - $html .= Html::hidden( 'raw-header', $thread->subject() ); |
1499 | | - $html = Xml::tags( 'h' . $this->headerLevel, |
1500 | | - array( 'class' => 'lqt_header', 'id' => $id ), |
1501 | | - $html ) . $commands_html; |
1502 | | - } |
1503 | | - |
1504 | | - // wrap it all in a container |
1505 | | - $html = Xml::tags( 'div', |
1506 | | - array( 'class' => 'lqt_thread_heading' ), |
1507 | | - $html ); |
1508 | | - return $html; |
1509 | | - } |
1510 | | - |
1511 | | - return ''; |
1512 | | - } |
1513 | | - |
1514 | | - function postDivClass( $thread ) { |
1515 | | - $levelClass = 'lqt-thread-nest-' . $this->threadNestingLevel; |
1516 | | - $alternatingType = ( $this->threadNestingLevel % 2 ) ? 'odd' : 'even'; |
1517 | | - $alternatingClass = "lqt-thread-$alternatingType"; |
1518 | | - |
1519 | | - return "lqt_post $levelClass $alternatingClass"; |
1520 | | - } |
1521 | | - |
1522 | 1014 | static function anchorName( $thread ) { |
1523 | 1015 | return $thread->getAnchorName(); |
1524 | 1016 | } |
1525 | 1017 | |
1526 | | - // Display a moved thread |
1527 | | - function showMovedThread( $thread ) { |
1528 | | - global $wgLang; |
1529 | | - |
1530 | | - $sk = $this->user->getSkin(); |
1531 | | - |
1532 | | - // Grab target thread |
1533 | | - if ( !$thread->title() ) { |
1534 | | - return; // Odd case: moved thread with no title? |
1535 | | - } |
1536 | | - |
1537 | | - $article = new Article( $thread->title() ); |
1538 | | - $target = Title::newFromRedirect( $article->getContent() ); |
1539 | | - |
1540 | | - if ( !$target ) { |
1541 | | - throw new MWException( "Thread " . $thread->id() . ' purports to be moved, ' . |
1542 | | - 'but no redirect found in text (' . $article->getContent() . ') of ' . |
1543 | | - $thread->root()->getTitle()->getPrefixedText() . '. Dying.' ); |
1544 | | - } |
1545 | | - |
1546 | | - $t_thread = Threads::withRoot( new Article( $target ) ); |
1547 | | - |
1548 | | - // Grab data about the new post. |
1549 | | - $author = $thread->author(); |
1550 | | - $sig = $sk->userLink( $author->getID(), $author->getName() ) . |
1551 | | - $sk->userToolLinks( $author->getID(), $author->getName() ); |
1552 | | - $newTalkpage = is_object( $t_thread ) ? $t_thread->getTitle() : ''; |
1553 | | - |
1554 | | - $html = wfMsgExt( 'lqt_move_placeholder', |
1555 | | - array( 'parseinline', 'replaceafter' ), |
1556 | | - $sk->link( $target ), |
1557 | | - $sig, |
1558 | | - $wgLang->date( $thread->modified() ), |
1559 | | - $wgLang->time( $thread->modified() ), |
1560 | | - $sk->link( $newTalkpage ) |
1561 | | - ); |
1562 | | - |
1563 | | - $this->output->addHTML( $html ); |
1564 | | - } |
1565 | | - |
1566 | | - /** Shows a deleted thread. Returns true to show the thread body */ |
1567 | | - function showDeletedThread( $thread ) { |
1568 | | - if ( $this->user->isAllowed( 'deletedhistory' ) ) { |
1569 | | - $this->output->addWikiMsg( 'lqt_thread_deleted_for_sysops' ); |
1570 | | - return true; |
1571 | | - } else { |
1572 | | - $msg = wfMsgExt( 'lqt_thread_deleted', 'parseinline' ); |
1573 | | - $msg = Xml::tags( 'em', null, $msg ); |
1574 | | - $msg = Xml::tags( 'p', null, $msg ); |
1575 | | - |
1576 | | - $this->output->addHTML( $msg ); |
1577 | | - return false; |
1578 | | - } |
1579 | | - } |
1580 | | - |
1581 | | - // Shows a single thread, rather than a thread tree. |
1582 | | - function showSingleThread( $thread ) { |
1583 | | - $html = ''; |
1584 | | - |
1585 | | - // If it's a 'moved' thread, show the placeholder |
1586 | | - if ( $thread->type() == Threads::TYPE_MOVED ) { |
1587 | | - $this->showMovedThread( $thread ); |
1588 | | - return; |
1589 | | - } elseif ( $thread->type() == Threads::TYPE_DELETED ) { |
1590 | | - $res = $this->showDeletedThread( $thread ); |
1591 | | - |
1592 | | - if ( !$res ) return; |
1593 | | - } |
1594 | | - |
1595 | | - $this->output->addHTML( $this->threadInfoPanel( $thread ) ); |
1596 | | - |
1597 | | - if ( $thread->summary() ) { |
1598 | | - $html .= $this->getSummary( $thread ); |
1599 | | - } |
1600 | | - |
1601 | | - // Unfortunately, I can't rewrite showRootPost() to pass back HTML |
1602 | | - // as it would involve rewriting EditPage, which I do NOT intend to do. |
1603 | | - |
1604 | | - $this->output->addHTML( $html ); |
1605 | | - |
1606 | | - $this->showThreadBody( $thread ); |
1607 | | - } |
1608 | | - |
1609 | 1018 | function getMustShowThreads( $threads = array() ) { |
1610 | 1019 | if ( $this->request->getCheck( 'lqt_operand' ) ) { |
1611 | 1020 | $operands = explode( ',', $this->request->getVal( 'lqt_operand' ) ); |
— | — | @@ -1670,336 +1079,6 @@ |
1671 | 1080 | return $link; |
1672 | 1081 | } |
1673 | 1082 | |
1674 | | - static function threadContainsRepliesWithContent( $thread ) { |
1675 | | - $replies = $thread->replies(); |
1676 | | - |
1677 | | - foreach ( $replies as $reply ) { |
1678 | | - $content = ''; |
1679 | | - if ( $reply->root() ) $content = $reply->root()->getContent(); |
1680 | | - |
1681 | | - if ( trim( $content ) != '' ) { |
1682 | | - return true; |
1683 | | - } |
1684 | | - |
1685 | | - if ( self::threadContainsRepliesWithContent( $reply ) ) { |
1686 | | - return true; |
1687 | | - } |
1688 | | - |
1689 | | - if ( $reply->type() == Threads::TYPE_MOVED ) { |
1690 | | - return true; |
1691 | | - } |
1692 | | - } |
1693 | | - |
1694 | | - return false; |
1695 | | - } |
1696 | | - |
1697 | | - function showThreadReplies( $thread, $startAt, $maxCount, $showThreads, |
1698 | | - $cascadeOptions, $interruption = false ) { |
1699 | | - $repliesClass = 'lqt-thread-replies lqt-thread-replies-' . |
1700 | | - $this->threadNestingLevel; |
1701 | | - |
1702 | | - if ( $interruption ) { |
1703 | | - $repliesClass .= ' lqt-thread-replies-interruption'; |
1704 | | - } |
1705 | | - |
1706 | | - $div = Xml::openElement( 'div', array( 'class' => $repliesClass ) ); |
1707 | | - |
1708 | | - $subthreadCount = count( $thread->subthreads() ); |
1709 | | - $i = 0; |
1710 | | - $showCount = 0; |
1711 | | - $showThreads = true; |
1712 | | - |
1713 | | - $mustShowThreads = $cascadeOptions['mustShowThreads']; |
1714 | | - |
1715 | | - $replies = $thread->subthreads(); |
1716 | | - usort( $replies, array( 'Thread', 'createdSortCallback' ) ); |
1717 | | - |
1718 | | - foreach ( $replies as $st ) { |
1719 | | - ++$i; |
1720 | | - |
1721 | | - // Only show undeleted threads that are above our 'startAt' index. |
1722 | | - $shown = false; |
1723 | | - if ( $st->type() != Threads::TYPE_DELETED && |
1724 | | - $i >= $startAt && |
1725 | | - $showThreads ) { |
1726 | | - if ( $showCount > $maxCount && $maxCount > 0 ) { |
1727 | | - // We've shown too many threads. |
1728 | | - $link = $this->getShowMore( $thread, $st, $i ); |
1729 | | - |
1730 | | - $this->output->addHTML( $div . $link ); |
1731 | | - $showThreads = false; |
1732 | | - continue; |
1733 | | - } |
1734 | | - |
1735 | | - ++$showCount; |
1736 | | - if ( $showCount == 1 ) { |
1737 | | - // There's a post sep before each reply group to |
1738 | | - // separate from the parent thread. |
1739 | | - $this->output->addHTML( $div ); |
1740 | | - } |
1741 | | - |
1742 | | - $this->showThread( $st, $i, $subthreadCount, $cascadeOptions ); |
1743 | | - $shown = true; |
1744 | | - } |
1745 | | - |
1746 | | - // Handle must-show threads. |
1747 | | - // FIXME this thread will be duplicated if somebody clicks the |
1748 | | - // "show more" link (probably needs fixing in the JS) |
1749 | | - if ( $st->type() != Threads::TYPE_DELETED && !$shown && |
1750 | | - array_key_exists( $st->id(), $mustShowThreads ) ) { |
1751 | | - |
1752 | | - $this->showThread( $st, $i, $subthreadCount, $cascadeOptions ); |
1753 | | - } |
1754 | | - } |
1755 | | - |
1756 | | - // Show reply stuff |
1757 | | - $this->showReplyBox( $thread ); |
1758 | | - |
1759 | | - $finishDiv = ''; |
1760 | | - $finishDiv .= Xml::tags( |
1761 | | - 'div', |
1762 | | - array( 'class' => 'lqt-replies-finish' ), |
1763 | | - ' ' |
1764 | | - ); |
1765 | | - |
1766 | | - $this->output->addHTML( $finishDiv . Xml::CloseElement( 'div' ) ); |
1767 | | - } |
1768 | | - |
1769 | | - function showThread( $thread, $levelNum = 1, $totalInLevel = 1, |
1770 | | - $options = array() ) { |
1771 | | - |
1772 | | - // Safeguard |
1773 | | - if ( $thread->type() & Threads::TYPE_DELETED || |
1774 | | - !$thread->root() ) { |
1775 | | - return; |
1776 | | - } |
1777 | | - |
1778 | | - $this->threadNestingLevel++; |
1779 | | - |
1780 | | - // Figure out which threads *need* to be shown because they're involved in an |
1781 | | - // operation |
1782 | | - $mustShowOption = array(); |
1783 | | - if ( isset( $options['mustShowThreads'] ) ) { |
1784 | | - $mustShowOption = $options['mustShowThreads' ]; |
1785 | | - } |
1786 | | - $mustShowThreads = $this->getMustShowThreads( $mustShowOption ); |
1787 | | - |
1788 | | - // For cascading. |
1789 | | - $options['mustShowThreads'] = $mustShowThreads; |
1790 | | - |
1791 | | - // Don't show blank posts unless we have to |
1792 | | - $content = ''; |
1793 | | - if ( $thread->root() ) $content = $thread->root()->getContent(); |
1794 | | - |
1795 | | - if ( |
1796 | | - trim( $content ) == '' && |
1797 | | - $thread->type() != Threads::TYPE_MOVED && |
1798 | | - ! self::threadContainsRepliesWithContent( $thread ) && |
1799 | | - ! array_key_exists( $thread->id(), $mustShowThreads ) |
1800 | | - ) { |
1801 | | - $this->threadNestingLevel--; |
1802 | | - return; |
1803 | | - } |
1804 | | - |
1805 | | - // Grab options |
1806 | | - if ( isset( $options['maxDepth'] ) ) { |
1807 | | - $maxDepth = $options['maxDepth']; |
1808 | | - } else { |
1809 | | - $maxDepth = $this->user->getOption( 'lqtdisplaydepth' ); |
1810 | | - } |
1811 | | - |
1812 | | - if ( isset( $options['maxCount'] ) ) { |
1813 | | - $maxCount = $options['maxCount']; |
1814 | | - } else { |
1815 | | - $maxCount = $this->user->getOption( 'lqtdisplaycount' ); |
1816 | | - } |
1817 | | - |
1818 | | - if ( isset( $options['startAt'] ) ) { |
1819 | | - $startAt = $options['startAt']; |
1820 | | - } else { |
1821 | | - $startAt = 0; |
1822 | | - } |
1823 | | - |
1824 | | - // Figure out if we have replies to show or not. |
1825 | | - $showThreads = ( $maxDepth == - 1 ) || |
1826 | | - ( $this->threadNestingLevel <= $maxDepth ); |
1827 | | - $mustShowThreadIds = array_keys( $mustShowThreads ); |
1828 | | - $subthreadIds = array_keys( $thread->replies() ); |
1829 | | - $mustShowSubthreadIds = array_intersect( $mustShowThreadIds, $subthreadIds ); |
1830 | | - |
1831 | | - $hasSubthreads = self::threadContainsRepliesWithContent( $thread ); |
1832 | | - $hasSubthreads = $hasSubthreads || count( $mustShowSubthreadIds ); |
1833 | | - // Show subthreads if one of the subthreads is on the must-show list |
1834 | | - $showThreads = $showThreads || |
1835 | | - count( array_intersect( |
1836 | | - array_keys( $mustShowThreads ), array_keys( $thread->replies() ) |
1837 | | - ) ); |
1838 | | - $replyTo = $this->methodAppliesToThread( 'reply', $thread ); |
1839 | | - |
1840 | | - $this->output->addModules( 'ext.liquidThreads' ); |
1841 | | - |
1842 | | - $html = ''; |
1843 | | - wfRunHooks( 'EditPageBeforeEditToolbar', array( &$html ) ); |
1844 | | - |
1845 | | - $class = $this->threadDivClass( $thread ); |
1846 | | - if ( $levelNum == 1 ) { |
1847 | | - $class .= ' lqt-thread-first'; |
1848 | | - } elseif ( $levelNum == $totalInLevel ) { |
1849 | | - $class .= ' lqt-thread-last'; |
1850 | | - } |
1851 | | - |
1852 | | - if ( $hasSubthreads && $showThreads ) { |
1853 | | - $class .= ' lqt-thread-with-subthreads'; |
1854 | | - } else { |
1855 | | - $class .= ' lqt-thread-no-subthreads'; |
1856 | | - } |
1857 | | - |
1858 | | - $class .= ' lqt-thread-wrapper'; |
1859 | | - |
1860 | | - $html .= Xml::openElement( |
1861 | | - 'div', |
1862 | | - array( |
1863 | | - 'class' => $class, |
1864 | | - 'id' => 'lqt_thread_id_' . $thread->id() |
1865 | | - ) |
1866 | | - ); |
1867 | | - |
1868 | | - $html .= Xml::element( 'a', array( 'name' => $this->anchorName( $thread ) ), ' ' ); |
1869 | | - $html .= $this->showThreadHeading( $thread ); |
1870 | | - |
1871 | | - // Metadata stuck in the top of the lqt_thread div. |
1872 | | - // Modified time for topmost threads... |
1873 | | - if ( $thread->isTopmostThread() ) { |
1874 | | - $html .= Html::hidden( |
1875 | | - 'lqt-thread-modified-' . $thread->id(), |
1876 | | - wfTimestamp( TS_MW, $thread->modified() ), |
1877 | | - array( |
1878 | | - 'id' => 'lqt-thread-modified-' . $thread->id(), |
1879 | | - 'class' => 'lqt-thread-modified' |
1880 | | - ) |
1881 | | - ); |
1882 | | - $html .= Html::hidden( |
1883 | | - 'lqt-thread-sortkey', |
1884 | | - $thread->sortkey(), |
1885 | | - array( 'id' => 'lqt-thread-sortkey-' . $thread->id() ) |
1886 | | - ); |
1887 | | - |
1888 | | - $html .= Html::hidden( |
1889 | | - 'lqt-thread-talkpage-' . $thread->id(), |
1890 | | - $thread->article()->getTitle()->getPrefixedText(), |
1891 | | - array( |
1892 | | - 'class' => 'lqt-thread-talkpage-metadata', |
1893 | | - ) |
1894 | | - ); |
1895 | | - } |
1896 | | - |
1897 | | - if ( ! $thread->title() ) { |
1898 | | - throw new MWException( "Thread " . $thread->id() . " has null title" ); |
1899 | | - } |
1900 | | - |
1901 | | - // Add the thread's title |
1902 | | - $html .= Html::hidden( |
1903 | | - 'lqt-thread-title-' . $thread->id(), |
1904 | | - $thread->title()->getPrefixedText(), |
1905 | | - array( |
1906 | | - 'id' => 'lqt-thread-title-' . $thread->id(), |
1907 | | - 'class' => 'lqt-thread-title-metadata' |
1908 | | - ) |
1909 | | - ); |
1910 | | - |
1911 | | - // Flush output to display thread |
1912 | | - $this->output->addHTML( $html ); |
1913 | | - $this->output->addHTML( Xml::openElement( 'div', |
1914 | | - array( 'class' => 'lqt-post-wrapper' ) ) ); |
1915 | | - $this->showSingleThread( $thread ); |
1916 | | - $this->output->addHTML( Xml::closeElement( 'div' ) ); |
1917 | | - |
1918 | | - $cascadeOptions = $options; |
1919 | | - unset( $cascadeOptions['startAt'] ); |
1920 | | - |
1921 | | - $replyInterruption = $levelNum < $totalInLevel; |
1922 | | - |
1923 | | - if ( ( $hasSubthreads && $showThreads ) ) { |
1924 | | - // If the thread has subthreads, and we want to show them, we should do so. |
1925 | | - $this->showThreadReplies( $thread, $startAt, $maxCount, $showThreads, |
1926 | | - $cascadeOptions, $replyInterruption ); |
1927 | | - } elseif ( $hasSubthreads && !$showThreads ) { |
1928 | | - // If the thread has subthreads, but we don't want to show them, then |
1929 | | - // show the reply form if necessary, and add the "Show X replies" link. |
1930 | | - if ( $replyTo ) { |
1931 | | - $this->showReplyForm( $thread ); |
1932 | | - } |
1933 | | - |
1934 | | - // Add a "show subthreads" link. |
1935 | | - $link = $this->getShowReplies( $thread ); |
1936 | | - |
1937 | | - $this->output->addHTML( $link ); |
1938 | | - |
1939 | | - if ( $levelNum < $totalInLevel ) { |
1940 | | - $this->output->addHTML( |
1941 | | - Xml::tags( 'div', array( 'class' => 'lqt-post-sep' ), ' ' ) ); |
1942 | | - } |
1943 | | - } elseif ( $levelNum < $totalInLevel ) { |
1944 | | - // If we have no replies, and we're not at the end of this level, add the post separator |
1945 | | - // and a reply box if necessary. |
1946 | | - $this->output->addHTML( |
1947 | | - Xml::tags( 'div', array( 'class' => 'lqt-post-sep' ), ' ' ) ); |
1948 | | - |
1949 | | - if ( $replyTo ) { |
1950 | | - $class = 'lqt-thread-replies lqt-thread-replies-' . |
1951 | | - $this->threadNestingLevel; |
1952 | | - $html = Xml::openElement( 'div', array( 'class' => $class ) ); |
1953 | | - $this->output->addHTML( $html ); |
1954 | | - |
1955 | | - $this->showReplyForm( $thread ); |
1956 | | - |
1957 | | - $finishDiv = Xml::tags( 'div', |
1958 | | - array( 'class' => 'lqt-replies-finish' ), |
1959 | | - ' ' ); |
1960 | | - // Layout plus close div.lqt-thread-replies |
1961 | | - |
1962 | | - $finishHTML = Xml::closeElement( 'div' ); // lqt-reply-form |
1963 | | - $finishHTML .= $finishDiv; // Layout |
1964 | | - $finishHTML .= Xml::closeElement( 'div' ); // lqt-thread-replies |
1965 | | - $this->output->addHTML( $finishHTML ); |
1966 | | - } |
1967 | | - } elseif ( !$hasSubthreads && $replyTo ) { |
1968 | | - // If we have no replies, we're at the end of this level, and we want to reply, |
1969 | | - // show the reply box. |
1970 | | - $class = 'lqt-thread-replies lqt-thread-replies-' . |
1971 | | - $this->threadNestingLevel; |
1972 | | - $html = Xml::openElement( 'div', array( 'class' => $class ) ); |
1973 | | - $this->output->addHTML( $html ); |
1974 | | - |
1975 | | - $this->showReplyForm( $thread ); |
1976 | | - |
1977 | | - $html = Xml::tags( 'div', |
1978 | | - array( 'class' => 'lqt-replies-finish' ), |
1979 | | - Xml::tags( 'div', |
1980 | | - array( 'class' => |
1981 | | - 'lqt-replies-finish-corner' |
1982 | | - ), ' ' ) ); |
1983 | | - $html .= Xml::closeElement( 'div' ); |
1984 | | - $this->output->addHTML( $html ); |
1985 | | - } |
1986 | | - |
1987 | | - // I don't remember why this is here, commenting out. |
1988 | | -// if ( $this->threadNestingLevel == 1 ) { |
1989 | | -// if ( !( $hasSubthreads && $showThreads && !$replyTo ) ) { |
1990 | | -// $this->showReplyBox( $thread ); |
1991 | | -// $finishDiv = ''; |
1992 | | -// $finishDiv .= Xml::tags( 'div', array( 'class' => 'lqt-replies-finish' ), |
1993 | | -// Xml::tags( 'div', array( 'class' => 'lqt-replies-finish-corner' ), ' ' ) ); |
1994 | | -// |
1995 | | -// $this->output->addHTML( $finishDiv ); |
1996 | | -// } |
1997 | | -// } |
1998 | | - |
1999 | | - $this->output->addHTML( Xml::closeElement( 'div' ) ); |
2000 | | - |
2001 | | - $this->threadNestingLevel--; |
2002 | | - } |
2003 | | - |
2004 | 1083 | function showReplyBox( $thread ) { |
2005 | 1084 | // Check if we're actually replying to this thread. |
2006 | 1085 | if ( $this->methodAppliesToThread( 'reply', $thread ) ) { |
— | — | @@ -2168,22 +1247,4 @@ |
2169 | 1248 | function show() { |
2170 | 1249 | return true; // No-op |
2171 | 1250 | } |
2172 | | - |
2173 | | - // Copy-and-modify of Linker::formatComment |
2174 | | - static function formatSubject( $s ) { |
2175 | | - wfProfileIn( __METHOD__ ); |
2176 | | - global $wgUser; |
2177 | | - $sk = $wgUser->getSkin(); |
2178 | | - |
2179 | | - # Sanitize text a bit: |
2180 | | - $s = str_replace( "\n", " ", $s ); |
2181 | | - # Allow HTML entities |
2182 | | - $s = Sanitizer::escapeHtmlAllowEntities( $s ); |
2183 | | - |
2184 | | - # Render links: |
2185 | | - $s = $sk->formatLinksInComment( $s, null, false ); |
2186 | | - |
2187 | | - wfProfileOut( __METHOD__ ); |
2188 | | - return $s; |
2189 | | - } |
2190 | 1251 | } |