Index: trunk/extensions/Score/Score.body.php |
— | — | @@ -32,16 +32,14 @@ |
33 | 33 | */ |
34 | 34 | class ScoreException extends Exception { |
35 | 35 | /** |
36 | | - * Error message parameters |
| 36 | + * Constructor. |
| 37 | + * |
| 38 | + * @param $message Message to create error message from. Should have one $1 parameter. |
| 39 | + * @param $code optionally, an error code. |
| 40 | + * @param $previous Exception that caused this exception. |
37 | 41 | */ |
38 | | - private $parameters; |
39 | | - |
40 | | - /** |
41 | | - * Empty constructor. |
42 | | - */ |
43 | | - public function __construct( $message ) { |
44 | | - $this->parameters = array_slice( func_get_args(), 1 ); |
45 | | - parent::__construct( $message ); |
| 42 | + public function __construct( $message, $code = 0, Exception $previous = null ) { |
| 43 | + parent::__construct( $message->inContentLanguage()->parse(), $code, $previous ); |
46 | 44 | } |
47 | 45 | |
48 | 46 | /** |
— | — | @@ -54,66 +52,41 @@ |
55 | 53 | return Html::rawElement( |
56 | 54 | 'span', |
57 | 55 | array( 'class' => 'error' ), |
58 | | - wfMessage( $this->getMessage() ) |
59 | | - ->inContentLanguage() |
60 | | - ->params( $this->parameters ) |
61 | | - ->parse() |
| 56 | + $this->getMessage() |
62 | 57 | ); |
63 | 58 | } |
64 | 59 | } |
65 | 60 | |
66 | 61 | /** |
67 | | - * Score call exception. |
68 | | - * This is a type of exception thrown when a call to some binary used by the |
69 | | - * Score extension fails. |
| 62 | + * Score class |
70 | 63 | */ |
71 | | -class ScoreCallException extends ScoreException { |
| 64 | +class Score { |
72 | 65 | /** |
73 | | - * Error message returned from the call. |
| 66 | + * LilyPond version string. |
| 67 | + * It defaults to null and is set the first time it is required. |
74 | 68 | */ |
75 | | - private $callErrMsg; |
| 69 | + private static $lilypondVersion = null; |
76 | 70 | |
77 | 71 | /** |
78 | | - * Constructs a new ScoreCallException. |
| 72 | + * Throws proper ScoreException in case of failed shell executions. |
79 | 73 | * |
80 | | - * @param $message Message key to be used. It should accept one |
81 | | - * parameter, the error message returned from the binary. |
82 | | - * @param $callErrMsg Raw error message returned by the binary. |
83 | | - */ |
84 | | - public function __construct( $message, $callErrMsg ) { |
85 | | - $this->callErrMsg = $callErrMsg; |
86 | | - parent::__construct( $message ); |
87 | | - } |
88 | | - |
89 | | - /** |
90 | | - * Auto-renders exception as HTML error message in the wiki's content |
91 | | - * language. |
| 74 | + * @param $message Message to display. |
| 75 | + * @param $output collected output from wfShellExec(). |
92 | 76 | * |
93 | | - * @return error message HTML. |
| 77 | + * @throws ScoreException always. |
94 | 78 | */ |
95 | | - public function __toString() { |
96 | | - return Html::rawElement( |
97 | | - 'span', |
98 | | - array( 'class' => 'error' ), |
99 | | - wfMessage( $this->getMessage() ) |
100 | | - ->inContentLanguage() |
101 | | - ->rawParams( Html::rawElement( 'pre', array(), strip_tags( $this->callErrMsg ) ) ) |
102 | | - ->parse() |
| 79 | + private function throwCallException( $message, $output ) { |
| 80 | + throw new ScoreException( |
| 81 | + $message->rawParams( |
| 82 | + Html::rawElement( 'pre', |
| 83 | + array(), |
| 84 | + strip_tags( $output ) |
| 85 | + ) |
| 86 | + ) |
103 | 87 | ); |
104 | 88 | } |
105 | | -} |
106 | 89 | |
107 | | -/** |
108 | | - * Score class |
109 | | - */ |
110 | | -class Score { |
111 | 90 | /** |
112 | | - * LilyPond version string. |
113 | | - * It defaults to null and is set the first time it is required. |
114 | | - */ |
115 | | - private static $lilypondVersion = null; |
116 | | - |
117 | | - /** |
118 | 91 | * Determines the version of LilyPond in use and writes the version |
119 | 92 | * string to self::$lilypondVersion. |
120 | 93 | * |
— | — | @@ -123,19 +96,19 @@ |
124 | 97 | global $wgLilyPond; |
125 | 98 | |
126 | 99 | if ( !is_executable( $wgLilyPond ) ) { |
127 | | - throw new ScoreException( 'score-notexecutable', $wgLilyPond ); |
| 100 | + throw new ScoreException( wfMessage( 'score-notexecutable', $wgLilyPond ) ); |
128 | 101 | } |
129 | 102 | |
130 | 103 | $cmd = wfEscapeShellArg( $wgLilyPond ) . ' --version 2>&1'; // FIXME: 2>&1 is not portable |
131 | | - $stdout = wfShellExec( $cmd, $rc ); |
| 104 | + $output = wfShellExec( $cmd, $rc ); |
132 | 105 | if ( $rc != 0 ) { |
133 | | - throw new ScoreCallException( 'score-versionerr', $stdout ); |
| 106 | + self::throwCallException( wfMessage( 'score-versionerr' ), $output ); |
134 | 107 | } |
135 | 108 | |
136 | | - $n = sscanf( $stdout, 'GNU LilyPond %s', self::$lilypondVersion ); |
| 109 | + $n = sscanf( $output, 'GNU LilyPond %s', self::$lilypondVersion ); |
137 | 110 | if ( $n != 1 ) { |
138 | 111 | self::$lilypondVersion = null; |
139 | | - throw new ScoreCallException( 'score-versionerr', $stdout ); |
| 112 | + self::throwCallException( wfMessage( 'score-versionerr' ), $output ); |
140 | 113 | } |
141 | 114 | } |
142 | 115 | |
— | — | @@ -159,7 +132,7 @@ |
160 | 133 | $factoryDirectory = $wgTmpDirectory . "/$factoryPrefix$fuzz"; |
161 | 134 | $rc = wfMkdirParents( $factoryDirectory, 0700, __METHOD__ ); |
162 | 135 | if ( !$rc ) { |
163 | | - throw new ScoreException( 'score-nofactory' ); |
| 136 | + throw new ScoreException( wfMessage( 'score-nofactory' ) ); |
164 | 137 | } |
165 | 138 | } catch ( ScoreException $e ) { |
166 | 139 | return $e; |
— | — | @@ -193,7 +166,7 @@ |
194 | 167 | } |
195 | 168 | $rc = file_put_contents( $lilypondFile, $lilypondCode ); |
196 | 169 | if ( $rc === false ) { |
197 | | - throw new ScoreException( 'score-noinput', $lilypondFile ); |
| 170 | + throw new ScoreException( wfMessage( 'score-noinput', $lilypondFile ) ); |
198 | 171 | } |
199 | 172 | break; |
200 | 173 | case 'ABC': |
— | — | @@ -201,7 +174,7 @@ |
202 | 175 | self::runAbc2Ly( $code, $factoryDirectory ); |
203 | 176 | break; |
204 | 177 | default: |
205 | | - throw new ScoreException( 'score-invalidlang', $lang ); |
| 178 | + throw new ScoreException( wfMessage( 'score-invalidlang', $lang ) ); |
206 | 179 | } |
207 | 180 | |
208 | 181 | $html = self::runLilypond( $factoryDirectory, $renderMidi, $altText ); |
— | — | @@ -271,12 +244,12 @@ |
272 | 245 | /* Create ABC input file */ |
273 | 246 | $rc = file_put_contents( $abcFile, ltrim( $code ) ); // abc2ly is picky about whitespace at the start of the file |
274 | 247 | if ( $rc === false ) { |
275 | | - throw new ScoreException( 'score-noabcinput', $abcFile ); |
| 248 | + throw new ScoreException( wfMessage( 'score-noabcinput', $abcFile ) ); |
276 | 249 | } |
277 | 250 | |
278 | 251 | /* Convert to LilyPond file */ |
279 | 252 | if ( !is_executable( $wgAbc2Ly ) ) { |
280 | | - throw new ScoreException( 'score-abc2lynotexecutable', $wgAbc2Ly ); |
| 253 | + throw new ScoreException( wfMessage( 'score-abc2lynotexecutable', $wgAbc2Ly ) ); |
281 | 254 | } |
282 | 255 | |
283 | 256 | $cmd = wfEscapeShellArg( $wgAbc2Ly ) |
— | — | @@ -286,25 +259,25 @@ |
287 | 260 | . ' 2>&1'; // FIXME: this last bit is not portable |
288 | 261 | $output = wfShellExec( $cmd, $rc ); |
289 | 262 | if ( $rc != 0 ) { |
290 | | - throw new ScoreCallException( 'score-abcconversionerr', $output ); |
| 263 | + self::throwCallException( wfMessage( 'score-abcconversionerr' ), $output ); |
291 | 264 | } |
292 | 265 | if ( !file_exists( $lyFile ) ) { |
293 | 266 | /* Occasionally, abc2ly will return exit code 0 but not create an output file */ |
294 | | - throw new ScoreCallException( 'score-abcconversionerr', $output ); |
| 267 | + self::throwCallException( wfMessage( 'score-abcconversionerr' ), $output ); |
295 | 268 | } |
296 | 269 | |
297 | 270 | /* The output file has a tagline which should be removed in a wiki context */ |
298 | 271 | $lyData = file_get_contents( $lyFile ); |
299 | 272 | if ( $lyData === false ) { |
300 | | - throw new ScoreException( 'score-readerr', $lyFile ); |
| 273 | + throw new ScoreException( wfMessage( 'score-readerr', $lyFile ) ); |
301 | 274 | } |
302 | 275 | $lyData = preg_replace( '/^(\s*tagline\s*=).*/m', '$1 ##f', $lyData ); |
303 | 276 | if ( $lyData === null ) { |
304 | | - throw new ScoreException( 'score-pregreplaceerr' ); |
| 277 | + throw new ScoreException( wfMessage( 'score-pregreplaceerr' ) ); |
305 | 278 | } |
306 | 279 | $rc = file_put_contents( $lyFile, $lyData ); |
307 | 280 | if ( $rc === false ) { |
308 | | - throw new ScoreException( 'score-noinput', $lyFile ); |
| 281 | + throw new ScoreException( wfMessage( 'score-noinput', $lyFile ) ); |
309 | 282 | } |
310 | 283 | } |
311 | 284 | |
— | — | @@ -335,7 +308,7 @@ |
336 | 309 | $lilypondDir = 'lilypond'; |
337 | 310 | $md5 = md5_file( $lilypondFile ); |
338 | 311 | if ( $md5 === false ) { |
339 | | - throw new ScoreException( 'score-noinput', $lilypondFile ); |
| 312 | + throw new ScoreException( wfMessage( 'score-noinput', $lilypondFile ) ); |
340 | 313 | } |
341 | 314 | $rel = $lilypondDir . '/' . $md5; // FIXME: Too many files in one directory? |
342 | 315 | $filePrefix = "$wgUploadDirectory/$rel"; |
— | — | @@ -376,28 +349,28 @@ |
377 | 350 | $rc = $rc && unlink( $f ); |
378 | 351 | } |
379 | 352 | if ( !$rc ) { |
380 | | - throw new ScoreException( 'score-cleanerr' ); |
| 353 | + throw new ScoreException( wfMessage( 'score-cleanerr' ) ); |
381 | 354 | } |
382 | 355 | |
383 | 356 | /* create output directory if necessary */ |
384 | 357 | if ( !file_exists( "$wgUploadDirectory/$lilypondDir" ) ) { |
385 | 358 | $rc = wfMkdirParents( "$wgUploadDirectory/$lilypondDir", null, __METHOD__ ); |
386 | 359 | if ( !$rc ) { |
387 | | - throw new ScoreException( 'score-nooutput', $lilypondDir ); |
| 360 | + throw new ScoreException( wfMessage( 'score-nooutput', $lilypondDir ) ); |
388 | 361 | } |
389 | 362 | } |
390 | 363 | |
391 | 364 | /* generate lilypond output files in working environment */ |
392 | 365 | $oldcwd = getcwd(); |
393 | 366 | if ( $oldcwd === false ) { |
394 | | - throw new ScoreException( 'score-getcwderr' ); |
| 367 | + throw new ScoreException( wfMessage( 'score-getcwderr' ) ); |
395 | 368 | } |
396 | 369 | $rc = chdir( $factoryDirectory ); |
397 | 370 | if ( !$rc ) { |
398 | | - throw new ScoreException( 'score-chdirerr', $factoryDirectory ); |
| 371 | + throw new ScoreException( wfMessage( 'score-chdirerr', $factoryDirectory ) ); |
399 | 372 | } |
400 | 373 | if ( !is_executable( $wgLilyPond ) ) { |
401 | | - throw new ScoreException( 'score-notexecutable', $wgLilyPond ); |
| 374 | + throw new ScoreException( wfMessage( 'score-notexecutable', $wgLilyPond ) ); |
402 | 375 | } |
403 | 376 | $cmd = wfEscapeShellArg( $wgLilyPond ) |
404 | 377 | . " -dsafe='#t' -dbackend=eps --png --header=texidoc " |
— | — | @@ -406,10 +379,10 @@ |
407 | 380 | $output = wfShellExec( $cmd, $rc2 ); |
408 | 381 | $rc = chdir( $oldcwd ); |
409 | 382 | if ( !$rc ) { |
410 | | - throw new ScoreException( 'score-chdirerr', $oldcwd ); |
| 383 | + throw new ScoreException( wfMessage( 'score-chdirerr', $oldcwd ) ); |
411 | 384 | } |
412 | 385 | if ( $rc2 != 0 ) { |
413 | | - throw new ScoreCallException( 'score-compilererr', $output ); |
| 386 | + self::throwCallException( wfMessage( 'score-compilererr' ), $output ); |
414 | 387 | } |
415 | 388 | |
416 | 389 | /* trim output images if wanted */ |
— | — | @@ -437,7 +410,7 @@ |
438 | 411 | $rc = $rc && rename( $f, sprintf( $multiFormat, $i ) ); |
439 | 412 | } |
440 | 413 | if ( !$rc ) { |
441 | | - throw new ScoreException( 'score-renameerr' ); |
| 414 | + throw new ScoreException( wfMessage( 'score-renameerr' ) ); |
442 | 415 | } |
443 | 416 | |
444 | 417 | } catch ( ScoreException $e ) { |
— | — | @@ -503,7 +476,7 @@ |
504 | 477 | . ' 2>&1'; // FIXME: not portable |
505 | 478 | $output = wfShellExec( $cmd, $rc ); |
506 | 479 | if ( $rc != 0 ) { |
507 | | - throw new ScoreCallException( 'score-trimerr', $output ); |
| 480 | + self::throwCallException( wfMessage( 'score-trimerr' ), $output ); |
508 | 481 | } |
509 | 482 | } |
510 | 483 | |