Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
36.00% |
18 / 50 |
|
50.00% |
7 / 14 |
CRAP | |
0.00% |
0 / 1 |
ConversionStrategy | |
36.00% |
18 / 50 |
|
50.00% |
7 / 14 |
73.98 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
getSourceStore | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMoveComment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getCleanupComment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isConversionFinished | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
createImportSource | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
decideArchiveTitle | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
createArchiveCleanupRevisionContent | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
getPostprocessor | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
shouldConvert | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
removePrefixText | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getPrefixText | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
removeLqtMagicWord | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
getDisableLqtMagicWord | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Flow\Import\LiquidThreadsApi; |
4 | |
5 | use Flow\Import\ArchiveNameHelper; |
6 | use Flow\Import\IConversionStrategy; |
7 | use Flow\Import\Postprocessor\LqtNotifications; |
8 | use Flow\Import\Postprocessor\LqtRedirector; |
9 | use Flow\Import\Postprocessor\ProcessorGroup; |
10 | use Flow\Import\SourceStore\SourceStoreInterface; |
11 | use Flow\Notifications\Controller; |
12 | use Flow\UrlGenerator; |
13 | use LqtDispatch; |
14 | use MediaWiki\Content\WikitextContent; |
15 | use MediaWiki\MediaWikiServices; |
16 | use MediaWiki\Title\Title; |
17 | use MediaWiki\User\User; |
18 | use MediaWiki\Utils\MWTimestamp; |
19 | use Wikimedia\Rdbms\IReadableDatabase; |
20 | |
21 | /** |
22 | * Converts LiquidThreads pages on a wiki to Flow. This converter is idempotent |
23 | * when used with an appropriate SourceStoreInterface, and may be run many times |
24 | * without worry for duplicate imports. |
25 | * |
26 | * Pages with the LQT magic word will be moved to a subpage of their original location |
27 | * named 'LQT Archive N' with N increasing starting at 1 looking for the first empty page. |
28 | * On successful import of an entire page the LQT magic word will be stripped from the |
29 | * archive version of the page. |
30 | */ |
31 | class ConversionStrategy implements IConversionStrategy { |
32 | |
33 | protected IReadableDatabase $dbr; |
34 | /** |
35 | * @var SourceStoreInterface |
36 | */ |
37 | protected $sourceStore; |
38 | |
39 | /** |
40 | * @var ApiBackend |
41 | */ |
42 | public $api; |
43 | |
44 | /** |
45 | * @var UrlGenerator |
46 | */ |
47 | protected $urlGenerator; |
48 | |
49 | /** |
50 | * @var User |
51 | */ |
52 | protected $talkpageUser; |
53 | |
54 | /** |
55 | * @var Controller |
56 | */ |
57 | protected $notificationController; |
58 | |
59 | public function __construct( |
60 | IReadableDatabase $dbr, |
61 | SourceStoreInterface $sourceStore, |
62 | ApiBackend $api, |
63 | UrlGenerator $urlGenerator, |
64 | User $talkpageUser, |
65 | Controller $notificationController |
66 | ) { |
67 | $this->dbr = $dbr; |
68 | $this->sourceStore = $sourceStore; |
69 | $this->api = $api; |
70 | $this->urlGenerator = $urlGenerator; |
71 | $this->talkpageUser = $talkpageUser; |
72 | $this->notificationController = $notificationController; |
73 | } |
74 | |
75 | public function getSourceStore() { |
76 | return $this->sourceStore; |
77 | } |
78 | |
79 | public function getMoveComment( Title $from, Title $to ) { |
80 | return "Conversion of LQT to Flow from: {$from->getPrefixedText()}"; |
81 | } |
82 | |
83 | public function getCleanupComment( Title $from, Title $to ) { |
84 | return "LQT to Flow conversion"; |
85 | } |
86 | |
87 | public function isConversionFinished( Title $title, ?Title $movedFrom = null ) { |
88 | if ( LqtDispatch::isLqtPage( $title ) ) { |
89 | return false; |
90 | } else { |
91 | return true; |
92 | } |
93 | } |
94 | |
95 | public function createImportSource( Title $title ) { |
96 | return new ImportSource( $this->api, $title->getPrefixedText(), $this->talkpageUser ); |
97 | } |
98 | |
99 | /** |
100 | * Flow does not support viewing the history of the wikitext pages it takes |
101 | * over, so those need to be moved out the way. This method decides that |
102 | * destination. The archived revisions include the headers displayed with |
103 | * lqt and potentially any pre-lqt wikitext talk page content. |
104 | * |
105 | * @param Title $source |
106 | * @return Title |
107 | */ |
108 | public function decideArchiveTitle( Title $source ) { |
109 | $archiveNameHelper = new ArchiveNameHelper(); |
110 | return $archiveNameHelper->decideArchiveTitle( $source, [ |
111 | '%s/LQT Archive %d', |
112 | ] ); |
113 | } |
114 | |
115 | /** |
116 | * Creates a new revision that ensures the LQT magic word is there and turning LQT off. |
117 | * It also adds a template about the move. |
118 | * effectively no longer be LQT pages. |
119 | * |
120 | * @param WikitextContent $content |
121 | * @param Title $title |
122 | * @return WikitextContent |
123 | */ |
124 | public function createArchiveCleanupRevisionContent( WikitextContent $content, Title $title ) { |
125 | // cleanup existing text |
126 | $existing = $content->getText(); |
127 | $existing = self::removeLqtMagicWord( $existing ); |
128 | $existing = $this->removePrefixText( $existing ); |
129 | |
130 | // prefix the existing text with some additional info related to the conversion |
131 | $text = $this->getPrefixText( $content, $title ) . "\n\n"; |
132 | $text .= self::getDisableLqtMagicWord() . "\n\n"; |
133 | $text .= $existing; |
134 | |
135 | return new WikitextContent( $text ); |
136 | } |
137 | |
138 | public function getPostprocessor() { |
139 | $group = new ProcessorGroup; |
140 | $group->add( new LqtRedirector( $this->urlGenerator, $this->talkpageUser ) ); |
141 | $group->add( new LqtNotifications( $this->notificationController, $this->dbr ) ); |
142 | |
143 | return $group; |
144 | } |
145 | |
146 | /** |
147 | * @inheritDoc |
148 | */ |
149 | public function shouldConvert( Title $sourceTitle ) { |
150 | // The expensive part of this (user-override checking) is cached by LQT. |
151 | return LqtDispatch::isLqtPage( $sourceTitle ); |
152 | } |
153 | |
154 | /** |
155 | * Gets rid of any "This page is an archived page..." prefix that may have |
156 | * been added in an earlier conversion run. |
157 | * |
158 | * @param string $content |
159 | * @return string |
160 | */ |
161 | protected function removePrefixText( $content ) { |
162 | $template = wfMessage( 'flow-importer-lqt-converted-archive-template' )->inContentLanguage()->plain(); |
163 | $templateSearch = preg_quote( $template, '/' ); |
164 | return preg_replace( '/{{' . $templateSearch . '}\\|[^\\}]+}/', '', $content ); |
165 | } |
166 | |
167 | /** |
168 | * Generates a "This page is an archived page..." text to add to the |
169 | * existing content. |
170 | * |
171 | * @param WikitextContent $content |
172 | * @param Title $title |
173 | * @return string |
174 | */ |
175 | protected function getPrefixText( WikitextContent $content, Title $title ) { |
176 | $arguments = implode( '|', [ |
177 | 'from=' . $title->getPrefixedText(), |
178 | 'date=' . MWTimestamp::getInstance()->timestamp->format( 'Y-m-d' ), |
179 | ] ); |
180 | |
181 | $template = wfMessage( 'flow-importer-lqt-converted-archive-template' )->inContentLanguage()->plain(); |
182 | |
183 | return "{{{$template}|$arguments}}\n\n" . self::getDisableLqtMagicWord() . "\n\n"; |
184 | } |
185 | |
186 | /** |
187 | * Remove the LQT magic word or its localized version |
188 | * @param string $content |
189 | * @return string |
190 | */ |
191 | public static function removeLqtMagicWord( $content ) { |
192 | $magicWord = MediaWikiServices::getInstance()->getMagicWordFactory()-> |
193 | get( 'useliquidthreads' ); |
194 | $patterns = array_map( |
195 | // delete any status: enabled or disabled doesn't matter (we're |
196 | // adding disabled magic word anyway and having it twice is messy) |
197 | static function ( $word ) { |
198 | return '/{{\\s*#' . preg_quote( $word ) . ':\\s*[01]*\\s*}}/i'; |
199 | }, |
200 | [ 'useliquidthreads' ] + $magicWord->getSynonyms() ); |
201 | |
202 | return preg_replace( $patterns, '', $content ); |
203 | } |
204 | |
205 | /** |
206 | * @return string The localized magic word to disable LQT on a page |
207 | */ |
208 | public static function getDisableLqtMagicWord() { |
209 | $wordObj = MediaWikiServices::getInstance()->getMagicWordFactory()-> |
210 | get( 'useliquidthreads' ); |
211 | $magicWord = strtolower( $wordObj->getSynonym( 0 ) ); |
212 | return "{{#$magicWord:0}}"; |
213 | } |
214 | } |