1<?php 2 3use MediaWiki\Widget\TitleInputWidget; 4 5/** 6 * Implements a text input field for page titles. 7 * Automatically does validation that the title is valid, 8 * as well as autocompletion if using the OOUI display format. 9 * 10 * Optional parameters: 11 * 'namespace' - Namespace the page must be in 12 * 'relative' - If true and 'namespace' given, strip/add the namespace from/to the title as needed 13 * 'creatable' - Whether to validate the title is creatable (not a special page) 14 * 'exists' - Whether to validate that the title already exists 15 * 16 * @stable to extend 17 * @since 1.26 18 */ 19class HTMLTitleTextField extends HTMLTextField { 20 /** 21 * @stable to call 22 * @inheritDoc 23 */ 24 public function __construct( $params ) { 25 $params += [ 26 'namespace' => false, 27 'relative' => false, 28 'creatable' => false, 29 'exists' => false, 30 // This overrides the default from HTMLFormField 31 'required' => true, 32 ]; 33 34 parent::__construct( $params ); 35 } 36 37 public function validate( $value, $alldata ) { 38 // Default value (from getDefault()) is null, which breaks Title::newFromTextThrow() below 39 if ( $value === null ) { 40 $value = ''; 41 } 42 43 if ( !$this->mParams['required'] && $value === '' ) { 44 // If this field is not required and the value is empty, that's okay, skip validation 45 return parent::validate( $value, $alldata ); 46 } 47 48 try { 49 if ( !$this->mParams['relative'] ) { 50 $title = Title::newFromTextThrow( $value ); 51 } else { 52 // Can't use Title::makeTitleSafe(), because it doesn't throw useful exceptions 53 $title = Title::newFromTextThrow( Title::makeName( $this->mParams['namespace'], $value ) ); 54 } 55 } catch ( MalformedTitleException $e ) { 56 return $this->msg( $e->getErrorMessage(), $e->getErrorMessageParameters() ); 57 } 58 59 $text = $title->getPrefixedText(); 60 if ( $this->mParams['namespace'] !== false && 61 !$title->inNamespace( $this->mParams['namespace'] ) 62 ) { 63 return $this->msg( 'htmlform-title-badnamespace', $text, $this->mParams['namespace'] ); 64 } 65 66 if ( $this->mParams['creatable'] && !$title->canExist() ) { 67 return $this->msg( 'htmlform-title-not-creatable', $text ); 68 } 69 70 if ( $this->mParams['exists'] && !$title->exists() ) { 71 return $this->msg( 'htmlform-title-not-exists', $text ); 72 } 73 74 return parent::validate( $value, $alldata ); 75 } 76 77 protected function getInputWidget( $params ) { 78 if ( $this->mParams['namespace'] !== false ) { 79 $params['namespace'] = $this->mParams['namespace']; 80 } 81 $params['relative'] = $this->mParams['relative']; 82 return new TitleInputWidget( $params ); 83 } 84 85 protected function shouldInfuseOOUI() { 86 return true; 87 } 88 89 protected function getOOUIModules() { 90 // FIXME: TitleInputWidget should be in its own module 91 return [ 'mediawiki.widgets' ]; 92 } 93 94 public function getInputHtml( $value ) { 95 // add mw-searchInput class to enable search suggestions for non-OOUI, too 96 $this->mClass .= 'mw-searchInput'; 97 98 // return the HTMLTextField html 99 return parent::getInputHTML( $value ); 100 } 101 102 protected function getDataAttribs() { 103 return [ 104 'data-mw-searchsuggest' => FormatJson::encode( [ 105 'wrapAsLink' => false, 106 ] ), 107 ]; 108 } 109} 110