Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 89 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
ResourceLoaderData | |
0.00% |
0 / 89 |
|
0.00% |
0 / 7 |
462 | |
0.00% |
0 / 1 |
getLocalData | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
getContentLanguageMessages | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
getTermsOfUseMessages | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
getTermsOfUseMessagesParsed | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getTermsOfUseMessagesVersion | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
addOptionalDependencies | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
makeTestModule | |
0.00% |
0 / 45 |
|
0.00% |
0 / 1 |
110 |
1 | <?php |
2 | /** |
3 | * Utilities for ResourceLoader modules used by DiscussionTools. |
4 | * |
5 | * @file |
6 | * @ingroup Extensions |
7 | * @license MIT |
8 | */ |
9 | |
10 | namespace MediaWiki\Extension\DiscussionTools; |
11 | |
12 | use ExtensionRegistry; |
13 | use MediaWiki\Config\Config; |
14 | use MediaWiki\Extension\DiscussionTools\Hooks\HookRunner; |
15 | use MediaWiki\MediaWikiServices; |
16 | use MediaWiki\ResourceLoader as RL; |
17 | use MediaWiki\Title\Title; |
18 | use MessageLocalizer; |
19 | |
20 | class ResourceLoaderData { |
21 | /** |
22 | * Used for the 'ext.discussionTools.init' module and the test module. |
23 | * |
24 | * We need all of this data *in content language*. Some of it is already available in JS, but only |
25 | * in client language, so it's useless for us (e.g. digit transform table, month name messages). |
26 | */ |
27 | public static function getLocalData( |
28 | RL\Context $context, Config $config, ?string $langCode = null |
29 | ): array { |
30 | $services = MediaWikiServices::getInstance(); |
31 | |
32 | if ( $langCode === null ) { |
33 | $langData = $services->getService( 'DiscussionTools.LanguageData' ); |
34 | } else { |
35 | $langData = new LanguageData( |
36 | $services->getMainConfig(), |
37 | $services->getLanguageFactory()->getLanguage( $langCode ), |
38 | $services->getLanguageConverterFactory(), |
39 | $services->getSpecialPageFactory() |
40 | ); |
41 | } |
42 | |
43 | return $langData->getLocalData(); |
44 | } |
45 | |
46 | /** |
47 | * Return messages in content language, for use in a ResourceLoader module. |
48 | */ |
49 | public static function getContentLanguageMessages( |
50 | RL\Context $context, Config $config, array $messagesKeys = [] |
51 | ): array { |
52 | return array_combine( |
53 | $messagesKeys, |
54 | array_map( static function ( $key ) { |
55 | return wfMessage( $key )->inContentLanguage()->text(); |
56 | }, $messagesKeys ) |
57 | ); |
58 | } |
59 | |
60 | /** |
61 | * Return information about terms-of-use messages. |
62 | * |
63 | * @param MessageLocalizer $context |
64 | * @param Config $config |
65 | * @return array[] Map from internal name to array of parameters for MessageLocalizer::msg() |
66 | * @phan-return non-empty-array[] |
67 | */ |
68 | private static function getTermsOfUseMessages( |
69 | MessageLocalizer $context, Config $config |
70 | ): array { |
71 | $messages = [ |
72 | 'reply' => [ 'discussiontools-replywidget-terms-click', |
73 | $context->msg( 'discussiontools-replywidget-reply' )->text() ], |
74 | 'newtopic' => [ 'discussiontools-replywidget-terms-click', |
75 | $context->msg( 'discussiontools-replywidget-newtopic' )->text() ], |
76 | ]; |
77 | |
78 | $hookRunner = new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ); |
79 | $hookRunner->onDiscussionToolsTermsOfUseMessages( $messages, $context, $config ); |
80 | |
81 | return $messages; |
82 | } |
83 | |
84 | /** |
85 | * Return parsed terms-of-use messages, for use in a ResourceLoader module. |
86 | */ |
87 | public static function getTermsOfUseMessagesParsed( |
88 | MessageLocalizer $context, Config $config |
89 | ): array { |
90 | $messages = static::getTermsOfUseMessages( $context, $config ); |
91 | foreach ( $messages as &$msg ) { |
92 | $msg = $context->msg( ...$msg )->parse(); |
93 | } |
94 | return $messages; |
95 | } |
96 | |
97 | /** |
98 | * Return information about terms-of-use messages, for use in a ResourceLoader module as |
99 | * 'versionCallback'. This is to avoid calling the parser from version invalidation code. |
100 | */ |
101 | public static function getTermsOfUseMessagesVersion( |
102 | MessageLocalizer $context, Config $config |
103 | ): array { |
104 | $messages = static::getTermsOfUseMessages( $context, $config ); |
105 | foreach ( $messages as &$msg ) { |
106 | $message = $context->msg( ...$msg ); |
107 | $msg = [ |
108 | // Include the text of the message, in case the canonical translation changes |
109 | $message->plain(), |
110 | // Include the page touched time, in case the on-wiki override is invalidated |
111 | Title::makeTitle( NS_MEDIAWIKI, ucfirst( $message->getKey() ) )->getTouched(), |
112 | ]; |
113 | } |
114 | return $messages; |
115 | } |
116 | |
117 | /** |
118 | * Add optional dependencies to a ResourceLoader module definition depending on loaded extensions. |
119 | */ |
120 | public static function addOptionalDependencies( array $info ): RL\Module { |
121 | $extensionRegistry = ExtensionRegistry::getInstance(); |
122 | |
123 | foreach ( $info['optionalDependencies'] as $ext => $deps ) { |
124 | if ( $extensionRegistry->isLoaded( $ext ) ) { |
125 | $info['dependencies'] = array_merge( $info['dependencies'], (array)$deps ); |
126 | } |
127 | } |
128 | |
129 | $class = $info['class'] ?? RL\FileModule::class; |
130 | return new $class( $info ); |
131 | } |
132 | |
133 | /** |
134 | * Generate the test module that includes all of the test data, based on the JSON files defining |
135 | * test cases. |
136 | */ |
137 | public static function makeTestModule( array $info ): RL\Module { |
138 | // Some tests rely on PHP-only features or are too large for the Karma test runner. |
139 | // Skip them here. They are still tested in the PHP version. |
140 | $skipTests = [ |
141 | 'cases/modified.json' => [ |
142 | // Too large, cause timeouts in Karma test runner |
143 | 'enwiki oldparser', |
144 | 'enwiki parsoid', |
145 | 'enwiki oldparser (bullet indentation)', |
146 | 'enwiki parsoid (bullet indentation)', |
147 | // These tests depend on #getTranscludedFrom(), which we didn't implement in JS |
148 | 'arwiki no-paragraph parsoid', |
149 | 'enwiki parsoid', |
150 | 'Many comments consisting of a block template and a paragraph', |
151 | 'Comment whose range almost exactly matches a template, but is not considered transcluded (T313100)', |
152 | 'Accidental complex transclusion (T265528)', |
153 | 'Accidental complex transclusion (T313093)', |
154 | ], |
155 | ]; |
156 | $info['packageFiles'][] = [ |
157 | 'name' => 'skip.json', |
158 | 'type' => 'data', |
159 | 'content' => $skipTests, |
160 | ]; |
161 | |
162 | $keys = [ 'config', 'data', 'dom', 'expected' ]; |
163 | foreach ( $info['testData'] as $path ) { |
164 | $info['packageFiles'][] = $path; |
165 | $localPath = $info['localBasePath'] . '/' . $path; |
166 | $data = json_decode( file_get_contents( $localPath ), true ); |
167 | foreach ( $data as $case ) { |
168 | if ( isset( $case['name'] ) && in_array( $case['name'], $skipTests[$path] ?? [], true ) ) { |
169 | continue; |
170 | } |
171 | foreach ( $case as $key => $val ) { |
172 | if ( in_array( $key, $keys, true ) && is_string( $val ) ) { |
173 | if ( str_ends_with( $val, '.json' ) ) { |
174 | $info['packageFiles'][] = substr( $val, strlen( '../' ) ); |
175 | } elseif ( str_ends_with( $val, '.html' ) ) { |
176 | $info['packageFiles'][] = [ |
177 | 'name' => $val, |
178 | 'type' => 'data', |
179 | 'callback' => static function () use ( $info, $val ) { |
180 | $localPath = $info['localBasePath'] . '/' . $val; |
181 | return file_get_contents( $localPath ); |
182 | }, |
183 | 'versionCallback' => static function () use ( $val ) { |
184 | return new RL\FilePath( $val ); |
185 | }, |
186 | ]; |
187 | } |
188 | } |
189 | } |
190 | } |
191 | } |
192 | $class = $info['class'] ?? RL\FileModule::class; |
193 | return new $class( $info ); |
194 | } |
195 | } |