Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 139 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
PFFormEditAction | |
0.00% |
0 / 139 |
|
0.00% |
0 / 9 |
1806 | |
0.00% |
0 / 1 |
getName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
show | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
displayTab | |
0.00% |
0 / 45 |
|
0.00% |
0 / 1 |
342 | |||
displayFormChooser | |
0.00% |
0 / 44 |
|
0.00% |
0 / 1 |
132 | |||
getNumPagesPerForm | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
6 | |||
printLinksToFormArray | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
displayForm | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
12 | |||
doesWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | use MediaWiki\MediaWikiServices; |
4 | |
5 | /** |
6 | * Handles the formedit action. |
7 | * |
8 | * @author Yaron Koren |
9 | * @author Stephan Gambke |
10 | * @file |
11 | * @ingroup PF |
12 | */ |
13 | |
14 | class PFFormEditAction extends Action { |
15 | |
16 | /** |
17 | * Return the name of the action this object responds to |
18 | * @return string lowercase |
19 | */ |
20 | public function getName() { |
21 | return 'formedit'; |
22 | } |
23 | |
24 | /** |
25 | * The main action entry point. Do all output for display and send it to the context |
26 | * output. Do not use globals $wgOut, $wgRequest, etc, in implementations; use |
27 | * $this->getOutput(), etc. |
28 | * @throws ErrorPageError |
29 | * @return false |
30 | */ |
31 | public function show() { |
32 | return self::displayForm( $this, $this->getArticle() ); |
33 | } |
34 | |
35 | /** |
36 | * Execute the action in a silent fashion: do not display anything or release any errors. |
37 | * @return bool whether execution was successful |
38 | */ |
39 | public function execute() { |
40 | return true; |
41 | } |
42 | |
43 | /** |
44 | * Adds an "action" (i.e., a tab) to edit the current article with |
45 | * a form |
46 | * @param IContextSource $obj |
47 | * @param array &$links |
48 | */ |
49 | static function displayTab( $obj, &$links ) { |
50 | $title = $obj->getTitle(); |
51 | $user = $obj->getUser(); |
52 | |
53 | // Make sure that this is not a special page, and |
54 | // that the user is allowed to edit it |
55 | // - this function is almost never called on special pages, |
56 | // but before SMW is fully initialized, it's called on |
57 | // Special:SMWAdmin for some reason, which is why the |
58 | // special-page check is there. |
59 | if ( !isset( $title ) || |
60 | ( $title->getNamespace() == NS_SPECIAL ) ) { |
61 | return; |
62 | } |
63 | |
64 | $form_names = PFFormLinker::getDefaultFormsForPage( $title ); |
65 | if ( count( $form_names ) == 0 ) { |
66 | return; |
67 | } |
68 | |
69 | global $wgPageFormsRenameEditTabs, $wgPageFormsRenameMainEditTab; |
70 | |
71 | $content_actions = &$links['views']; |
72 | |
73 | $permissionManager = MediaWikiServices::getInstance()->getPermissionManager(); |
74 | $user_can_edit = $permissionManager->userCan( 'edit', $user, $title, $permissionManager::RIGOR_QUICK ); |
75 | |
76 | // Create the form edit tab, and apply whatever changes are |
77 | // specified by the edit-tab global variables. |
78 | if ( $wgPageFormsRenameEditTabs ) { |
79 | $form_edit_tab_msg = $user_can_edit ? 'edit' : 'pf_viewform'; |
80 | if ( array_key_exists( 'edit', $content_actions ) ) { |
81 | $msg = $user_can_edit ? 'pf_editsource' : 'viewsource'; |
82 | $content_actions['edit']['text'] = wfMessage( $msg )->text(); |
83 | } |
84 | } else { |
85 | if ( $user_can_edit ) { |
86 | $form_edit_tab_msg = $title->exists() ? 'formedit' : 'pf_formcreate'; |
87 | } else { |
88 | $form_edit_tab_msg = 'pf_viewform'; |
89 | } |
90 | // Check for renaming of main edit tab only if |
91 | // $wgPageFormsRenameEditTabs is off. |
92 | if ( $wgPageFormsRenameMainEditTab ) { |
93 | if ( array_key_exists( 'edit', $content_actions ) ) { |
94 | $msg = $user_can_edit ? 'pf_editsource' : 'viewsource'; |
95 | $content_actions['edit']['text'] = wfMessage( $msg )->text(); |
96 | } |
97 | } |
98 | } |
99 | |
100 | $class_name = ( $obj->getRequest()->getVal( 'action' ) == 'formedit' ) ? 'selected' : ''; |
101 | $form_edit_tab = [ |
102 | 'class' => $class_name, |
103 | 'text' => wfMessage( $form_edit_tab_msg )->text(), |
104 | 'href' => $title->getLocalURL( 'action=formedit' ) |
105 | ]; |
106 | |
107 | // Find the location of the 'edit' tab, and add 'edit |
108 | // with form' right before it. |
109 | // This is a "key-safe" splice - it preserves both the keys |
110 | // and the values of the array, by editing them separately |
111 | // and then rebuilding the array. Based on the example at |
112 | // http://us2.php.net/manual/en/function.array-splice.php#31234 |
113 | $tab_keys = array_keys( $content_actions ); |
114 | $tab_values = array_values( $content_actions ); |
115 | $edit_tab_location = array_search( 'edit', $tab_keys ); |
116 | |
117 | // If there's no 'edit' tab, look for the 'view source' tab |
118 | // instead. |
119 | if ( $edit_tab_location == null ) { |
120 | $edit_tab_location = array_search( 'viewsource', $tab_keys ); |
121 | } |
122 | |
123 | // This should rarely happen, but if there was no edit *or* |
124 | // view source tab, set the location index to -1, so the |
125 | // tab shows up near the end. |
126 | if ( $edit_tab_location == null ) { |
127 | $edit_tab_location = -1; |
128 | } |
129 | array_splice( $tab_keys, $edit_tab_location, 0, 'formedit' ); |
130 | array_splice( $tab_values, $edit_tab_location, 0, [ $form_edit_tab ] ); |
131 | $content_actions = []; |
132 | foreach ( $tab_keys as $i => $key ) { |
133 | $content_actions[$key] = $tab_values[$i]; |
134 | } |
135 | |
136 | if ( !$obj->getUser()->isAllowed( 'viewedittab' ) ) { |
137 | // The tab can have either of these two actions. |
138 | unset( $content_actions['edit'] ); |
139 | unset( $content_actions['viewsource'] ); |
140 | } |
141 | } |
142 | |
143 | static function displayFormChooser( $output, $title ) { |
144 | global $wgPageFormsMainFormsMinimum; |
145 | |
146 | $output->addModules( 'ext.pageforms.main.styles' ); |
147 | |
148 | $targetName = $title->getPrefixedText(); |
149 | $output->setPageTitle( wfMessage( "creating", $targetName )->text() ); |
150 | |
151 | try { |
152 | $formNames = PFUtils::getAllForms(); |
153 | } catch ( MWException $e ) { |
154 | $output->addHTML( Html::element( 'div', [ 'class' => 'error' ], $e->getMessage() ) ); |
155 | return; |
156 | } |
157 | |
158 | $output->addHTML( Html::element( 'p', null, wfMessage( 'pf-formedit-selectform' )->text() ) ); |
159 | $pagesPerForm = self::getNumPagesPerForm(); |
160 | $totalPages = 0; |
161 | foreach ( $pagesPerForm as $formName => $numPages ) { |
162 | $totalPages += $numPages; |
163 | } |
164 | // We define "popular forms" as those that are used to |
165 | // edit more than the specified amount of the wiki's |
166 | // form-editable pages. (Set by $wgPageFormsMainFormsMinimum, |
167 | // which by default is 1%.) |
168 | $popularForms = []; |
169 | foreach ( $pagesPerForm as $formName => $numPages ) { |
170 | if ( $numPages > $totalPages * $wgPageFormsMainFormsMinimum ) { |
171 | $popularForms[] = $formName; |
172 | } |
173 | } |
174 | $otherForms = []; |
175 | foreach ( $formNames as $i => $formName ) { |
176 | if ( !in_array( $formName, $popularForms ) ) { |
177 | $otherForms[] = $formName; |
178 | } |
179 | } |
180 | |
181 | $fe = PFUtils::getSpecialPage( 'FormEdit' ); |
182 | |
183 | if ( count( $popularForms ) > 0 ) { |
184 | if ( count( $otherForms ) > 0 ) { |
185 | $output->addHTML( Html::element( |
186 | 'p', |
187 | [], |
188 | wfMessage( 'pf-formedit-mainforms' )->text() |
189 | ) ); |
190 | } |
191 | $text = self::printLinksToFormArray( $popularForms, $targetName, $fe ); |
192 | $output->addHTML( Html::rawElement( 'div', [ 'class' => 'infoMessage mainForms' ], $text ) ); |
193 | } |
194 | |
195 | if ( count( $otherForms ) > 0 ) { |
196 | if ( count( $popularForms ) > 0 ) { |
197 | $output->addHTML( Html::element( |
198 | 'p', |
199 | [], |
200 | wfMessage( 'pf-formedit-otherforms' )->text() |
201 | ) ); |
202 | } |
203 | $text = self::printLinksToFormArray( $otherForms, $targetName, $fe ); |
204 | $output->addHTML( Html::rawElement( 'div', [ 'class' => 'infoMessage otherForms' ], $text ) ); |
205 | } |
206 | |
207 | $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); |
208 | $linkParams = [ 'action' => 'edit', 'redlink' => true ]; |
209 | $noFormLink = $linkRenderer->makeKnownLink( $title, wfMessage( 'pf-formedit-donotuseform' )->escaped(), [], $linkParams ); |
210 | $output->addHTML( Html::rawElement( 'p', null, $noFormLink ) ); |
211 | } |
212 | |
213 | /** |
214 | * Find the number of pages on the wiki that use each form, by getting |
215 | * all the categories that have a #default_form call pointing to a |
216 | * particular form, and adding up the number of pages in each such |
217 | * category. |
218 | * This approach doesn't count #default_form calls for namespaces or |
219 | * individual pages, but that doesn't seem like a big deal, because, |
220 | * when creating a page in a namespace that has a form, this interface |
221 | * probably won't get called anyway; and #default_form calls for |
222 | * individual pages are (hopefully) pretty rare. |
223 | * @return int[] |
224 | */ |
225 | static function getNumPagesPerForm() { |
226 | $dbr = PFUtils::getReadDB(); |
227 | $res = $dbr->select( |
228 | [ 'category', 'page', 'page_props' ], |
229 | [ 'pp_value', 'SUM(cat_pages) AS total_pages' ], |
230 | [ |
231 | // Keep backward compatibility with |
232 | // the page property name for |
233 | // Semantic Forms. |
234 | 'pp_propname' => [ 'PFDefaultForm', 'SFDefaultForm' ] |
235 | ], |
236 | __METHOD__, |
237 | [ |
238 | 'GROUP BY' => 'pp_value', |
239 | 'ORDER BY' => 'total_pages DESC', |
240 | 'LIMIT' => 100 |
241 | ], |
242 | [ |
243 | 'page' => [ 'JOIN', 'cat_title = page_title' ], |
244 | 'page_props' => [ 'JOIN', 'page_id = pp_page' ] |
245 | ] |
246 | ); |
247 | |
248 | $pagesPerForm = []; |
249 | while ( $row = $res->fetchRow() ) { |
250 | $formName = $row['pp_value']; |
251 | $pagesPerForm[$formName] = $row['total_pages']; |
252 | } |
253 | return $pagesPerForm; |
254 | } |
255 | |
256 | static function printLinksToFormArray( $formNames, $targetName, $fe ) { |
257 | $text = ''; |
258 | foreach ( $formNames as $i => $formName ) { |
259 | if ( $i > 0 ) { |
260 | $text .= ' <span class="pageforms-separator">·</span> '; |
261 | } |
262 | |
263 | // Special handling for forms whose name contains a slash. |
264 | if ( strpos( $formName, '/' ) !== false ) { |
265 | $url = $fe->getPageTitle()->getLocalURL( [ 'form' => $formName, 'target' => $targetName ] ); |
266 | } else { |
267 | $url = $fe->getPageTitle( "$formName/$targetName" )->getLocalURL(); |
268 | } |
269 | $text .= Html::element( 'a', [ 'href' => $url ], $formName ); |
270 | } |
271 | return $text; |
272 | } |
273 | |
274 | /** |
275 | * The function called if we're in index.php (as opposed to one of the |
276 | * special pages) |
277 | * @param Action $action |
278 | * @param Article $article |
279 | * @return true |
280 | */ |
281 | static function displayForm( $action, $article ) { |
282 | $output = $action->getOutput(); |
283 | $title = $article->getTitle(); |
284 | $form_names = PFFormLinker::getDefaultFormsForPage( $title ); |
285 | if ( count( $form_names ) == 0 ) { |
286 | // If no form is set, display an interface to let the |
287 | // user choose out of all the forms defined on this wiki |
288 | // (or none at all). |
289 | self::displayFormChooser( $output, $title ); |
290 | return true; |
291 | } |
292 | |
293 | if ( count( $form_names ) > 1 ) { |
294 | $warning_text = Html::warningBox( wfMessage( 'pf_formedit_morethanoneform' )->text() ); |
295 | $output->addWikiTextAsInterface( $warning_text ); |
296 | } |
297 | |
298 | $form_name = $form_names[0]; |
299 | $page_name = $title->getPrefixedText(); |
300 | |
301 | $pfFormEdit = new PFFormEdit(); |
302 | $pfFormEdit->printForm( $form_name, $page_name ); |
303 | |
304 | return false; |
305 | } |
306 | |
307 | public function doesWrites() { |
308 | return true; |
309 | } |
310 | } |