Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
62.50% |
30 / 48 |
|
14.29% |
1 / 7 |
CRAP | |
0.00% |
0 / 1 |
HTMLTitleTextField | |
63.83% |
30 / 47 |
|
14.29% |
1 / 7 |
48.03 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
validate | |
84.00% |
21 / 25 |
|
0.00% |
0 / 1 |
17.05 | |||
getInputWidget | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
shouldInfuseOOUI | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getOOUIModules | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getInputHtml | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getDataAttribs | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\HTMLForm\Field; |
4 | |
5 | use FormatJson; |
6 | use InvalidArgumentException; |
7 | use MediaWiki\MediaWikiServices; |
8 | use MediaWiki\Title\MalformedTitleException; |
9 | use MediaWiki\Title\Title; |
10 | use MediaWiki\Widget\TitleInputWidget; |
11 | |
12 | /** |
13 | * Implements a text input field for page titles. |
14 | * Automatically does validation that the title is valid, |
15 | * as well as autocompletion if using the OOUI display format. |
16 | * |
17 | * Optional parameters: |
18 | * 'namespace' - Namespace the page must be in (use namespace constant; one of the NS_* constants may be used) |
19 | * 'relative' - If true and 'namespace' given, strip/add the namespace from/to the title as needed |
20 | * 'creatable' - Whether to validate the title is creatable (not a special page) |
21 | * 'exists' - Whether to validate that the title already exists |
22 | * 'interwiki' – Tolerate interwiki links (other conditions such as 'namespace' or 'exists' will be |
23 | * ignored if the title is an interwiki title). Cannot be used together with 'relative'. |
24 | * |
25 | * @stable to extend |
26 | * @since 1.26 |
27 | */ |
28 | class HTMLTitleTextField extends HTMLTextField { |
29 | /** |
30 | * @stable to call |
31 | * @inheritDoc |
32 | */ |
33 | public function __construct( $params ) { |
34 | $params += [ |
35 | 'namespace' => false, |
36 | 'relative' => false, |
37 | 'creatable' => false, |
38 | 'exists' => false, |
39 | 'interwiki' => false, |
40 | // This overrides the default from HTMLFormField |
41 | 'required' => true, |
42 | ]; |
43 | |
44 | parent::__construct( $params ); |
45 | } |
46 | |
47 | public function validate( $value, $alldata ) { |
48 | if ( $this->mParams['interwiki'] && $this->mParams['relative'] ) { |
49 | // relative and interwiki cannot be used together, because we don't have a way to know about |
50 | // namespaces used by the other wiki (and it might actually be a non-wiki link, too). |
51 | throw new InvalidArgumentException( 'relative and interwiki may not be used together' ); |
52 | } |
53 | // Default value (from getDefault()) is null, which breaks Title::newFromTextThrow() below |
54 | if ( $value === null ) { |
55 | $value = ''; |
56 | } |
57 | |
58 | if ( !$this->mParams['required'] && $value === '' ) { |
59 | // If this field is not required and the value is empty, that's okay, skip validation |
60 | return parent::validate( $value, $alldata ); |
61 | } |
62 | |
63 | $titleFactory = MediaWikiServices::getInstance()->getTitleFactory(); |
64 | try { |
65 | if ( !$this->mParams['relative'] ) { |
66 | $title = $titleFactory->newFromTextThrow( $value ); |
67 | } else { |
68 | // Can't use makeTitleSafe(), because it doesn't throw useful exceptions |
69 | $title = $titleFactory->newFromTextThrow( Title::makeName( $this->mParams['namespace'], $value ) ); |
70 | } |
71 | } catch ( MalformedTitleException $e ) { |
72 | return $this->msg( $e->getErrorMessage(), $e->getErrorMessageParameters() ); |
73 | } |
74 | |
75 | if ( $title->isExternal() ) { |
76 | if ( $this->mParams['interwiki'] ) { |
77 | // We cannot validate external titles, skip the rest of the validation |
78 | return parent::validate( $value, $alldata ); |
79 | } else { |
80 | return $this->msg( 'htmlform-title-interwiki', $title->getPrefixedText() ); |
81 | } |
82 | } |
83 | |
84 | $text = $title->getPrefixedText(); |
85 | if ( $this->mParams['namespace'] !== false && |
86 | !$title->inNamespace( $this->mParams['namespace'] ) |
87 | ) { |
88 | return $this->msg( 'htmlform-title-badnamespace', $text, $this->mParams['namespace'] ); |
89 | } |
90 | |
91 | if ( $this->mParams['creatable'] && !$title->canExist() ) { |
92 | return $this->msg( 'htmlform-title-not-creatable', $text ); |
93 | } |
94 | |
95 | if ( $this->mParams['exists'] && !$title->exists() ) { |
96 | return $this->msg( 'htmlform-title-not-exists', $text ); |
97 | } |
98 | |
99 | return parent::validate( $value, $alldata ); |
100 | } |
101 | |
102 | protected function getInputWidget( $params ) { |
103 | if ( $this->mParams['namespace'] !== false ) { |
104 | $params['namespace'] = $this->mParams['namespace']; |
105 | } |
106 | $params['relative'] = $this->mParams['relative']; |
107 | return new TitleInputWidget( $params ); |
108 | } |
109 | |
110 | protected function shouldInfuseOOUI() { |
111 | return true; |
112 | } |
113 | |
114 | protected function getOOUIModules() { |
115 | // FIXME: TitleInputWidget should be in its own module |
116 | return [ 'mediawiki.widgets' ]; |
117 | } |
118 | |
119 | public function getInputHtml( $value ) { |
120 | // add mw-searchInput class to enable search suggestions for non-OOUI, too |
121 | $this->mClass .= 'mw-searchInput'; |
122 | |
123 | // return the HTMLTextField html |
124 | return parent::getInputHTML( $value ); |
125 | } |
126 | |
127 | protected function getDataAttribs() { |
128 | return [ |
129 | 'data-mw-searchsuggest' => FormatJson::encode( [ |
130 | 'wrapAsLink' => false, |
131 | ] ), |
132 | ]; |
133 | } |
134 | } |
135 | |
136 | /** @deprecated class alias since 1.42 */ |
137 | class_alias( HTMLTitleTextField::class, 'HTMLTitleTextField' ); |