Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 103 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
LqtParserFunctions | |
0.00% |
0 / 103 |
|
0.00% |
0 / 9 |
756 | |
0.00% |
0 / 1 |
useLiquidThreads | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
lqtPageLimit | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
12 | |||
addToExtensionData | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
lqtTalkPage | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
lqtThread | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
30 | |||
runLqtTalkPage | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
showLqtThread | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
onAddParserOutput | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
56 | |||
onAddHTML | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | use MediaWiki\Language\ReplacementArray; |
4 | use MediaWiki\MediaWikiServices; |
5 | use MediaWiki\Output\OutputPage; |
6 | use MediaWiki\Parser\Parser; |
7 | use MediaWiki\Parser\ParserOutput; |
8 | use MediaWiki\Parser\PPFrame; |
9 | use MediaWiki\Title\Title; |
10 | |
11 | class LqtParserFunctions { |
12 | |
13 | private const LQT_REPLACEMENTS_DATA_KEY = 'liquidthreads_replacements'; |
14 | |
15 | public static function useLiquidThreads( Parser $parser, $param = '1' ) { |
16 | $offParams = [ 'no', 'off', 'disable' ]; |
17 | // Figure out if they want to turn it off or on. |
18 | $param = trim( strtolower( $param ) ); |
19 | |
20 | if ( in_array( $param, $offParams ) || !$param ) { |
21 | $param = '0'; |
22 | } else { |
23 | $param = '1'; |
24 | } |
25 | |
26 | $parser->getOutput()->setUnsortedPageProperty( 'use-liquid-threads', $param ); |
27 | } |
28 | |
29 | public static function lqtPageLimit( Parser $parser, $param = null ) { |
30 | if ( $param && $param > 0 ) { |
31 | $parser->getOutput()->setUnsortedPageProperty( 'lqt-page-limit', $param ); |
32 | } |
33 | } |
34 | |
35 | /** |
36 | * Adds $data under $text key to ParserOutput $out extension data |
37 | * LQT_REPLACEMENTS_DATA_KEY property. |
38 | * |
39 | * @param ParserOutput $pout |
40 | * @param string $text |
41 | * @param array $data |
42 | */ |
43 | private static function addToExtensionData( ParserOutput $pout, string $text, array $data ) { |
44 | $lqtReplacements = $pout->getExtensionData( self::LQT_REPLACEMENTS_DATA_KEY ) ?? []; |
45 | $lqtReplacements[$text] = $data; |
46 | $pout->setExtensionData( self::LQT_REPLACEMENTS_DATA_KEY, $lqtReplacements ); |
47 | } |
48 | |
49 | /** To bypass the parser cache just for the LiquidThreads part, we have a cute trick. |
50 | * We leave a placeholder comment in the HTML, which we expand out in a hook. This way, |
51 | * most of the page can be cached, but the LiquidThreads dynamism still works. |
52 | * Thanks to Tim for the idea. |
53 | * @param string $content |
54 | * @param array $args |
55 | * @param Parser $parser |
56 | * @param PPFrame $frame |
57 | * @return string |
58 | */ |
59 | public static function lqtTalkPage( $content, $args, $parser, $frame ) { |
60 | $pout = $parser->getOutput(); |
61 | |
62 | // Prepare information. |
63 | $title = null; |
64 | if ( !empty( $args['talkpage'] ) ) { |
65 | $title = Title::newFromText( $args['talkpage'] ); |
66 | } |
67 | $title ??= $parser->getTitle(); |
68 | |
69 | $talkpage = new Article( $title, 0 ); |
70 | $article = new Article( $parser->getTitle(), 0 ); |
71 | |
72 | $data = [ |
73 | 'type' => 'talkpage', |
74 | 'args' => $args, |
75 | 'article' => $article, |
76 | 'title' => $article->getTitle(), |
77 | 'talkpage' => $talkpage, |
78 | ]; |
79 | |
80 | // Generate a token |
81 | $tok = MWCryptRand::generateHex( 32 ); |
82 | $text = '<!--LQT-PAGE-' . $tok . '-->'; |
83 | self::addToExtensionData( $pout, $text, $data ); |
84 | return $text; |
85 | } |
86 | |
87 | public static function lqtThread( $content, $args, $parser, $frame ) { |
88 | $pout = $parser->getOutput(); |
89 | |
90 | // Prepare information. |
91 | $title = Title::newFromText( $args['thread'] ); |
92 | $thread = null; |
93 | if ( $args['thread'] ) { |
94 | if ( is_numeric( $args['thread'] ) ) { |
95 | $thread = Threads::withId( $args['thread'] ); |
96 | } elseif ( $title ) { |
97 | $thread = Threads::withRoot( |
98 | MediaWikiServices::getInstance()->getWikiPageFactory()->newFromTitle( $title ) |
99 | ); |
100 | } |
101 | } |
102 | |
103 | if ( $thread === null ) { |
104 | return ''; |
105 | } |
106 | |
107 | $data = [ |
108 | 'type' => 'thread', |
109 | 'args' => $args, |
110 | 'thread' => $thread->id(), |
111 | 'title' => $thread->title(), |
112 | ]; |
113 | |
114 | // Generate a token |
115 | $tok = MWCryptRand::generateHex( 32 ); |
116 | $text = '<!--LQT-THREAD-' . $tok . '-->'; |
117 | self::addToExtensionData( $pout, $text, $data ); |
118 | return $text; |
119 | } |
120 | |
121 | private static function runLqtTalkPage( $details, OutputPage $out ) { |
122 | $title = $details["title"]; |
123 | $article = $details["article"]; |
124 | $talkpage = $details["talkpage"]; |
125 | $args = $details["args"]; |
126 | |
127 | global $wgRequest; |
128 | $oldOut = $out->getHTML(); |
129 | $out->clearHTML(); |
130 | |
131 | $user = $out->getUser(); |
132 | $view = new TalkpageView( $out, $article, $title, $user, $wgRequest ); |
133 | $view->setTalkPage( $talkpage ); |
134 | |
135 | // Handle show/hide preferences. Header gone by default. |
136 | $view->hideItems( 'header' ); |
137 | |
138 | if ( array_key_exists( 'show', $args ) ) { |
139 | $show = explode( ' ', $args['show'] ); |
140 | $view->setShownItems( $show ); |
141 | } |
142 | |
143 | $view->show(); |
144 | |
145 | $html = $out->getHTML(); |
146 | $out->clearHTML(); |
147 | |
148 | return $html; |
149 | } |
150 | |
151 | private static function showLqtThread( $details, OutputPage $out ) { |
152 | $title = $details["title"]; |
153 | $article = $details["article"]; |
154 | |
155 | global $wgRequest; |
156 | $oldOut = $out->getHTML(); |
157 | $out->clearHTML(); |
158 | |
159 | $thread = Threads::withRoot( MediaWikiServices::getInstance()->getWikiPageFactory()->newFromTitle( $title ) ); |
160 | |
161 | $user = $out->getUser(); |
162 | $view = new LqtView( $out, $article, $title, $user, $wgRequest ); |
163 | |
164 | $view->showThread( $thread ); |
165 | |
166 | $html = $out->getHTML(); |
167 | $out->clearHTML(); |
168 | |
169 | return $html; |
170 | } |
171 | |
172 | public static function onAddParserOutput( OutputPage $out, ParserOutput $pout ) { |
173 | if ( !$pout->getExtensionData( self::LQT_REPLACEMENTS_DATA_KEY ) ) { |
174 | return true; |
175 | } |
176 | |
177 | if ( !isset( $out->mLqtReplacements ) ) { |
178 | $out->mLqtReplacements = []; |
179 | } |
180 | |
181 | $lqtReplacements = $pout->getExtensionData( self::LQT_REPLACEMENTS_DATA_KEY ); |
182 | foreach ( $lqtReplacements as $text => $details ) { |
183 | $result = ''; |
184 | |
185 | if ( !is_array( $details ) ) { |
186 | continue; |
187 | } |
188 | |
189 | if ( $details['type'] == 'talkpage' ) { |
190 | $result = self::runLqtTalkPage( $details, $out ); |
191 | } elseif ( $details['type'] == 'thread' ) { |
192 | $result = self::showLqtThread( $details, $out ); |
193 | } |
194 | |
195 | $out->mLqtReplacements[$text] = $result; |
196 | $out->addModules( 'ext.liquidThreads' ); |
197 | } |
198 | |
199 | return true; |
200 | } |
201 | |
202 | public static function onAddHTML( OutputPage $out, &$text ) { |
203 | if ( !isset( $out->mLqtReplacements ) || !count( $out->mLqtReplacements ) ) { |
204 | return true; |
205 | } |
206 | |
207 | $replacements = $out->mLqtReplacements; |
208 | |
209 | $replacer = new ReplacementArray( $replacements ); |
210 | $text = $replacer->replace( $text ); |
211 | |
212 | return true; |
213 | } |
214 | } |