These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Implements Special:Tags |
||
4 | * |
||
5 | * This program is free software; you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation; either version 2 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | * GNU General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU General Public License along |
||
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
18 | * http://www.gnu.org/copyleft/gpl.html |
||
19 | * |
||
20 | * @file |
||
21 | * @ingroup SpecialPage |
||
22 | */ |
||
23 | |||
24 | /** |
||
25 | * A special page that lists tags for edits |
||
26 | * |
||
27 | * @ingroup SpecialPage |
||
28 | */ |
||
29 | class SpecialTags extends SpecialPage { |
||
30 | |||
31 | /** |
||
32 | * @var array List of explicitly defined tags |
||
33 | */ |
||
34 | protected $explicitlyDefinedTags; |
||
35 | |||
36 | /** |
||
37 | * @var array List of software defined tags |
||
38 | */ |
||
39 | protected $softwareDefinedTags; |
||
40 | |||
41 | /** |
||
42 | * @var array List of software activated tags |
||
43 | */ |
||
44 | protected $softwareActivatedTags; |
||
45 | |||
46 | function __construct() { |
||
47 | parent::__construct( 'Tags' ); |
||
48 | } |
||
49 | |||
50 | function execute( $par ) { |
||
51 | $this->setHeaders(); |
||
52 | $this->outputHeader(); |
||
53 | |||
54 | $request = $this->getRequest(); |
||
55 | switch ( $par ) { |
||
56 | case 'delete': |
||
57 | $this->showDeleteTagForm( $request->getVal( 'tag' ) ); |
||
58 | break; |
||
59 | case 'activate': |
||
60 | $this->showActivateDeactivateForm( $request->getVal( 'tag' ), true ); |
||
61 | break; |
||
62 | case 'deactivate': |
||
63 | $this->showActivateDeactivateForm( $request->getVal( 'tag' ), false ); |
||
64 | break; |
||
65 | case 'create': |
||
66 | // fall through, thanks to HTMLForm's logic |
||
67 | default: |
||
68 | $this->showTagList(); |
||
69 | break; |
||
70 | } |
||
71 | } |
||
72 | |||
73 | function showTagList() { |
||
74 | $out = $this->getOutput(); |
||
75 | $out->setPageTitle( $this->msg( 'tags-title' ) ); |
||
76 | $out->wrapWikiMsg( "<div class='mw-tags-intro'>\n$1\n</div>", 'tags-intro' ); |
||
77 | |||
78 | $user = $this->getUser(); |
||
79 | $userCanManage = $user->isAllowed( 'managechangetags' ); |
||
80 | $userCanDelete = $user->isAllowed( 'deletechangetags' ); |
||
81 | $userCanEditInterface = $user->isAllowed( 'editinterface' ); |
||
82 | |||
83 | // Show form to create a tag |
||
84 | if ( $userCanManage ) { |
||
85 | $fields = [ |
||
86 | 'Tag' => [ |
||
87 | 'type' => 'text', |
||
88 | 'label' => $this->msg( 'tags-create-tag-name' )->plain(), |
||
89 | 'required' => true, |
||
90 | ], |
||
91 | 'Reason' => [ |
||
92 | 'type' => 'text', |
||
93 | 'label' => $this->msg( 'tags-create-reason' )->plain(), |
||
94 | 'size' => 50, |
||
95 | ], |
||
96 | 'IgnoreWarnings' => [ |
||
97 | 'type' => 'hidden', |
||
98 | ], |
||
99 | ]; |
||
100 | |||
101 | $form = new HTMLForm( $fields, $this->getContext() ); |
||
102 | $form->setAction( $this->getPageTitle( 'create' )->getLocalURL() ); |
||
103 | $form->setWrapperLegendMsg( 'tags-create-heading' ); |
||
104 | $form->setHeaderText( $this->msg( 'tags-create-explanation' )->parseAsBlock() ); |
||
105 | $form->setSubmitCallback( [ $this, 'processCreateTagForm' ] ); |
||
106 | $form->setSubmitTextMsg( 'tags-create-submit' ); |
||
107 | $form->show(); |
||
108 | |||
109 | // If processCreateTagForm generated a redirect, there's no point |
||
110 | // continuing with this, as the user is just going to end up getting sent |
||
111 | // somewhere else. Additionally, if we keep going here, we end up |
||
112 | // populating the memcache of tag data (see ChangeTags::listDefinedTags) |
||
113 | // with out-of-date data from the replica DB, because the replica DB hasn't caught |
||
114 | // up to the fact that a new tag has been created as part of an implicit, |
||
115 | // as yet uncommitted transaction on master. |
||
116 | if ( $out->getRedirect() !== '' ) { |
||
117 | return; |
||
118 | } |
||
119 | } |
||
120 | |||
121 | // Used to get hitcounts for #doTagRow() |
||
122 | $tagStats = ChangeTags::tagUsageStatistics(); |
||
123 | |||
124 | // Used in #doTagRow() |
||
125 | $this->explicitlyDefinedTags = array_fill_keys( |
||
126 | ChangeTags::listExplicitlyDefinedTags(), true ); |
||
127 | $this->softwareDefinedTags = array_fill_keys( |
||
128 | ChangeTags::listSoftwareDefinedTags(), true ); |
||
129 | |||
130 | // List all defined tags, even if they were never applied |
||
131 | $definedTags = array_keys( $this->explicitlyDefinedTags + $this->softwareDefinedTags ); |
||
132 | |||
133 | // Show header only if there exists atleast one tag |
||
134 | if ( !$tagStats && !$definedTags ) { |
||
135 | return; |
||
136 | } |
||
137 | |||
138 | // Write the headers |
||
139 | $html = Xml::tags( 'tr', null, Xml::tags( 'th', null, $this->msg( 'tags-tag' )->parse() ) . |
||
140 | Xml::tags( 'th', null, $this->msg( 'tags-display-header' )->parse() ) . |
||
141 | Xml::tags( 'th', null, $this->msg( 'tags-description-header' )->parse() ) . |
||
142 | Xml::tags( 'th', null, $this->msg( 'tags-source-header' )->parse() ) . |
||
143 | Xml::tags( 'th', null, $this->msg( 'tags-active-header' )->parse() ) . |
||
144 | Xml::tags( 'th', null, $this->msg( 'tags-hitcount-header' )->parse() ) . |
||
145 | ( ( $userCanManage || $userCanDelete ) ? |
||
146 | Xml::tags( 'th', [ 'class' => 'unsortable' ], |
||
147 | $this->msg( 'tags-actions-header' )->parse() ) : |
||
148 | '' ) |
||
149 | ); |
||
150 | |||
151 | // Used in #doTagRow() |
||
152 | $this->softwareActivatedTags = array_fill_keys( |
||
153 | ChangeTags::listSoftwareActivatedTags(), true ); |
||
154 | |||
155 | // Insert tags that have been applied at least once |
||
156 | foreach ( $tagStats as $tag => $hitcount ) { |
||
157 | $html .= $this->doTagRow( $tag, $hitcount, $userCanManage, |
||
158 | $userCanDelete, $userCanEditInterface ); |
||
159 | } |
||
160 | // Insert tags defined somewhere but never applied |
||
161 | foreach ( $definedTags as $tag ) { |
||
162 | if ( !isset( $tagStats[$tag] ) ) { |
||
163 | $html .= $this->doTagRow( $tag, 0, $userCanManage, $userCanDelete, $userCanEditInterface ); |
||
164 | } |
||
165 | } |
||
166 | |||
167 | $out->addHTML( Xml::tags( |
||
168 | 'table', |
||
169 | [ 'class' => 'mw-datatable sortable mw-tags-table' ], |
||
170 | $html |
||
171 | ) ); |
||
172 | } |
||
173 | |||
174 | function doTagRow( $tag, $hitcount, $showManageActions, $showDeleteActions, $showEditLinks ) { |
||
175 | $newRow = ''; |
||
176 | $newRow .= Xml::tags( 'td', null, Xml::element( 'code', null, $tag ) ); |
||
177 | |||
178 | $linkRenderer = $this->getLinkRenderer(); |
||
179 | $disp = ChangeTags::tagDescription( $tag, $this->getContext() ); |
||
180 | View Code Duplication | if ( $showEditLinks ) { |
|
181 | $disp .= ' '; |
||
182 | $editLink = $linkRenderer->makeLink( |
||
183 | $this->msg( "tag-$tag" )->inContentLanguage()->getTitle(), |
||
184 | $this->msg( 'tags-edit' )->text() |
||
185 | ); |
||
186 | $disp .= $this->msg( 'parentheses' )->rawParams( $editLink )->escaped(); |
||
187 | } |
||
188 | $newRow .= Xml::tags( 'td', null, $disp ); |
||
0 ignored issues
–
show
|
|||
189 | |||
190 | $msg = $this->msg( "tag-$tag-description" ); |
||
191 | $desc = !$msg->exists() ? '' : $msg->parse(); |
||
192 | View Code Duplication | if ( $showEditLinks ) { |
|
193 | $desc .= ' '; |
||
194 | $editDescLink = $linkRenderer->makeLink( |
||
195 | $this->msg( "tag-$tag-description" )->inContentLanguage()->getTitle(), |
||
196 | $this->msg( 'tags-edit' )->text() |
||
197 | ); |
||
198 | $desc .= $this->msg( 'parentheses' )->rawParams( $editDescLink )->escaped(); |
||
199 | } |
||
200 | $newRow .= Xml::tags( 'td', null, $desc ); |
||
201 | |||
202 | $sourceMsgs = []; |
||
203 | $isSoftware = isset( $this->softwareDefinedTags[$tag] ); |
||
204 | $isExplicit = isset( $this->explicitlyDefinedTags[$tag] ); |
||
205 | if ( $isSoftware ) { |
||
206 | // TODO: Rename this message |
||
207 | $sourceMsgs[] = $this->msg( 'tags-source-extension' )->escaped(); |
||
208 | } |
||
209 | if ( $isExplicit ) { |
||
210 | $sourceMsgs[] = $this->msg( 'tags-source-manual' )->escaped(); |
||
211 | } |
||
212 | if ( !$sourceMsgs ) { |
||
213 | $sourceMsgs[] = $this->msg( 'tags-source-none' )->escaped(); |
||
214 | } |
||
215 | $newRow .= Xml::tags( 'td', null, implode( Xml::element( 'br' ), $sourceMsgs ) ); |
||
216 | |||
217 | $isActive = $isExplicit || isset( $this->softwareActivatedTags[$tag] ); |
||
218 | $activeMsg = ( $isActive ? 'tags-active-yes' : 'tags-active-no' ); |
||
219 | $newRow .= Xml::tags( 'td', null, $this->msg( $activeMsg )->escaped() ); |
||
220 | |||
221 | $hitcountLabelMsg = $this->msg( 'tags-hitcount' )->numParams( $hitcount ); |
||
222 | if ( $this->getConfig()->get( 'UseTagFilter' ) ) { |
||
223 | $hitcountLabel = $linkRenderer->makeLink( |
||
224 | SpecialPage::getTitleFor( 'Recentchanges' ), |
||
225 | $hitcountLabelMsg->text(), |
||
226 | [], |
||
227 | [ 'tagfilter' => $tag ] |
||
228 | ); |
||
229 | } else { |
||
230 | $hitcountLabel = $hitcountLabelMsg->escaped(); |
||
231 | } |
||
232 | |||
233 | // add raw $hitcount for sorting, because tags-hitcount contains numbers and letters |
||
234 | $newRow .= Xml::tags( 'td', [ 'data-sort-value' => $hitcount ], $hitcountLabel ); |
||
235 | |||
236 | // actions |
||
237 | $actionLinks = []; |
||
238 | |||
239 | // delete |
||
240 | if ( $showDeleteActions && ChangeTags::canDeleteTag( $tag )->isOK() ) { |
||
241 | $actionLinks[] = $linkRenderer->makeKnownLink( |
||
242 | $this->getPageTitle( 'delete' ), |
||
243 | $this->msg( 'tags-delete' )->text(), |
||
244 | [], |
||
245 | [ 'tag' => $tag ] ); |
||
246 | } |
||
247 | |||
248 | if ( $showManageActions ) { // we've already checked that the user had the requisite userright |
||
249 | |||
250 | // activate |
||
251 | if ( ChangeTags::canActivateTag( $tag )->isOK() ) { |
||
252 | $actionLinks[] = $linkRenderer->makeKnownLink( |
||
253 | $this->getPageTitle( 'activate' ), |
||
254 | $this->msg( 'tags-activate' )->text(), |
||
255 | [], |
||
256 | [ 'tag' => $tag ] ); |
||
257 | } |
||
258 | |||
259 | // deactivate |
||
260 | if ( ChangeTags::canDeactivateTag( $tag )->isOK() ) { |
||
261 | $actionLinks[] = $linkRenderer->makeKnownLink( |
||
262 | $this->getPageTitle( 'deactivate' ), |
||
263 | $this->msg( 'tags-deactivate' )->text(), |
||
264 | [], |
||
265 | [ 'tag' => $tag ] ); |
||
266 | } |
||
267 | |||
268 | } |
||
269 | |||
270 | if ( $showDeleteActions || $showManageActions ) { |
||
271 | $newRow .= Xml::tags( 'td', null, $this->getLanguage()->pipeList( $actionLinks ) ); |
||
272 | } |
||
273 | |||
274 | return Xml::tags( 'tr', null, $newRow ) . "\n"; |
||
275 | } |
||
276 | |||
277 | public function processCreateTagForm( array $data, HTMLForm $form ) { |
||
278 | $context = $form->getContext(); |
||
279 | $out = $context->getOutput(); |
||
280 | |||
281 | $tag = trim( strval( $data['Tag'] ) ); |
||
282 | $ignoreWarnings = isset( $data['IgnoreWarnings'] ) && $data['IgnoreWarnings'] === '1'; |
||
283 | $status = ChangeTags::createTagWithChecks( $tag, $data['Reason'], |
||
284 | $context->getUser(), $ignoreWarnings ); |
||
285 | |||
286 | if ( $status->isGood() ) { |
||
287 | $out->redirect( $this->getPageTitle()->getLocalURL() ); |
||
288 | return true; |
||
289 | } elseif ( $status->isOK() ) { |
||
290 | // we have some warnings, so we show a confirmation form |
||
291 | $fields = [ |
||
292 | 'Tag' => [ |
||
293 | 'type' => 'hidden', |
||
294 | 'default' => $data['Tag'], |
||
295 | ], |
||
296 | 'Reason' => [ |
||
297 | 'type' => 'hidden', |
||
298 | 'default' => $data['Reason'], |
||
299 | ], |
||
300 | 'IgnoreWarnings' => [ |
||
301 | 'type' => 'hidden', |
||
302 | 'default' => '1', |
||
303 | ], |
||
304 | ]; |
||
305 | |||
306 | // fool HTMLForm into thinking the form hasn't been submitted yet. Otherwise |
||
307 | // we get into an infinite loop! |
||
308 | $context->getRequest()->unsetVal( 'wpEditToken' ); |
||
309 | |||
310 | $headerText = $this->msg( 'tags-create-warnings-above', $tag, |
||
311 | count( $status->getWarningsArray() ) )->parseAsBlock() . |
||
312 | $out->parse( $status->getWikiText() ) . |
||
313 | $this->msg( 'tags-create-warnings-below' )->parseAsBlock(); |
||
314 | |||
315 | $subform = new HTMLForm( $fields, $this->getContext() ); |
||
316 | $subform->setAction( $this->getPageTitle( 'create' )->getLocalURL() ); |
||
317 | $subform->setWrapperLegendMsg( 'tags-create-heading' ); |
||
318 | $subform->setHeaderText( $headerText ); |
||
319 | $subform->setSubmitCallback( [ $this, 'processCreateTagForm' ] ); |
||
320 | $subform->setSubmitTextMsg( 'htmlform-yes' ); |
||
321 | $subform->show(); |
||
322 | |||
323 | $out->addBacklinkSubtitle( $this->getPageTitle() ); |
||
324 | return true; |
||
325 | } else { |
||
326 | $out->addWikiText( "<div class=\"error\">\n" . $status->getWikiText() . |
||
327 | "\n</div>" ); |
||
328 | return false; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | protected function showDeleteTagForm( $tag ) { |
||
333 | $user = $this->getUser(); |
||
334 | if ( !$user->isAllowed( 'deletechangetags' ) ) { |
||
335 | throw new PermissionsError( 'deletechangetags' ); |
||
336 | } |
||
337 | |||
338 | $out = $this->getOutput(); |
||
339 | $out->setPageTitle( $this->msg( 'tags-delete-title' ) ); |
||
340 | $out->addBacklinkSubtitle( $this->getPageTitle() ); |
||
341 | |||
342 | // is the tag actually able to be deleted? |
||
343 | $canDeleteResult = ChangeTags::canDeleteTag( $tag, $user ); |
||
344 | if ( !$canDeleteResult->isGood() ) { |
||
345 | $out->addWikiText( "<div class=\"error\">\n" . $canDeleteResult->getWikiText() . |
||
346 | "\n</div>" ); |
||
347 | if ( !$canDeleteResult->isOK() ) { |
||
348 | return; |
||
349 | } |
||
350 | } |
||
351 | |||
352 | $preText = $this->msg( 'tags-delete-explanation-initial', $tag )->parseAsBlock(); |
||
353 | $tagUsage = ChangeTags::tagUsageStatistics(); |
||
354 | if ( isset( $tagUsage[$tag] ) && $tagUsage[$tag] > 0 ) { |
||
355 | $preText .= $this->msg( 'tags-delete-explanation-in-use', $tag, |
||
356 | $tagUsage[$tag] )->parseAsBlock(); |
||
357 | } |
||
358 | $preText .= $this->msg( 'tags-delete-explanation-warning', $tag )->parseAsBlock(); |
||
359 | |||
360 | // see if the tag is in use |
||
361 | $this->softwareActivatedTags = array_fill_keys( |
||
362 | ChangeTags::listSoftwareActivatedTags(), true ); |
||
363 | if ( isset( $this->softwareActivatedTags[$tag] ) ) { |
||
364 | $preText .= $this->msg( 'tags-delete-explanation-active', $tag )->parseAsBlock(); |
||
365 | } |
||
366 | |||
367 | $fields = []; |
||
368 | $fields['Reason'] = [ |
||
369 | 'type' => 'text', |
||
370 | 'label' => $this->msg( 'tags-delete-reason' )->plain(), |
||
371 | 'size' => 50, |
||
372 | ]; |
||
373 | $fields['HiddenTag'] = [ |
||
374 | 'type' => 'hidden', |
||
375 | 'name' => 'tag', |
||
376 | 'default' => $tag, |
||
377 | 'required' => true, |
||
378 | ]; |
||
379 | |||
380 | $form = new HTMLForm( $fields, $this->getContext() ); |
||
381 | $form->setAction( $this->getPageTitle( 'delete' )->getLocalURL() ); |
||
382 | $form->tagAction = 'delete'; // custom property on HTMLForm object |
||
383 | $form->setSubmitCallback( [ $this, 'processTagForm' ] ); |
||
384 | $form->setSubmitTextMsg( 'tags-delete-submit' ); |
||
385 | $form->setSubmitDestructive(); // nasty! |
||
386 | $form->addPreText( $preText ); |
||
387 | $form->show(); |
||
388 | } |
||
389 | |||
390 | protected function showActivateDeactivateForm( $tag, $activate ) { |
||
391 | $actionStr = $activate ? 'activate' : 'deactivate'; |
||
392 | |||
393 | $user = $this->getUser(); |
||
394 | if ( !$user->isAllowed( 'managechangetags' ) ) { |
||
395 | throw new PermissionsError( 'managechangetags' ); |
||
396 | } |
||
397 | |||
398 | $out = $this->getOutput(); |
||
399 | // tags-activate-title, tags-deactivate-title |
||
400 | $out->setPageTitle( $this->msg( "tags-$actionStr-title" ) ); |
||
401 | $out->addBacklinkSubtitle( $this->getPageTitle() ); |
||
402 | |||
403 | // is it possible to do this? |
||
404 | $func = $activate ? 'canActivateTag' : 'canDeactivateTag'; |
||
405 | $result = ChangeTags::$func( $tag, $user ); |
||
406 | if ( !$result->isGood() ) { |
||
407 | $out->addWikiText( "<div class=\"error\">\n" . $result->getWikiText() . |
||
408 | "\n</div>" ); |
||
409 | if ( !$result->isOK() ) { |
||
410 | return; |
||
411 | } |
||
412 | } |
||
413 | |||
414 | // tags-activate-question, tags-deactivate-question |
||
415 | $preText = $this->msg( "tags-$actionStr-question", $tag )->parseAsBlock(); |
||
416 | |||
417 | $fields = []; |
||
418 | // tags-activate-reason, tags-deactivate-reason |
||
419 | $fields['Reason'] = [ |
||
420 | 'type' => 'text', |
||
421 | 'label' => $this->msg( "tags-$actionStr-reason" )->plain(), |
||
422 | 'size' => 50, |
||
423 | ]; |
||
424 | $fields['HiddenTag'] = [ |
||
425 | 'type' => 'hidden', |
||
426 | 'name' => 'tag', |
||
427 | 'default' => $tag, |
||
428 | 'required' => true, |
||
429 | ]; |
||
430 | |||
431 | $form = new HTMLForm( $fields, $this->getContext() ); |
||
432 | $form->setAction( $this->getPageTitle( $actionStr )->getLocalURL() ); |
||
433 | $form->tagAction = $actionStr; |
||
434 | $form->setSubmitCallback( [ $this, 'processTagForm' ] ); |
||
435 | // tags-activate-submit, tags-deactivate-submit |
||
436 | $form->setSubmitTextMsg( "tags-$actionStr-submit" ); |
||
437 | $form->addPreText( $preText ); |
||
438 | $form->show(); |
||
439 | } |
||
440 | |||
441 | public function processTagForm( array $data, HTMLForm $form ) { |
||
442 | $context = $form->getContext(); |
||
443 | $out = $context->getOutput(); |
||
444 | |||
445 | $tag = $data['HiddenTag']; |
||
446 | $status = call_user_func( [ 'ChangeTags', "{$form->tagAction}TagWithChecks" ], |
||
447 | $tag, $data['Reason'], $context->getUser(), true ); |
||
448 | |||
449 | if ( $status->isGood() ) { |
||
450 | $out->redirect( $this->getPageTitle()->getLocalURL() ); |
||
451 | return true; |
||
452 | } elseif ( $status->isOK() && $form->tagAction === 'delete' ) { |
||
453 | // deletion succeeded, but hooks raised a warning |
||
454 | $out->addWikiText( $this->msg( 'tags-delete-warnings-after-delete', $tag, |
||
455 | count( $status->getWarningsArray() ) )->text() . "\n" . |
||
456 | $status->getWikitext() ); |
||
457 | $out->addReturnTo( $this->getPageTitle() ); |
||
458 | return true; |
||
459 | } else { |
||
460 | $out->addWikiText( "<div class=\"error\">\n" . $status->getWikitext() . |
||
461 | "\n</div>" ); |
||
462 | return false; |
||
463 | } |
||
464 | } |
||
465 | |||
466 | /** |
||
467 | * Return an array of subpages that this special page will accept. |
||
468 | * |
||
469 | * @return string[] subpages |
||
470 | */ |
||
471 | public function getSubpagesForPrefixSearch() { |
||
472 | // The subpages does not have an own form, so not listing it at the moment |
||
473 | return [ |
||
474 | // 'delete', |
||
475 | // 'activate', |
||
476 | // 'deactivate', |
||
477 | // 'create', |
||
478 | ]; |
||
479 | } |
||
480 | |||
481 | protected function getGroupName() { |
||
482 | return 'changes'; |
||
483 | } |
||
484 | } |
||
485 |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.