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