Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 110 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
EditIndexPage | |
0.00% |
0 / 110 |
|
0.00% |
0 / 8 |
650 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
showContentForm | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
30 | |||
buildField | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
132 | |||
buildCategoriesField | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
getFieldNameForEntry | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
importContentFormData | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
20 | |||
importCategoryList | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
cleanInputtedContent | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace ProofreadPage\Index; |
4 | |
5 | use Article; |
6 | use LogicException; |
7 | use MediaWiki\Content\WikitextContent; |
8 | use MediaWiki\EditPage\EditPage; |
9 | use MediaWiki\MediaWikiServices; |
10 | use MediaWiki\Request\WebRequest; |
11 | use MediaWiki\Title\Title; |
12 | use OOUI\DropdownInputWidget; |
13 | use OOUI\FieldLayout; |
14 | use OOUI\FieldsetLayout; |
15 | use OOUI\MultilineTextInputWidget; |
16 | use OOUI\TextInputWidget; |
17 | use ProofreadPage\Context; |
18 | use ProofreadPage\OOUI\PagelistInputWidget; |
19 | use ProofreadPage\Pagination\PageNumber; |
20 | |
21 | /** |
22 | * @license GPL-2.0-or-later |
23 | */ |
24 | class EditIndexPage extends EditPage { |
25 | |
26 | /** |
27 | * @var Context |
28 | */ |
29 | private $extContext; |
30 | |
31 | /** |
32 | * @param Article $article Article of page to be edited |
33 | */ |
34 | public function __construct( Article $article ) { |
35 | parent::__construct( $article ); |
36 | |
37 | $this->extContext = Context::getDefaultContext(); |
38 | } |
39 | |
40 | /** |
41 | * @inheritDoc |
42 | */ |
43 | protected function showContentForm() { |
44 | $pageLang = $this->getTitle()->getPageLanguage(); |
45 | $out = $this->context->getOutput(); |
46 | $out->enableOOUI(); |
47 | $inputOptions = [ 'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir() ]; |
48 | if ( MediaWikiServices::getInstance()->getReadOnlyMode()->isReadOnly() ) { |
49 | $inputOptions['readOnly'] = ''; |
50 | } |
51 | |
52 | $content = $this->toEditContent( $this->textbox1 ); |
53 | if ( !( $content instanceof IndexContent ) ) { |
54 | throw new LogicException( 'EditIndexPage is only able to display a form for IndexContent' ); |
55 | } |
56 | |
57 | $fields = []; |
58 | $i = 10; |
59 | $entries = $this->extContext->getCustomIndexFieldsParser()->parseCustomIndexFields( $content ); |
60 | foreach ( $entries as $entry ) { |
61 | $inputOptions['tabIndex'] = $i; |
62 | if ( !$entry->isHidden() ) { |
63 | $fields[] = $this->buildField( $entry, $inputOptions ); |
64 | } |
65 | $i++; |
66 | } |
67 | |
68 | $inputOptions['tabIndex'] = $i; |
69 | $fields[] = $this->buildCategoriesField( $content->getCategories(), $inputOptions ); |
70 | |
71 | $out->addHTML( new FieldsetLayout( [ |
72 | 'items' => $fields, |
73 | 'classes' => [ 'prp-index-fieldLayout' ] |
74 | ] ) ); |
75 | |
76 | $out->addModules( 'ext.proofreadpage.index' ); |
77 | } |
78 | |
79 | /** |
80 | * @param CustomIndexField $field |
81 | * @param array $inputOptions |
82 | * @return FieldLayout |
83 | */ |
84 | private function buildField( CustomIndexField $field, $inputOptions ) { |
85 | $key = $this->getFieldNameForEntry( $field->getKey() ); |
86 | $val = $field->getStringValue(); |
87 | $out = $this->context->getOutput(); |
88 | |
89 | $out->addJsConfigVars( 'prpPagelistBuiltinLabels', PageNumber::getDisplayModes() ); |
90 | |
91 | $inputOptions['name'] = $key; |
92 | $inputOptions['value'] = $val; |
93 | $inputOptions['inputId'] = $key; |
94 | |
95 | $values = $field->getPossibleValues(); |
96 | if ( $values !== null ) { |
97 | $options = []; |
98 | foreach ( $values as $data => $label ) { |
99 | $options[] = [ 'data' => $data, 'label' => $label ]; |
100 | } |
101 | if ( !array_key_exists( $val, $values ) && $val !== '' ) { |
102 | $options[] = [ 'data' => $val, 'label' => $val ]; |
103 | } |
104 | $input = new DropdownInputWidget( $inputOptions + [ |
105 | 'options' => $options |
106 | ] ); |
107 | } elseif ( $field->isPagelist() ) { |
108 | $input = new PagelistInputWidget( array_merge( [ |
109 | 'templateParameter' => $field->getKey(), |
110 | 'rows' => $field->getSize() |
111 | ], $inputOptions ) ); |
112 | $out->addModules( 'ext.proofreadpage.index.pagelist' ); |
113 | } else { |
114 | if ( $field->getSize() > 1 ) { |
115 | $input = new MultilineTextInputWidget( $inputOptions + [ |
116 | 'rows' => $field->getSize() |
117 | ] ); |
118 | } else { |
119 | $input = new TextInputWidget( $inputOptions + [ |
120 | 'type' => $field->getType() === 'number' && ( $val === '' || is_numeric( $val ) ) |
121 | ? 'number' |
122 | : 'text', |
123 | ] ); |
124 | } |
125 | } |
126 | |
127 | $fieldLayoutArgs = [ |
128 | 'label' => $field->getLabel() |
129 | ]; |
130 | if ( $field->getHelp() ) { |
131 | $fieldLayoutArgs += [ |
132 | 'help' => $field->getHelp(), |
133 | 'infusable' => true, |
134 | 'classes' => [ 'prp-fieldLayout-help' ] |
135 | ]; |
136 | } |
137 | |
138 | return new FieldLayout( $input, $fieldLayoutArgs ); |
139 | } |
140 | |
141 | /** |
142 | * @param array $categories |
143 | * @param array $inputOptions |
144 | * @return FieldLayout |
145 | */ |
146 | private function buildCategoriesField( array $categories, $inputOptions ) { |
147 | $input = new TextInputWidget( $inputOptions + [ |
148 | 'type' => 'text', |
149 | 'name' => 'wpPrpCategories', |
150 | 'value' => implode( '|', array_map( static function ( Title $title ) { |
151 | return $title->getText(); |
152 | }, $categories ) ), |
153 | 'inputId' => 'wpPrpCategories' |
154 | ] ); |
155 | return new FieldLayout( $input, [ |
156 | 'label' => $this->context->msg( 'proofreadpage-index-field-category-label' )->text(), |
157 | 'help' => $this->context->msg( 'proofreadpage-index-edit-category-help' )->text(), |
158 | 'infusable' => true, |
159 | 'classes' => [ 'prp-fieldLayout-help' ] |
160 | ] ); |
161 | } |
162 | |
163 | /** |
164 | * Return the name of the edit field for an entry |
165 | * |
166 | * @param string $key the entry key |
167 | * @return string |
168 | */ |
169 | protected function getFieldNameForEntry( $key ) { |
170 | return 'wpprpindex-' . str_replace( ' ', '_', $key ); |
171 | } |
172 | |
173 | /** |
174 | * @inheritDoc |
175 | */ |
176 | protected function importContentFormData( &$request ) { |
177 | if ( $this->textbox1 !== '' ) { |
178 | return $this->textbox1; |
179 | } |
180 | |
181 | $config = $this->extContext->getCustomIndexFieldsParser()->getCustomIndexFieldsConfiguration(); |
182 | $fields = []; |
183 | foreach ( $config as $key => $params ) { |
184 | $field = $this->getFieldNameForEntry( $key ); |
185 | $value = $this->cleanInputtedContent( $request->getText( $field ) ); |
186 | $entry = new CustomIndexField( $key, $value, $params ); |
187 | if ( !$entry->isHidden() ) { |
188 | $fields[$entry->getKey()] = new WikitextContent( $entry->getStringValue() ); |
189 | } |
190 | } |
191 | $content = new IndexContent( $fields, $this->importCategoryList( $request ) ); |
192 | return $content->serialize( $this->contentFormat ); |
193 | } |
194 | |
195 | /** |
196 | * Returns filtered list of categories from a web request. |
197 | * @param WebRequest $request |
198 | * @return Title[] |
199 | */ |
200 | private function importCategoryList( WebRequest $request ) { |
201 | return array_filter( array_map( static function ( $text ) { |
202 | return Title::makeTitleSafe( NS_CATEGORY, trim( $text ) ); |
203 | }, explode( '|', $request->getText( 'wpPrpCategories' ) ) ), static function ( $title ) { |
204 | return $title !== null; |
205 | } ); |
206 | } |
207 | |
208 | /** |
209 | * Clean a text before inclusion into a template |
210 | * |
211 | * @param string $value |
212 | * @return string |
213 | */ |
214 | protected function cleanInputtedContent( $value ) { |
215 | // remove trailing \n \t or \r |
216 | $value = trim( $value ); |
217 | |
218 | // replace pipe symbol everywhere... |
219 | $value = preg_replace( '/\|/', '&!&', $value ); |
220 | |
221 | // ...except in links... |
222 | do { |
223 | $prev = $value; |
224 | $value = preg_replace( '/\[\[(.*?)&!&(.*?)\]\]/', '[[$1|$2]]', $value ); |
225 | } while ( $value !== $prev ); |
226 | |
227 | // ..and in templates |
228 | do { |
229 | $prev = $value; |
230 | $value = preg_replace( '/\{\{(.*?)&!&(.*?)\}\}/s', '{{$1|$2}}', $value ); |
231 | } while ( $value !== $prev ); |
232 | |
233 | $value = preg_replace( '/&!&/', '{{!}}', $value ); |
234 | |
235 | return $value; |
236 | } |
237 | } |