Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 124 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
SpecialHieroglyphs | |
0.00% |
0 / 124 |
|
0.00% |
0 / 8 |
420 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 47 |
|
0.00% |
0 / 1 |
6 | |||
listHieroglyphs | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
90 | |||
getToc | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
6 | |||
getCategories | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
getHeading | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSyntaxHelp | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License along |
15 | * with this program; if not, write to the Free Software Foundation, Inc., |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | * http://www.gnu.org/copyleft/gpl.html |
18 | */ |
19 | |
20 | namespace WikiHiero; |
21 | |
22 | use MediaWiki\Html\Html; |
23 | use MediaWiki\HTMLForm\HTMLForm; |
24 | use MediaWiki\MediaWikiServices; |
25 | use MediaWiki\SpecialPage\SpecialPage; |
26 | use MediaWiki\User\Options\UserOptionsLookup; |
27 | |
28 | class SpecialHieroglyphs extends SpecialPage { |
29 | /** 1 day */ |
30 | private const CACHE_EXPIRY = 86400; |
31 | |
32 | /** |
33 | * @var WikiHiero |
34 | */ |
35 | private $hiero; |
36 | private $syntaxHelp = [ |
37 | [ 'code' => '-', 'message' => 'wikihiero-separator', 'example' => 'A1 - B1' ], |
38 | [ 'code' => ':', 'message' => 'wikihiero-superposition', 'example' => 'p:t' ], |
39 | [ 'code' => '*', 'message' => 'wikihiero-juxtaposition', 'example' => 'p*t' ], |
40 | [ 'code' => '!', 'message' => 'wikihiero-eol', 'example' => 'A1-B1 ! C1-D1' ], |
41 | [ 'code' => '\\', 'message' => 'wikihiero-mirror', 'example' => 'A1\-A1' ], |
42 | [ 'code' => '..', 'message' => 'wikihiero-void', 'example' => 'A1 .. B1' ], |
43 | [ 'code' => '.', 'message' => 'wikihiero-half-void', 'example' => 'A1 . B1' ], |
44 | [ 'code' => '<!-- -->', 'message' => 'wikihiero-comment', 'example' => 'A<!-- B1 -->1' ], |
45 | ]; |
46 | private $helpColumns = [ |
47 | 'code', |
48 | 'meaning', |
49 | 'example', |
50 | 'result', |
51 | ]; |
52 | |
53 | /** |
54 | * @var UserOptionsLookup |
55 | */ |
56 | private $userOptionsLookup; |
57 | |
58 | /** |
59 | * @param UserOptionsLookup $userOptionsLookup |
60 | */ |
61 | public function __construct( UserOptionsLookup $userOptionsLookup ) { |
62 | parent::__construct( 'Hieroglyphs' ); |
63 | $this->userOptionsLookup = $userOptionsLookup; |
64 | } |
65 | |
66 | /** |
67 | * @inheritDoc |
68 | */ |
69 | public function execute( $par ) { |
70 | $this->setHeaders(); |
71 | $this->addHelpLink( 'Extension:WikiHiero/Syntax' ); |
72 | $out = $this->getContext()->getOutput(); |
73 | $out->enableOOUI(); |
74 | $out->addModules( 'ext.wikihiero.special' ); |
75 | $out->addModuleStyles( |
76 | [ 'ext.wikihiero', 'mediawiki.editfont.styles' ] |
77 | ); |
78 | $out->addWikiMsg( |
79 | 'wikihiero-special-page-text', |
80 | $this->msg( 'wikihiero-help-link' )->text() |
81 | ); |
82 | |
83 | $out->addHTML( '<div class="mw-hiero-form">' ); |
84 | $out->addHTML( '<div id="hiero-result">' ); |
85 | |
86 | $text = trim( $this->getContext()->getRequest()->getVal( 'text', '' ) ); |
87 | if ( $text !== '' ) { |
88 | $hiero = new WikiHiero(); |
89 | $out->addHTML( '<table class="wikitable">' |
90 | . '<tr><th>' . $this->msg( 'wikihiero-input' )->escaped() . '</th><th>' |
91 | . $this->msg( 'wikihiero-result' )->escaped() . '</th></tr>' |
92 | . '<tr><td><code><hiero>' . nl2br( htmlspecialchars( $text ) ) |
93 | . "</hiero></code></td><td>{$hiero->render( $text )}</td></tr></table>" |
94 | ); |
95 | } |
96 | |
97 | // End of <div id="hiero-result"> |
98 | $out->addHTML( '</div>' ); |
99 | |
100 | $formDescriptor = [ |
101 | 'textarea' => [ |
102 | 'type' => 'textarea', |
103 | 'name' => 'text', |
104 | 'id' => 'hiero-text', |
105 | // The following classes are used here: |
106 | // * mw-editfont-monospace |
107 | // * mw-editfont-sans-serif |
108 | // * mw-editfont-serif |
109 | 'cssclass' => 'mw-editfont-' . $this->userOptionsLookup->getOption( $this->getUser(), 'editfont' ), |
110 | 'default' => $text, |
111 | 'rows' => 3, |
112 | 'required' => true, |
113 | ] |
114 | ]; |
115 | |
116 | $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() ); |
117 | $htmlForm |
118 | ->setMethod( 'get' ) |
119 | ->setSubmitID( 'hiero-submit' ) |
120 | ->setSubmitName( 'submit' ) |
121 | ->setSubmitTextMsg( 'wikihiero-submit' ) |
122 | ->prepareForm() |
123 | ->displayForm( false ); |
124 | |
125 | $this->hiero = new WikiHiero(); |
126 | |
127 | $out->addHTML( $this->getToc() ); |
128 | // class="mw-hiero-form" |
129 | $out->addHTML( '</div>' ); |
130 | $out->addHTML( $this->listHieroglyphs() ); |
131 | } |
132 | |
133 | /** |
134 | * Returns a HTML list of hieroglyphs |
135 | * @return string |
136 | * @return-taint none |
137 | */ |
138 | private function listHieroglyphs() { |
139 | $services = MediaWikiServices::getInstance(); |
140 | $cache = $services->getMainWANObjectCache(); |
141 | $langConv = $services->getLanguageConverterFactory() |
142 | ->getLanguageConverter( $this->getContext()->getLanguage() ); |
143 | |
144 | return $cache->getWithSetCallback( |
145 | $cache->makeKey( 'hiero-list', |
146 | $langConv->getExtraHashOptions(), |
147 | WikiHiero::getImagePath(), |
148 | '1.2' |
149 | ), |
150 | self::CACHE_EXPIRY, |
151 | function () { |
152 | $html = ''; |
153 | |
154 | $html .= $this->getHeading( 'wikihiero-syntax', 'syntax' ); |
155 | $html .= '<table class="wikitable"><tr>'; |
156 | foreach ( $this->helpColumns as $col ) { |
157 | $html .= '<th>' . $this->msg( "wikihiero-th-$col" )->escaped() . '</th>'; |
158 | } |
159 | $html .= '</tr>'; |
160 | foreach ( $this->syntaxHelp as $e ) { |
161 | $html .= $this->getSyntaxHelp( $e['code'], $e['message'], $e['example'] ); |
162 | } |
163 | $html .= "</table>\n"; |
164 | |
165 | $files = array_keys( $this->hiero->getFiles() ); |
166 | natsort( $files ); |
167 | |
168 | foreach ( $this->getCategories() as $cat ) { |
169 | $alnum = strlen( $cat ) == 1; |
170 | $html .= $this->getHeading( "wikihiero-category-$cat", "cat-$cat" ); |
171 | foreach ( $files as $code ) { |
172 | if ( strpos( $code, '&' ) !== false ) { |
173 | // prefab |
174 | continue; |
175 | } |
176 | if ( strpos( $code, $cat ) !== 0 || ( $alnum && !ctype_digit( $code[1] ) ) ) { |
177 | // wrong category |
178 | continue; |
179 | } |
180 | $html .= |
181 | '<div class="mw-hiero-code">' . |
182 | '<span class="mw-hiero-glyph">' . $this->hiero->render( $code ) . '</span>' . |
183 | '<span class="mw-hiero-syntax">' . htmlspecialchars( $code ) . '</span>' . |
184 | '</div>'; |
185 | } |
186 | } |
187 | |
188 | return $html; |
189 | } |
190 | ); |
191 | } |
192 | |
193 | private function getToc() { |
194 | $html = '<div class="toc mw-hiero-toc">'; |
195 | |
196 | $syntax = $this->msg( 'wikihiero-syntax' )->text(); |
197 | $html .= |
198 | Html::element( 'a', |
199 | [ 'href' => "#syntax", 'title' => $syntax ], |
200 | $syntax |
201 | ); |
202 | $cats = $this->getCategories(); |
203 | $end = array_pop( $cats ); |
204 | foreach ( $cats as $cat ) { |
205 | $html .= |
206 | Html::element( 'a', |
207 | [ 'href' => "#cat-$cat", 'title' => $this->msg( "wikihiero-category-$cat" )->text() ], |
208 | $cat |
209 | ); |
210 | } |
211 | $html .= |
212 | Html::element( 'a', |
213 | [ 'href' => "#cat-$end", 'title' => $this->msg( "wikihiero-category-$end" )->text() ], |
214 | $end |
215 | ); |
216 | |
217 | $html .= '</div>'; |
218 | return $html; |
219 | } |
220 | |
221 | /** |
222 | * Returns an array with hieroglyph categories from Gardiner's list |
223 | * @return string[] |
224 | */ |
225 | private function getCategories() { |
226 | $res = []; |
227 | $ordJ = ord( 'J' ); |
228 | for ( $i = ord( 'A' ), $ordZ = ord( 'Z' ); $i <= $ordZ; $i++ ) { |
229 | if ( $i != $ordJ ) { |
230 | $res[] = chr( $i ); |
231 | } |
232 | } |
233 | $res[] = 'Aa'; |
234 | return $res; |
235 | } |
236 | |
237 | private function getHeading( $message, $anchor ) { |
238 | return "<h2 id=\"$anchor\">" . $this->msg( $message )->escaped() . "</h2>\n"; |
239 | } |
240 | |
241 | private function getSyntaxHelp( $code, $message, $example ) { |
242 | return '<tr><th>' . htmlspecialchars( $code ) . '</th><td>' |
243 | . $this->msg( $message )->escaped() . '</td><td dir="ltr">' |
244 | . '<code>' . htmlspecialchars( "<hiero>$example</hiero>" ) . '</code></td><td>' |
245 | . $this->hiero->render( $example ) |
246 | . "</td></tr>\n"; |
247 | } |
248 | |
249 | /** |
250 | * @inheritDoc |
251 | */ |
252 | protected function getGroupName() { |
253 | return 'wiki'; |
254 | } |
255 | } |