Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 121 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
CollectionRenderingAPI | |
0.00% |
0 / 121 |
|
0.00% |
0 / 11 |
992 | |
0.00% |
0 / 1 |
instance | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
makeRequest | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getBaseUrl | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
render | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
forceRender | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
doRender | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
postZip | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
getRenderStatus | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
download | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getLicenseInfos | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
20 | |||
buildJsonCollection | |
0.00% |
0 / 63 |
|
0.00% |
0 / 1 |
272 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Collection\Rendering; |
4 | |
5 | use FormatJson; |
6 | use MediaWiki\MediaWikiServices; |
7 | use RequestContext; |
8 | |
9 | /** |
10 | * Base class for API that interacts with book rendering service |
11 | */ |
12 | abstract class CollectionRenderingAPI { |
13 | /** @var self */ |
14 | private static $inst; |
15 | |
16 | /** @var string|false */ |
17 | protected $writer; |
18 | |
19 | /** |
20 | * @param string|false $writer Name of a writer, or false if none specified/needed. |
21 | * |
22 | * @return self |
23 | */ |
24 | public static function instance( $writer = false ) { |
25 | if ( !self::$inst ) { |
26 | self::$inst = new MWServeRenderingAPI( $writer ); |
27 | } |
28 | return self::$inst; |
29 | } |
30 | |
31 | /** |
32 | * @param string|false $writer Name of a writer, or false if none specified/needed. |
33 | */ |
34 | public function __construct( $writer ) { |
35 | $this->writer = $writer; |
36 | } |
37 | |
38 | /** |
39 | * When overridden in derived class, performs a request to the service |
40 | * |
41 | * @param string $command |
42 | * @param array $params |
43 | * @return CollectionAPIResult |
44 | */ |
45 | abstract protected function makeRequest( $command, array $params ); |
46 | |
47 | /** |
48 | * @return string Expanded wgScriptPath to work around T39868 |
49 | */ |
50 | private function getBaseUrl() { |
51 | global $wgScriptPath; |
52 | |
53 | return wfExpandUrl( $wgScriptPath ?: '/', PROTO_CANONICAL ); |
54 | } |
55 | |
56 | /** |
57 | * Requests a collection to be rendered |
58 | * @param array $collection |
59 | * |
60 | * @return CollectionAPIResult |
61 | */ |
62 | public function render( array $collection ) { |
63 | return $this->doRender( [ |
64 | 'metabook' => $this->buildJsonCollection( $collection ), |
65 | ] |
66 | ); |
67 | } |
68 | |
69 | /** |
70 | * Requests a queued collection to be immediately rendered |
71 | * |
72 | * @param string $collectionId |
73 | * @return CollectionAPIResult |
74 | */ |
75 | public function forceRender( $collectionId ) { |
76 | return $this->doRender( [ |
77 | 'collection_id' => $collectionId, |
78 | 'force_render' => true |
79 | ] |
80 | ); |
81 | } |
82 | |
83 | protected function doRender( array $params ) { |
84 | $params['base_url'] = $this->getBaseUrl(); |
85 | $params['script_extension'] = '.php'; |
86 | $params['language'] = MediaWikiServices::getInstance()->getContentLanguage() |
87 | ->getCode(); |
88 | return $this->makeRequest( 'render', $params ); |
89 | } |
90 | |
91 | /** |
92 | * Requests the service to create a collection package and send it to an external server |
93 | * e.g. for printing |
94 | * |
95 | * @param array $collection |
96 | * @param string $url |
97 | * |
98 | * @return CollectionAPIResult |
99 | */ |
100 | public function postZip( array $collection, $url ) { |
101 | return $this->makeRequest( 'zip_post', |
102 | [ |
103 | 'metabook' => $this->buildJsonCollection( $collection ), |
104 | 'base_url' => $this->getBaseUrl(), |
105 | 'script_extension' => '.php', |
106 | 'pod_api_url' => $url, |
107 | ] |
108 | ); |
109 | } |
110 | |
111 | /** |
112 | * Returns information about a collection's rendering status |
113 | * |
114 | * @param string $collectionId |
115 | * @return CollectionAPIResult |
116 | */ |
117 | public function getRenderStatus( $collectionId ) { |
118 | return $this->makeRequest( |
119 | 'render_status', |
120 | [ |
121 | 'collection_id' => $collectionId, |
122 | ] |
123 | ); |
124 | } |
125 | |
126 | /** |
127 | * Requests a download of rendered collection |
128 | * |
129 | * @param string $collectionId |
130 | * @return CollectionAPIResult |
131 | */ |
132 | public function download( $collectionId ) { |
133 | return $this->makeRequest( 'download', |
134 | [ |
135 | 'collection_id' => $collectionId, |
136 | ] |
137 | ); |
138 | } |
139 | |
140 | /** |
141 | * @return array |
142 | */ |
143 | protected function getLicenseInfos() { |
144 | global $wgCollectionLicenseName, $wgCollectionLicenseURL, $wgRightsIcon; |
145 | global $wgRightsPage, $wgRightsText, $wgRightsUrl; |
146 | |
147 | $licenseInfo = [ |
148 | 'type' => 'license', |
149 | ]; |
150 | |
151 | $fromMsg = wfMessage( 'coll-license_url' )->inContentLanguage(); |
152 | if ( !$fromMsg->isDisabled() ) { |
153 | $licenseInfo['mw_license_url'] = $fromMsg->text(); |
154 | return [ $licenseInfo ]; |
155 | } |
156 | |
157 | if ( $wgCollectionLicenseName ) { |
158 | $licenseInfo['name'] = $wgCollectionLicenseName; |
159 | } else { |
160 | $licenseInfo['name'] = wfMessage( 'coll-license' )->inContentLanguage()->text(); |
161 | } |
162 | |
163 | if ( $wgCollectionLicenseURL ) { |
164 | $licenseInfo['mw_license_url'] = $wgCollectionLicenseURL; |
165 | } else { |
166 | $licenseInfo['mw_rights_icon'] = $wgRightsIcon; |
167 | $licenseInfo['mw_rights_page'] = $wgRightsPage; |
168 | $licenseInfo['mw_rights_url'] = $wgRightsUrl; |
169 | $licenseInfo['mw_rights_text'] = $wgRightsText; |
170 | } |
171 | |
172 | return [ $licenseInfo ]; |
173 | } |
174 | |
175 | /** |
176 | * @param array $collection |
177 | * @return string |
178 | */ |
179 | protected function buildJsonCollection( array $collection ) { |
180 | $result = [ |
181 | 'type' => 'collection', |
182 | 'licenses' => $this->getLicenseInfos() |
183 | ]; |
184 | |
185 | if ( isset( $collection['title'] ) ) { |
186 | $result['title'] = $collection['title']; |
187 | } |
188 | if ( isset( $collection['subtitle'] ) ) { |
189 | $result['subtitle'] = $collection['subtitle']; |
190 | } |
191 | if ( isset( $collection['settings'] ) ) { |
192 | foreach ( $collection['settings'] as $key => $val ) { |
193 | $result[$key] = $val; |
194 | } |
195 | // compatibility with old mw-serve |
196 | $result['settings'] = $collection['settings']; |
197 | } |
198 | |
199 | $items = []; |
200 | if ( isset( $collection['items'] ) ) { |
201 | $currentChapter = null; |
202 | foreach ( $collection['items'] as $item ) { |
203 | if ( $item['type'] == 'article' ) { |
204 | if ( $currentChapter === null ) { |
205 | $items[] = $item; |
206 | } else { |
207 | $currentChapter['items'][] = $item; |
208 | } |
209 | } elseif ( $item['type'] == 'chapter' ) { |
210 | if ( $currentChapter !== null ) { |
211 | $items[] = $currentChapter; |
212 | } |
213 | $currentChapter = $item; |
214 | } |
215 | } |
216 | if ( $currentChapter !== null ) { |
217 | $items[] = $currentChapter; |
218 | } |
219 | } |
220 | $result['items'] = $items; |
221 | |
222 | $result['wikis'] = [ |
223 | [ |
224 | 'type' => 'wikiconf', |
225 | 'baseurl' => $this->getBaseUrl(), |
226 | 'script_extension' => '.php', |
227 | 'format' => 'nuwiki', |
228 | ], |
229 | ]; |
230 | |
231 | // Prefer VRS configuration if present. |
232 | $context = RequestContext::getMain(); |
233 | $vrs = $context->getConfig()->get( 'VirtualRestConfig' ); |
234 | if ( isset( $vrs['modules']['restbase']['url'] ) ) { |
235 | // if restbase is available, use it |
236 | $params = $vrs['modules']['restbase']; |
237 | $domain = preg_replace( |
238 | '/^(https?:\/\/)?([^\/:]+?)(\/|:\d+\/?)?$/', |
239 | '$2', |
240 | $params['domain'] ?? 'localhost' |
241 | ); |
242 | $url = preg_replace( |
243 | '#/?$#', |
244 | '/' . $domain . '/v1/', |
245 | $params['url'] |
246 | ); |
247 | for ( $i = 0, $count = count( $result['wikis'] ); $i < $count; $i++ ) { |
248 | $result['wikis'][$i]['restbase1'] = $url; |
249 | } |
250 | } elseif ( isset( $vrs['modules']['parsoid']['url'] ) ) { |
251 | // there's a global parsoid config, use it next |
252 | $params = $vrs['modules']['parsoid']; |
253 | $domain = preg_replace( |
254 | '/^(https?:\/\/)?([^\/:]+?)(\/|:\d+\/?)?$/', |
255 | '$2', |
256 | $params['domain'] ?? 'localhost' |
257 | ); |
258 | for ( $i = 0, $count = count( $result['wikis'] ); $i < $count; $i++ ) { |
259 | $result['wikis'][$i]['parsoid'] = $params['url']; |
260 | $result['wikis'][$i]['prefix'] = $params['prefix'] ?? null; |
261 | $result['wikis'][$i]['domain'] = $domain; |
262 | } |
263 | } |
264 | |
265 | return FormatJson::encode( $result ); |
266 | } |
267 | } |