MediaWiki  1.32.0
HTMLFormField.php
Go to the documentation of this file.
1 <?php
2 
7 abstract class HTMLFormField {
8  public $mParams;
9 
11  protected $mFilterCallback;
12  protected $mName;
13  protected $mDir;
14  protected $mLabel; # String label, as HTML. Set on construction.
15  protected $mID;
16  protected $mClass = '';
17  protected $mVFormClass = '';
18  protected $mHelpClass = false;
19  protected $mDefault;
23  protected $mOptions = false;
24  protected $mOptionsLabelsNotFromMessage = false;
25  protected $mHideIf = null;
26 
31  protected $mShowEmptyLabels = true;
32 
36  public $mParent;
37 
48  abstract public function getInputHTML( $value );
49 
57  public function getInputOOUI( $value ) {
58  return false;
59  }
60 
66  public function canDisplayErrors() {
67  return $this->hasVisibleOutput();
68  }
69 
80  public function msg() {
81  $args = func_get_args();
82 
83  if ( $this->mParent ) {
84  return $this->mParent->msg( ...$args );
85  }
86  return wfMessage( ...$args );
87  }
88 
95  public function hasVisibleOutput() {
96  return true;
97  }
98 
112  protected function getNearestFieldByName( $alldata, $name ) {
113  $tmp = $this->mName;
114  $thisKeys = [];
115  while ( preg_match( '/^(.+)\[([^\]]+)\]$/', $tmp, $m ) ) {
116  array_unshift( $thisKeys, $m[2] );
117  $tmp = $m[1];
118  }
119  if ( substr( $tmp, 0, 2 ) == 'wp' &&
120  !array_key_exists( $tmp, $alldata ) &&
121  array_key_exists( substr( $tmp, 2 ), $alldata )
122  ) {
123  // Adjust for name mangling.
124  $tmp = substr( $tmp, 2 );
125  }
126  array_unshift( $thisKeys, $tmp );
127 
128  $tmp = $name;
129  $nameKeys = [];
130  while ( preg_match( '/^(.+)\[([^\]]+)\]$/', $tmp, $m ) ) {
131  array_unshift( $nameKeys, $m[2] );
132  $tmp = $m[1];
133  }
134  array_unshift( $nameKeys, $tmp );
135 
136  $testValue = '';
137  for ( $i = count( $thisKeys ) - 1; $i >= 0; $i-- ) {
138  $keys = array_merge( array_slice( $thisKeys, 0, $i ), $nameKeys );
139  $data = $alldata;
140  while ( $keys ) {
141  $key = array_shift( $keys );
142  if ( !is_array( $data ) || !array_key_exists( $key, $data ) ) {
143  continue 2;
144  }
145  $data = $data[$key];
146  }
147  $testValue = (string)$data;
148  break;
149  }
150 
151  return $testValue;
152  }
153 
162  protected function isHiddenRecurse( array $alldata, array $params ) {
163  $origParams = $params;
164  $op = array_shift( $params );
165 
166  try {
167  switch ( $op ) {
168  case 'AND':
169  foreach ( $params as $i => $p ) {
170  if ( !is_array( $p ) ) {
171  throw new MWException(
172  "Expected array, found " . gettype( $p ) . " at index $i"
173  );
174  }
175  if ( !$this->isHiddenRecurse( $alldata, $p ) ) {
176  return false;
177  }
178  }
179  return true;
180 
181  case 'OR':
182  foreach ( $params as $i => $p ) {
183  if ( !is_array( $p ) ) {
184  throw new MWException(
185  "Expected array, found " . gettype( $p ) . " at index $i"
186  );
187  }
188  if ( $this->isHiddenRecurse( $alldata, $p ) ) {
189  return true;
190  }
191  }
192  return false;
193 
194  case 'NAND':
195  foreach ( $params as $i => $p ) {
196  if ( !is_array( $p ) ) {
197  throw new MWException(
198  "Expected array, found " . gettype( $p ) . " at index $i"
199  );
200  }
201  if ( !$this->isHiddenRecurse( $alldata, $p ) ) {
202  return true;
203  }
204  }
205  return false;
206 
207  case 'NOR':
208  foreach ( $params as $i => $p ) {
209  if ( !is_array( $p ) ) {
210  throw new MWException(
211  "Expected array, found " . gettype( $p ) . " at index $i"
212  );
213  }
214  if ( $this->isHiddenRecurse( $alldata, $p ) ) {
215  return false;
216  }
217  }
218  return true;
219 
220  case 'NOT':
221  if ( count( $params ) !== 1 ) {
222  throw new MWException( "NOT takes exactly one parameter" );
223  }
224  $p = $params[0];
225  if ( !is_array( $p ) ) {
226  throw new MWException(
227  "Expected array, found " . gettype( $p ) . " at index 0"
228  );
229  }
230  return !$this->isHiddenRecurse( $alldata, $p );
231 
232  case '===':
233  case '!==':
234  if ( count( $params ) !== 2 ) {
235  throw new MWException( "$op takes exactly two parameters" );
236  }
237  list( $field, $value ) = $params;
238  if ( !is_string( $field ) || !is_string( $value ) ) {
239  throw new MWException( "Parameters for $op must be strings" );
240  }
241  $testValue = $this->getNearestFieldByName( $alldata, $field );
242  switch ( $op ) {
243  case '===':
244  return ( $value === $testValue );
245  case '!==':
246  return ( $value !== $testValue );
247  }
248 
249  default:
250  throw new MWException( "Unknown operation" );
251  }
252  } catch ( Exception $ex ) {
253  throw new MWException(
254  "Invalid hide-if specification for $this->mName: " .
255  $ex->getMessage() . " in " . var_export( $origParams, true ),
256  0, $ex
257  );
258  }
259  }
260 
269  public function isHidden( $alldata ) {
270  if ( !$this->mHideIf ) {
271  return false;
272  }
273 
274  return $this->isHiddenRecurse( $alldata, $this->mHideIf );
275  }
276 
287  public function cancelSubmit( $value, $alldata ) {
288  return false;
289  }
290 
302  public function validate( $value, $alldata ) {
303  if ( $this->isHidden( $alldata ) ) {
304  return true;
305  }
306 
307  if ( isset( $this->mParams['required'] )
308  && $this->mParams['required'] !== false
309  && $value === ''
310  ) {
311  return $this->msg( 'htmlform-required' );
312  }
313 
314  if ( isset( $this->mValidationCallback ) ) {
315  return ( $this->mValidationCallback )( $value, $alldata, $this->mParent );
316  }
317 
318  return true;
319  }
320 
321  public function filter( $value, $alldata ) {
322  if ( isset( $this->mFilterCallback ) ) {
323  $value = ( $this->mFilterCallback )( $value, $alldata, $this->mParent );
324  }
325 
326  return $value;
327  }
328 
335  protected function needsLabel() {
336  return true;
337  }
338 
348  public function setShowEmptyLabel( $show ) {
349  $this->mShowEmptyLabels = $show;
350  }
351 
362  protected function isSubmitAttempt( WebRequest $request ) {
363  return $request->getCheck( 'wpEditToken' ) || $request->getCheck( 'wpFormIdentifier' );
364  }
365 
373  public function loadDataFromRequest( $request ) {
374  if ( $request->getCheck( $this->mName ) ) {
375  return $request->getText( $this->mName );
376  } else {
377  return $this->getDefault();
378  }
379  }
380 
389  public function __construct( $params ) {
390  $this->mParams = $params;
391 
392  if ( isset( $params['parent'] ) && $params['parent'] instanceof HTMLForm ) {
393  $this->mParent = $params['parent'];
394  }
395 
396  # Generate the label from a message, if possible
397  if ( isset( $params['label-message'] ) ) {
398  $this->mLabel = $this->getMessage( $params['label-message'] )->parse();
399  } elseif ( isset( $params['label'] ) ) {
400  if ( $params['label'] === '&#160;' || $params['label'] === "\u{00A0}" ) {
401  // Apparently some things set &nbsp directly and in an odd format
402  $this->mLabel = "\u{00A0}";
403  } else {
404  $this->mLabel = htmlspecialchars( $params['label'] );
405  }
406  } elseif ( isset( $params['label-raw'] ) ) {
407  $this->mLabel = $params['label-raw'];
408  }
409 
410  $this->mName = "wp{$params['fieldname']}";
411  if ( isset( $params['name'] ) ) {
412  $this->mName = $params['name'];
413  }
414 
415  if ( isset( $params['dir'] ) ) {
416  $this->mDir = $params['dir'];
417  }
418 
419  $validName = urlencode( $this->mName );
420  $validName = str_replace( [ '%5B', '%5D' ], [ '[', ']' ], $validName );
421  if ( $this->mName != $validName && !isset( $params['nodata'] ) ) {
422  throw new MWException( "Invalid name '{$this->mName}' passed to " . __METHOD__ );
423  }
424 
425  $this->mID = "mw-input-{$this->mName}";
426 
427  if ( isset( $params['default'] ) ) {
428  $this->mDefault = $params['default'];
429  }
430 
431  if ( isset( $params['id'] ) ) {
432  $id = $params['id'];
433  $validId = urlencode( $id );
434 
435  if ( $id != $validId ) {
436  throw new MWException( "Invalid id '$id' passed to " . __METHOD__ );
437  }
438 
439  $this->mID = $id;
440  }
441 
442  if ( isset( $params['cssclass'] ) ) {
443  $this->mClass = $params['cssclass'];
444  }
445 
446  if ( isset( $params['csshelpclass'] ) ) {
447  $this->mHelpClass = $params['csshelpclass'];
448  }
449 
450  if ( isset( $params['validation-callback'] ) ) {
451  $this->mValidationCallback = $params['validation-callback'];
452  }
453 
454  if ( isset( $params['filter-callback'] ) ) {
455  $this->mFilterCallback = $params['filter-callback'];
456  }
457 
458  if ( isset( $params['hidelabel'] ) ) {
459  $this->mShowEmptyLabels = false;
460  }
461 
462  if ( isset( $params['hide-if'] ) ) {
463  $this->mHideIf = $params['hide-if'];
464  }
465 
466  if ( isset( $this->mParams['notice-message'] ) ) {
467  wfDeprecated( "'notice-message' parameter in HTMLForm", '1.32' );
468  }
469  if ( isset( $this->mParams['notice-messages'] ) ) {
470  wfDeprecated( "'notice-messages' parameter in HTMLForm", '1.32' );
471  }
472  if ( isset( $this->mParams['notice'] ) ) {
473  wfDeprecated( "'notice' parameter in HTMLForm", '1.32' );
474  }
475  }
476 
485  public function getTableRow( $value ) {
486  list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
487  $inputHtml = $this->getInputHTML( $value );
488  $fieldType = static::class;
489  $helptext = $this->getHelpTextHtmlTable( $this->getHelpText() );
490  $cellAttributes = [];
491  $rowAttributes = [];
492  $rowClasses = '';
493 
494  if ( !empty( $this->mParams['vertical-label'] ) ) {
495  $cellAttributes['colspan'] = 2;
496  $verticalLabel = true;
497  } else {
498  $verticalLabel = false;
499  }
500 
501  $label = $this->getLabelHtml( $cellAttributes );
502 
503  $field = Html::rawElement(
504  'td',
505  [ 'class' => 'mw-input' ] + $cellAttributes,
506  $inputHtml . "\n$errors"
507  );
508 
509  if ( $this->mHideIf ) {
510  $rowAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
511  $rowClasses .= ' mw-htmlform-hide-if';
512  }
513 
514  if ( $verticalLabel ) {
515  $html = Html::rawElement( 'tr',
516  $rowAttributes + [ 'class' => "mw-htmlform-vertical-label $rowClasses" ], $label );
517  $html .= Html::rawElement( 'tr',
518  $rowAttributes + [
519  'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
520  ],
521  $field );
522  } else {
523  $html =
524  Html::rawElement( 'tr',
525  $rowAttributes + [
526  'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
527  ],
528  $label . $field );
529  }
530 
531  return $html . $helptext;
532  }
533 
543  public function getDiv( $value ) {
544  list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
545  $inputHtml = $this->getInputHTML( $value );
546  $fieldType = static::class;
547  $helptext = $this->getHelpTextHtmlDiv( $this->getHelpText() );
548  $cellAttributes = [];
549  $label = $this->getLabelHtml( $cellAttributes );
550 
551  $outerDivClass = [
552  'mw-input',
553  'mw-htmlform-nolabel' => ( $label === '' )
554  ];
555 
556  $horizontalLabel = $this->mParams['horizontal-label'] ?? false;
557 
558  if ( $horizontalLabel ) {
559  $field = "\u{00A0}" . $inputHtml . "\n$errors";
560  } else {
561  $field = Html::rawElement(
562  'div',
563  [ 'class' => $outerDivClass ] + $cellAttributes,
564  $inputHtml . "\n$errors"
565  );
566  }
567  $divCssClasses = [ "mw-htmlform-field-$fieldType",
568  $this->mClass, $this->mVFormClass, $errorClass ];
569 
570  $wrapperAttributes = [
571  'class' => $divCssClasses,
572  ];
573  if ( $this->mHideIf ) {
574  $wrapperAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
575  $wrapperAttributes['class'][] = ' mw-htmlform-hide-if';
576  }
577  $html = Html::rawElement( 'div', $wrapperAttributes, $label . $field );
578  $html .= $helptext;
579 
580  return $html;
581  }
582 
591  public function getOOUI( $value ) {
592  $inputField = $this->getInputOOUI( $value );
593 
594  if ( !$inputField ) {
595  // This field doesn't have an OOUI implementation yet at all. Fall back to getDiv() to
596  // generate the whole field, label and errors and all, then wrap it in a Widget.
597  // It might look weird, but it'll work OK.
598  return $this->getFieldLayoutOOUI(
599  new OOUI\Widget( [ 'content' => new OOUI\HtmlSnippet( $this->getDiv( $value ) ) ] ),
600  [ 'infusable' => false, 'align' => 'top' ]
601  );
602  }
603 
604  $infusable = true;
605  if ( is_string( $inputField ) ) {
606  // We have an OOUI implementation, but it's not proper, and we got a load of HTML.
607  // Cheat a little and wrap it in a widget. It won't be infusable, though, since client-side
608  // JavaScript doesn't know how to rebuilt the contents.
609  $inputField = new OOUI\Widget( [ 'content' => new OOUI\HtmlSnippet( $inputField ) ] );
610  $infusable = false;
611  }
612 
613  $fieldType = static::class;
614  $help = $this->getHelpText();
615  $errors = $this->getErrorsRaw( $value );
616  foreach ( $errors as &$error ) {
617  $error = new OOUI\HtmlSnippet( $error );
618  }
619 
620  $notices = $this->getNotices( 'skip deprecation' );
621  foreach ( $notices as &$notice ) {
622  $notice = new OOUI\HtmlSnippet( $notice );
623  }
624 
625  $config = [
626  'classes' => [ "mw-htmlform-field-$fieldType", $this->mClass ],
627  'align' => $this->getLabelAlignOOUI(),
628  'help' => ( $help !== null && $help !== '' ) ? new OOUI\HtmlSnippet( $help ) : null,
629  'errors' => $errors,
630  'notices' => $notices,
631  'infusable' => $infusable,
632  'helpInline' => $this->isHelpInline(),
633  ];
634 
635  $preloadModules = false;
636 
637  if ( $infusable && $this->shouldInfuseOOUI() ) {
638  $preloadModules = true;
639  $config['classes'][] = 'mw-htmlform-field-autoinfuse';
640  }
641 
642  // the element could specify, that the label doesn't need to be added
643  $label = $this->getLabel();
644  if ( $label && $label !== "\u{00A0}" && $label !== '&#160;' ) {
645  $config['label'] = new OOUI\HtmlSnippet( $label );
646  }
647 
648  if ( $this->mHideIf ) {
649  $preloadModules = true;
650  $config['hideIf'] = $this->mHideIf;
651  }
652 
653  $config['modules'] = $this->getOOUIModules();
654 
655  if ( $preloadModules ) {
656  $this->mParent->getOutput()->addModules( 'mediawiki.htmlform.ooui' );
657  $this->mParent->getOutput()->addModules( $this->getOOUIModules() );
658  }
659 
660  return $this->getFieldLayoutOOUI( $inputField, $config );
661  }
662 
667  protected function getLabelAlignOOUI() {
668  return 'top';
669  }
670 
677  protected function getFieldLayoutOOUI( $inputField, $config ) {
678  if ( isset( $this->mClassWithButton ) ) {
679  $buttonWidget = $this->mClassWithButton->getInputOOUI( '' );
680  return new HTMLFormActionFieldLayout( $inputField, $buttonWidget, $config );
681  }
682  return new HTMLFormFieldLayout( $inputField, $config );
683  }
684 
692  protected function shouldInfuseOOUI() {
693  // Always infuse fields with popup help text, since the interface for it is nicer with JS
694  return $this->getHelpText() !== null && !$this->isHelpInline();
695  }
696 
703  protected function getOOUIModules() {
704  return [];
705  }
706 
716  public function getRaw( $value ) {
717  list( $errors, ) = $this->getErrorsAndErrorClass( $value );
718  $inputHtml = $this->getInputHTML( $value );
719  $helptext = $this->getHelpTextHtmlRaw( $this->getHelpText() );
720  $cellAttributes = [];
721  $label = $this->getLabelHtml( $cellAttributes );
722 
723  $html = "\n$errors";
724  $html .= $label;
725  $html .= $inputHtml;
726  $html .= $helptext;
727 
728  return $html;
729  }
730 
739  public function getVForm( $value ) {
740  // Ewwww
741  $this->mVFormClass = ' mw-ui-vform-field';
742  return $this->getDiv( $value );
743  }
744 
751  public function getInline( $value ) {
752  list( $errors, $errorClass ) = $this->getErrorsAndErrorClass( $value );
753  $inputHtml = $this->getInputHTML( $value );
754  $helptext = $this->getHelpTextHtmlDiv( $this->getHelpText() );
755  $cellAttributes = [];
756  $label = $this->getLabelHtml( $cellAttributes );
757 
758  $html = "\n" . $errors .
759  $label . "\u{00A0}" .
760  $inputHtml .
761  $helptext;
762 
763  return $html;
764  }
765 
773  public function getHelpTextHtmlTable( $helptext ) {
774  if ( is_null( $helptext ) ) {
775  return '';
776  }
777 
778  $rowAttributes = [];
779  if ( $this->mHideIf ) {
780  $rowAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
781  $rowAttributes['class'] = 'mw-htmlform-hide-if';
782  }
783 
784  $tdClasses = [ 'htmlform-tip' ];
785  if ( $this->mHelpClass !== false ) {
786  $tdClasses[] = $this->mHelpClass;
787  }
788  $row = Html::rawElement( 'td', [ 'colspan' => 2, 'class' => $tdClasses ], $helptext );
789  $row = Html::rawElement( 'tr', $rowAttributes, $row );
790 
791  return $row;
792  }
793 
802  public function getHelpTextHtmlDiv( $helptext ) {
803  if ( is_null( $helptext ) ) {
804  return '';
805  }
806 
807  $wrapperAttributes = [
808  'class' => 'htmlform-tip',
809  ];
810  if ( $this->mHelpClass !== false ) {
811  $wrapperAttributes['class'] .= " {$this->mHelpClass}";
812  }
813  if ( $this->mHideIf ) {
814  $wrapperAttributes['data-hide-if'] = FormatJson::encode( $this->mHideIf );
815  $wrapperAttributes['class'] .= ' mw-htmlform-hide-if';
816  }
817  $div = Html::rawElement( 'div', $wrapperAttributes, $helptext );
818 
819  return $div;
820  }
821 
829  public function getHelpTextHtmlRaw( $helptext ) {
830  return $this->getHelpTextHtmlDiv( $helptext );
831  }
832 
838  public function getHelpText() {
839  $helptext = null;
840 
841  if ( isset( $this->mParams['help-message'] ) ) {
842  $this->mParams['help-messages'] = [ $this->mParams['help-message'] ];
843  }
844 
845  if ( isset( $this->mParams['help-messages'] ) ) {
846  foreach ( $this->mParams['help-messages'] as $msg ) {
847  $msg = $this->getMessage( $msg );
848 
849  if ( $msg->exists() ) {
850  if ( is_null( $helptext ) ) {
851  $helptext = '';
852  } else {
853  $helptext .= $this->msg( 'word-separator' )->escaped(); // some space
854  }
855  $helptext .= $msg->parse(); // Append message
856  }
857  }
858  } elseif ( isset( $this->mParams['help'] ) ) {
859  $helptext = $this->mParams['help'];
860  }
861 
862  return $helptext;
863  }
864 
873  public function isHelpInline() {
874  return $this->mParams['help-inline'] ?? true;
875  }
876 
889  public function getErrorsAndErrorClass( $value ) {
890  $errors = $this->validate( $value, $this->mParent->mFieldData );
891 
892  if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
893  $errors = '';
894  $errorClass = '';
895  } else {
896  $errors = self::formatErrors( $errors );
897  $errorClass = 'mw-htmlform-invalid-input';
898  }
899 
900  return [ $errors, $errorClass ];
901  }
902 
910  public function getErrorsRaw( $value ) {
911  $errors = $this->validate( $value, $this->mParent->mFieldData );
912 
913  if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
914  $errors = [];
915  }
916 
917  if ( !is_array( $errors ) ) {
918  $errors = [ $errors ];
919  }
920  foreach ( $errors as &$error ) {
921  if ( $error instanceof Message ) {
922  $error = $error->parse();
923  }
924  }
925 
926  return $errors;
927  }
928 
938  public function getNotices( $skipDeprecation = null ) {
939  if ( $skipDeprecation !== 'skip deprecation' ) {
940  wfDeprecated( __METHOD__, '1.32' );
941  }
942 
943  $notices = [];
944 
945  if ( isset( $this->mParams['notice-message'] ) ) {
946  $notices[] = $this->getMessage( $this->mParams['notice-message'] )->parse();
947  }
948 
949  if ( isset( $this->mParams['notice-messages'] ) ) {
950  foreach ( $this->mParams['notice-messages'] as $msg ) {
951  $notices[] = $this->getMessage( $msg )->parse();
952  }
953  } elseif ( isset( $this->mParams['notice'] ) ) {
954  $notices[] = $this->mParams['notice'];
955  }
956 
957  return $notices;
958  }
959 
963  public function getLabel() {
964  return $this->mLabel ?? '';
965  }
966 
967  public function getLabelHtml( $cellAttributes = [] ) {
968  # Don't output a for= attribute for labels with no associated input.
969  # Kind of hacky here, possibly we don't want these to be <label>s at all.
970  $for = [];
971 
972  if ( $this->needsLabel() ) {
973  $for['for'] = $this->mID;
974  }
975 
976  $labelValue = trim( $this->getLabel() );
977  $hasLabel = false;
978  if ( $labelValue !== "\u{00A0}" && $labelValue !== '&#160;' && $labelValue !== '' ) {
979  $hasLabel = true;
980  }
981 
982  $displayFormat = $this->mParent->getDisplayFormat();
983  $html = '';
984  $horizontalLabel = $this->mParams['horizontal-label'] ?? false;
985 
986  if ( $displayFormat === 'table' ) {
987  $html =
988  Html::rawElement( 'td',
989  [ 'class' => 'mw-label' ] + $cellAttributes,
990  Html::rawElement( 'label', $for, $labelValue ) );
991  } elseif ( $hasLabel || $this->mShowEmptyLabels ) {
992  if ( $displayFormat === 'div' && !$horizontalLabel ) {
993  $html =
994  Html::rawElement( 'div',
995  [ 'class' => 'mw-label' ] + $cellAttributes,
996  Html::rawElement( 'label', $for, $labelValue ) );
997  } else {
998  $html = Html::rawElement( 'label', $for, $labelValue );
999  }
1000  }
1001 
1002  return $html;
1003  }
1004 
1005  public function getDefault() {
1006  return $this->mDefault ?? null;
1007  }
1008 
1014  public function getTooltipAndAccessKey() {
1015  if ( empty( $this->mParams['tooltip'] ) ) {
1016  return [];
1017  }
1018 
1019  return Linker::tooltipAndAccesskeyAttribs( $this->mParams['tooltip'] );
1020  }
1021 
1027  public function getTooltipAndAccessKeyOOUI() {
1028  if ( empty( $this->mParams['tooltip'] ) ) {
1029  return [];
1030  }
1031 
1032  return [
1033  'title' => Linker::titleAttrib( $this->mParams['tooltip'] ),
1034  'accessKey' => Linker::accesskey( $this->mParams['tooltip'] ),
1035  ];
1036  }
1037 
1044  public function getAttributes( array $list ) {
1045  static $boolAttribs = [ 'disabled', 'required', 'autofocus', 'multiple', 'readonly' ];
1046 
1047  $ret = [];
1048  foreach ( $list as $key ) {
1049  if ( in_array( $key, $boolAttribs ) ) {
1050  if ( !empty( $this->mParams[$key] ) ) {
1051  $ret[$key] = '';
1052  }
1053  } elseif ( isset( $this->mParams[$key] ) ) {
1054  $ret[$key] = $this->mParams[$key];
1055  }
1056  }
1057 
1058  return $ret;
1059  }
1060 
1068  private function lookupOptionsKeys( $options ) {
1069  $ret = [];
1070  foreach ( $options as $key => $value ) {
1071  $key = $this->msg( $key )->plain();
1072  $ret[$key] = is_array( $value )
1073  ? $this->lookupOptionsKeys( $value )
1074  : strval( $value );
1075  }
1076  return $ret;
1077  }
1078 
1086  public static function forceToStringRecursive( $array ) {
1087  if ( is_array( $array ) ) {
1088  return array_map( [ __CLASS__, 'forceToStringRecursive' ], $array );
1089  } else {
1090  return strval( $array );
1091  }
1092  }
1093 
1100  public function getOptions() {
1101  if ( $this->mOptions === false ) {
1102  if ( array_key_exists( 'options-messages', $this->mParams ) ) {
1103  $this->mOptions = $this->lookupOptionsKeys( $this->mParams['options-messages'] );
1104  } elseif ( array_key_exists( 'options', $this->mParams ) ) {
1105  $this->mOptionsLabelsNotFromMessage = true;
1106  $this->mOptions = self::forceToStringRecursive( $this->mParams['options'] );
1107  } elseif ( array_key_exists( 'options-message', $this->mParams ) ) {
1108  $message = $this->getMessage( $this->mParams['options-message'] )->inContentLanguage()->plain();
1109  $this->mOptions = Xml::listDropDownOptions( $message );
1110  } else {
1111  $this->mOptions = null;
1112  }
1113  }
1114 
1115  return $this->mOptions;
1116  }
1117 
1122  public function getOptionsOOUI() {
1123  $oldoptions = $this->getOptions();
1124 
1125  if ( $oldoptions === null ) {
1126  return null;
1127  }
1128 
1129  return Xml::listDropDownOptionsOoui( $oldoptions );
1130  }
1131 
1139  public static function flattenOptions( $options ) {
1140  $flatOpts = [];
1141 
1142  foreach ( $options as $value ) {
1143  if ( is_array( $value ) ) {
1144  $flatOpts = array_merge( $flatOpts, self::flattenOptions( $value ) );
1145  } else {
1146  $flatOpts[] = $value;
1147  }
1148  }
1149 
1150  return $flatOpts;
1151  }
1152 
1166  protected static function formatErrors( $errors ) {
1167  // Note: If you change the logic in this method, change
1168  // htmlform.Checker.js to match.
1169 
1170  if ( is_array( $errors ) && count( $errors ) === 1 ) {
1171  $errors = array_shift( $errors );
1172  }
1173 
1174  if ( is_array( $errors ) ) {
1175  $lines = [];
1176  foreach ( $errors as $error ) {
1177  if ( $error instanceof Message ) {
1178  $lines[] = Html::rawElement( 'li', [], $error->parse() );
1179  } else {
1180  $lines[] = Html::rawElement( 'li', [], $error );
1181  }
1182  }
1183 
1184  return Html::rawElement( 'ul', [ 'class' => 'error' ], implode( "\n", $lines ) );
1185  } else {
1186  if ( $errors instanceof Message ) {
1187  $errors = $errors->parse();
1188  }
1189 
1190  return Html::rawElement( 'span', [ 'class' => 'error' ], $errors );
1191  }
1192  }
1193 
1200  protected function getMessage( $value ) {
1201  $message = Message::newFromSpecifier( $value );
1202 
1203  if ( $this->mParent ) {
1204  $message->setContext( $this->mParent );
1205  }
1206 
1207  return $message;
1208  }
1209 
1216  public function skipLoadData( $request ) {
1217  return !empty( $this->mParams['nodata'] );
1218  }
1219 
1227  public function needsJSForHtml5FormValidation() {
1228  if ( $this->mHideIf ) {
1229  // This is probably more restrictive than it needs to be, but better safe than sorry
1230  return true;
1231  }
1232  return false;
1233  }
1234 }
HTMLFormField\getOptions
getOptions()
Fetch the array of options from the field's parameters.
Definition: HTMLFormField.php:1100
HTMLFormField\getNotices
getNotices( $skipDeprecation=null)
Determine notices to display for the field.
Definition: HTMLFormField.php:938
HTMLFormField\__construct
__construct( $params)
Initialise the object.
Definition: HTMLFormField.php:389
HTMLFormField\$mHelpClass
$mHelpClass
Definition: HTMLFormField.php:18
HTMLFormField\getTooltipAndAccessKeyOOUI
getTooltipAndAccessKeyOOUI()
Returns the attributes required for the tooltip and accesskey, for OOUI widgets' config.
Definition: HTMLFormField.php:1027
HTMLFormField\$mLabel
$mLabel
Definition: HTMLFormField.php:14
HTMLFormField\isHiddenRecurse
isHiddenRecurse(array $alldata, array $params)
Helper function for isHidden to handle recursive data structures.
Definition: HTMLFormField.php:162
Xml\listDropDownOptionsOoui
static listDropDownOptionsOoui( $options)
Convert options for a drop-down box into a format accepted by OOUI\DropdownInputWidget etc.
Definition: Xml.php:583
HTMLFormField\setShowEmptyLabel
setShowEmptyLabel( $show)
Tell the field whether to generate a separate label element if its label is blank.
Definition: HTMLFormField.php:348
captcha-old.count
count
Definition: captcha-old.py:249
HTMLFormField\getErrorsAndErrorClass
getErrorsAndErrorClass( $value)
Determine form errors to display and their classes.
Definition: HTMLFormField.php:889
HTMLFormField\validate
validate( $value, $alldata)
Override this function to add specific validation checks on the field input.
Definition: HTMLFormField.php:302
HTMLFormActionFieldLayout
Definition: HTMLFormElement.php:52
$params
$params
Definition: styleTest.css.php:44
HTMLFormField\formatErrors
static formatErrors( $errors)
Formats one or more errors as accepted by field validation-callback.
Definition: HTMLFormField.php:1166
HTMLFormField\hasVisibleOutput
hasVisibleOutput()
If this field has a user-visible output or not.
Definition: HTMLFormField.php:95
HTMLFormField\getMessage
getMessage( $value)
Turns a *-message parameter (which could be a MessageSpecifier, or a message name,...
Definition: HTMLFormField.php:1200
HTMLFormField\getNearestFieldByName
getNearestFieldByName( $alldata, $name)
Fetch a field value from $alldata for the closest field matching a given name.
Definition: HTMLFormField.php:112
HTMLFormField\$mClass
$mClass
Definition: HTMLFormField.php:16
HTMLFormField\shouldInfuseOOUI
shouldInfuseOOUI()
Whether the field should be automatically infused.
Definition: HTMLFormField.php:692
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
HTMLFormField\needsLabel
needsLabel()
Should this field have a label, or is there no input element with the appropriate id for the label to...
Definition: HTMLFormField.php:335
Linker\tooltipAndAccesskeyAttribs
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition: Linker.php:2133
HTMLFormField\$mDir
$mDir
Definition: HTMLFormField.php:13
HTMLFormField\skipLoadData
skipLoadData( $request)
Skip this field when collecting data.
Definition: HTMLFormField.php:1216
HTMLFormField\$mOptions
array bool null $mOptions
Definition: HTMLFormField.php:23
HTMLFormField\getTableRow
getTableRow( $value)
Get the complete table row for the input, including help text, labels, and whatever.
Definition: HTMLFormField.php:485
HTMLFormField\cancelSubmit
cancelSubmit( $value, $alldata)
Override this function if the control can somehow trigger a form submission that shouldn't actually s...
Definition: HTMLFormField.php:287
HTMLFormField\getLabelHtml
getLabelHtml( $cellAttributes=[])
Definition: HTMLFormField.php:967
HTMLFormField\canDisplayErrors
canDisplayErrors()
True if this field type is able to display errors; false if validation errors need to be displayed in...
Definition: HTMLFormField.php:66
HTMLFormField\getHelpTextHtmlTable
getHelpTextHtmlTable( $helptext)
Generate help text HTML in table format.
Definition: HTMLFormField.php:773
HTMLFormField\$mParent
HTMLForm null $mParent
Definition: HTMLFormField.php:36
FormatJson\encode
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:115
HTMLFormField\getHelpText
getHelpText()
Determine the help text to display.
Definition: HTMLFormField.php:838
$html
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition: hooks.txt:2036
MWException
MediaWiki exception.
Definition: MWException.php:26
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1118
HTMLFormField\$mName
$mName
Definition: HTMLFormField.php:12
HTMLFormField\isHelpInline
isHelpInline()
Determine if the help text should be displayed inline.
Definition: HTMLFormField.php:873
HTMLFormField\getLabelAlignOOUI
getLabelAlignOOUI()
Get label alignment when generating field for OOUI.
Definition: HTMLFormField.php:667
HTMLFormField
The parent class to generate form fields.
Definition: HTMLFormField.php:7
HTMLFormField\lookupOptionsKeys
lookupOptionsKeys( $options)
Given an array of msg-key => value mappings, returns an array with keys being the message texts.
Definition: HTMLFormField.php:1068
$lines
$lines
Definition: router.php:61
HTMLFormField\$mDefault
$mDefault
Definition: HTMLFormField.php:19
HTMLFormField\needsJSForHtml5FormValidation
needsJSForHtml5FormValidation()
Whether this field requires the user agent to have JavaScript enabled for the client-side HTML5 form ...
Definition: HTMLFormField.php:1227
array
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
string
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition: hooks.txt:175
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
HTMLFormField\filter
filter( $value, $alldata)
Definition: HTMLFormField.php:321
HTMLFormField\$mID
$mID
Definition: HTMLFormField.php:15
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2675
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
HTMLFormField\getOOUI
getOOUI( $value)
Get the OOUI version of the div.
Definition: HTMLFormField.php:591
HTMLFormField\isHidden
isHidden( $alldata)
Test whether this field is supposed to be hidden, based on the values of the other form fields.
Definition: HTMLFormField.php:269
$value
$value
Definition: styleTest.css.php:49
HTMLFormField\$mValidationCallback
$mValidationCallback
Definition: HTMLFormField.php:10
HTMLFormField\getDefault
getDefault()
Definition: HTMLFormField.php:1005
HTMLFormFieldLayout
Definition: HTMLFormElement.php:37
HTMLFormField\$mFilterCallback
$mFilterCallback
Definition: HTMLFormField.php:11
HTMLFormField\getFieldLayoutOOUI
getFieldLayoutOOUI( $inputField, $config)
Get a FieldLayout (or subclass thereof) to wrap this field in when using OOUI output.
Definition: HTMLFormField.php:677
HTMLFormField\msg
msg()
Get a translated interface message.
Definition: HTMLFormField.php:80
on
Using a hook running we can avoid having all this option specific stuff in our mainline code Using the function We ve cleaned up the code here by removing clumps of infrequently used code and moving them off somewhere else It s much easier for someone working with this code to see what s _really_ going on
Definition: hooks.txt:77
HTMLFormField\getLabel
getLabel()
Definition: HTMLFormField.php:963
$ret
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:2036
HTMLFormField\$mParams
$mParams
Definition: HTMLFormField.php:8
HTMLFormField\getHelpTextHtmlRaw
getHelpTextHtmlRaw( $helptext)
Generate help text HTML formatted for raw output.
Definition: HTMLFormField.php:829
Linker\titleAttrib
static titleAttrib( $name, $options=null, array $msgParams=[])
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
Definition: Linker.php:1967
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:41
HTMLFormField\getOOUIModules
getOOUIModules()
Get the list of extra ResourceLoader modules which must be loaded client-side before it's possible to...
Definition: HTMLFormField.php:703
HTMLFormField\getInputOOUI
getInputOOUI( $value)
Same as getInputHTML, but returns an OOUI object.
Definition: HTMLFormField.php:57
HTMLFormField\$mShowEmptyLabels
bool $mShowEmptyLabels
If true will generate an empty div element with no label.
Definition: HTMLFormField.php:31
$args
if( $line===false) $args
Definition: cdb.php:64
HTMLFormField\getDiv
getDiv( $value)
Get the complete div for the input, including help text, labels, and whatever.
Definition: HTMLFormField.php:543
HTMLFormField\getVForm
getVForm( $value)
Get the complete field for the input, including help text, labels, and whatever.
Definition: HTMLFormField.php:739
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:2036
HTMLFormField\getInputHTML
getInputHTML( $value)
This function must be implemented to return the HTML to generate the input object itself.
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:210
HTMLFormField\$mOptionsLabelsNotFromMessage
$mOptionsLabelsNotFromMessage
Definition: HTMLFormField.php:24
HTMLFormField\getRaw
getRaw( $value)
Get the complete raw fields for the input, including help text, labels, and whatever.
Definition: HTMLFormField.php:716
$keys
$keys
Definition: testCompression.php:67
HTMLFormField\getErrorsRaw
getErrorsRaw( $value)
Determine form errors to display, returning them in an array.
Definition: HTMLFormField.php:910
HTMLFormField\forceToStringRecursive
static forceToStringRecursive( $array)
Recursively forces values in an array to strings, because issues arise with integer 0 as a value.
Definition: HTMLFormField.php:1086
HTMLFormField\isSubmitAttempt
isSubmitAttempt(WebRequest $request)
Can we assume that the request is an attempt to submit a HTMLForm, as opposed to an attempt to just v...
Definition: HTMLFormField.php:362
$help
$help
Definition: mcc.php:32
HTMLFormField\$mHideIf
$mHideIf
Definition: HTMLFormField.php:25
HTMLFormField\getTooltipAndAccessKey
getTooltipAndAccessKey()
Returns the attributes required for the tooltip and accesskey, for Html::element() etc.
Definition: HTMLFormField.php:1014
HTMLFormField\flattenOptions
static flattenOptions( $options)
flatten an array of options to a single array, for instance, a set of "<options>" inside "<optgroups>...
Definition: HTMLFormField.php:1139
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
HTMLFormField\$mVFormClass
$mVFormClass
Definition: HTMLFormField.php:17
HTMLFormField\getHelpTextHtmlDiv
getHelpTextHtmlDiv( $helptext)
Generate help text HTML in div format.
Definition: HTMLFormField.php:802
wfMessage
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
Linker\accesskey
static accesskey( $name)
Given the id of an interface element, constructs the appropriate accesskey attribute from the system ...
Definition: Linker.php:2015
HTMLFormField\getInline
getInline( $value)
Get the complete field as an inline element.
Definition: HTMLFormField.php:751
HTMLFormField\getOptionsOOUI
getOptionsOOUI()
Get options and make them into arrays suitable for OOUI.
Definition: HTMLFormField.php:1122
Xml\listDropDownOptions
static listDropDownOptions( $list, $params=[])
Build options for a drop-down box from a textual list.
Definition: Xml.php:541
HTMLFormField\getAttributes
getAttributes(array $list)
Returns the given attributes from the parameters.
Definition: HTMLFormField.php:1044
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms.
Definition: HTMLForm.php:136
HTMLFormField\loadDataFromRequest
loadDataFromRequest( $request)
Get the value that this input has been set to from a posted form, or the input's default value if it ...
Definition: HTMLFormField.php:373