summaryrefslogtreecommitdiff
path: root/www/wiki/includes/widget/DateInputWidget.php
blob: 975f8e9c48c4b09d95af7d0d8ccc1a207577764a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<?php

namespace MediaWiki\Widget;

use DateTime;

/**
 * Date input widget.
 *
 * @since 1.29
 * @copyright 2016 MediaWiki Widgets Team and others; see AUTHORS.txt
 * @license MIT
 */
class DateInputWidget extends \OOUI\TextInputWidget {

	protected $inputFormat = null;
	protected $displayFormat = null;
	protected $longDisplayFormat = null;
	protected $placeholderLabel = null;
	protected $placeholderDateFormat = null;
	protected $precision = null;
	protected $mustBeAfter = null;
	protected $mustBeBefore = null;

	/**
	 * @param array $config Configuration options
	 *   - string $config['inputFormat'] Date format string to use for the textual input field.
	 *     Displayed while the widget is active, and the user can type in a date in this format.
	 *     Should be short and easy to type. (default: 'YYYY-MM-DD' or 'YYYY-MM', depending on
	 *     `precision`)
	 *   - string $config['displayFormat'] Date format string to use for the clickable label.
	 *     while the widget is inactive. Should be as unambiguous as possible (for example, prefer
	 *     to spell out the month, rather than rely on the order), even if that makes it longer.
	 *     Applicable only if the widget is infused. (default: language-specific)
	 *   - string $config['longDisplayFormat'] If a custom displayFormat is not specified, use
	 *     unabbreviated day of the week and month names in the default language-specific
	 *     displayFormat. (default: false)
	 *   - string $config['placeholderLabel'] Placeholder text shown when the widget is not
	 *     selected. Applicable only if the widget is infused. (default: taken from message
	 *     `mw-widgets-dateinput-no-date`)
	 *   - string $config['placeholderDateFormat'] User-visible date format string displayed
	 *     in the textual input field when it's empty. Should be the same as `inputFormat`, but
	 *     translated to the user's language. (default: 'YYYY-MM-DD' or 'YYYY-MM', depending on
	 *     `precision`)
	 *   - string $config['precision'] Date precision to use, 'day' or 'month' (default: 'day')
	 *   - string $config['mustBeAfter']	Validates the date to be after this.
	 *     In the 'YYYY-MM-DD' or 'YYYY-MM' format, depending on `precision`.
	 *   - string $config['mustBeBefore'] Validates the date to be before this.
	 *     In the 'YYYY-MM-DD' or 'YYYY-MM' format, depending on `precision`.
	 */
	public function __construct( array $config = [] ) {
		$config = array_merge( [
			// Default config values
			'precision' => 'day',
			'longDisplayFormat' => false,
		], $config );

		// Properties
		if ( isset( $config['inputFormat'] ) ) {
			$this->inputFormat = $config['inputFormat'];
		}
		if ( isset( $config['placeholderDateFormat'] ) ) {
			$this->placeholderDateFormat = $config['placeholderDateFormat'];
		}
		$this->precision = $config['precision'];
		if ( isset( $config['mustBeAfter'] ) ) {
			$this->mustBeAfter = $config['mustBeAfter'];
		}
		if ( isset( $config['mustBeBefore'] ) ) {
			$this->mustBeBefore = $config['mustBeBefore'];
		}

		// Properties stored for the infused JS widget
		if ( isset( $config['displayFormat'] ) ) {
			$this->displayFormat = $config['displayFormat'];
		}
		if ( isset( $config['longDisplayFormat'] ) ) {
			$this->longDisplayFormat = $config['longDisplayFormat'];
		}
		if ( isset( $config['placeholderLabel'] ) ) {
			$this->placeholderLabel = $config['placeholderLabel'];
		}

		// Set up placeholder text visible if the browser doesn't override it (logic taken from JS)
		if ( $this->placeholderDateFormat !== null ) {
			$placeholder = $this->placeholderDateFormat;
		} elseif ( $this->inputFormat !== null ) {
			// We have no way to display a translated placeholder for custom formats
			$placeholder = '';
		} else {
			$placeholder = wfMessage( "mw-widgets-dateinput-placeholder-$this->precision" )->text();
		}

		$config = array_merge( [
			// Processed config values
			'placeholder' => $placeholder,
		], $config );

		parent::__construct( $config );

		// Calculate min/max attributes (which are skipped by TextInputWidget) and add to <input>
		// min/max attributes are inclusive, but mustBeAfter/Before are exclusive
		if ( $this->mustBeAfter !== null ) {
			$min = new DateTime( $this->mustBeAfter );
			$min = $min->modify( '+1 day' );
			$min = $min->format( 'Y-m-d' );
			$this->input->setAttributes( [ 'min' => $min ] );
		}
		if ( $this->mustBeBefore !== null ) {
			$max = new DateTime( $this->mustBeBefore );
			$max = $max->modify( '-1 day' );
			$max = $max->format( 'Y-m-d' );
			$this->input->setAttributes( [ 'max' => $max ] );
		}

		// Initialization
		$this->addClasses( [ 'mw-widget-dateInputWidget' ] );
	}

	protected function getJavaScriptClassName() {
		return 'mw.widgets.DateInputWidget';
	}

	public function getConfig( &$config ) {
		if ( $this->inputFormat !== null ) {
			$config['inputFormat'] = $this->inputFormat;
		}
		if ( $this->displayFormat !== null ) {
			$config['displayFormat'] = $this->displayFormat;
		}
		if ( $this->longDisplayFormat !== null ) {
			$config['longDisplayFormat'] = $this->longDisplayFormat;
		}
		if ( $this->placeholderLabel !== null ) {
			$config['placeholderLabel'] = $this->placeholderLabel;
		}
		if ( $this->placeholderDateFormat !== null ) {
			$config['placeholderDateFormat'] = $this->placeholderDateFormat;
		}
		if ( $this->precision !== null ) {
			$config['precision'] = $this->precision;
		}
		if ( $this->mustBeAfter !== null ) {
			$config['mustBeAfter'] = $this->mustBeAfter;
		}
		if ( $this->mustBeBefore !== null ) {
			$config['mustBeBefore'] = $this->mustBeBefore;
		}
		$config['$overlay'] = true;
		return parent::getConfig( $config );
	}

	public function getInputElement( $config ) {
		// Inserts date/month type attribute
		return parent::getInputElement( $config )
			->setAttributes( [
				'type' => ( $config['precision'] === 'month' ) ? 'month' : 'date'
			] );
	}
}