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