DateInputWidget.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. namespace MediaWiki\Widget;
  3. use DateTime;
  4. /**
  5. * Date input widget.
  6. *
  7. * @since 1.29
  8. * @copyright 2016 MediaWiki Widgets Team and others; see AUTHORS.txt
  9. * @license MIT
  10. */
  11. class DateInputWidget extends \OOUI\TextInputWidget {
  12. protected $inputFormat = null;
  13. protected $displayFormat = null;
  14. protected $longDisplayFormat = null;
  15. protected $placeholderLabel = null;
  16. protected $placeholderDateFormat = null;
  17. protected $precision = null;
  18. protected $mustBeAfter = null;
  19. protected $mustBeBefore = null;
  20. /**
  21. * @param array $config Configuration options
  22. * - string $config['inputFormat'] Date format string to use for the textual input field.
  23. * Displayed while the widget is active, and the user can type in a date in this format.
  24. * Should be short and easy to type. (default: 'YYYY-MM-DD' or 'YYYY-MM', depending on
  25. * `precision`)
  26. * - string $config['displayFormat'] Date format string to use for the clickable label.
  27. * while the widget is inactive. Should be as unambiguous as possible (for example, prefer
  28. * to spell out the month, rather than rely on the order), even if that makes it longer.
  29. * Applicable only if the widget is infused. (default: language-specific)
  30. * - string $config['longDisplayFormat'] If a custom displayFormat is not specified, use
  31. * unabbreviated day of the week and month names in the default language-specific
  32. * displayFormat. (default: false)
  33. * - string $config['placeholderLabel'] Placeholder text shown when the widget is not
  34. * selected. Applicable only if the widget is infused. (default: taken from message
  35. * `mw-widgets-dateinput-no-date`)
  36. * - string $config['placeholderDateFormat'] User-visible date format string displayed
  37. * in the textual input field when it's empty. Should be the same as `inputFormat`, but
  38. * translated to the user's language. (default: 'YYYY-MM-DD' or 'YYYY-MM', depending on
  39. * `precision`)
  40. * - string $config['precision'] Date precision to use, 'day' or 'month' (default: 'day')
  41. * - string $config['mustBeAfter'] Validates the date to be after this.
  42. * In the 'YYYY-MM-DD' or 'YYYY-MM' format, depending on `precision`.
  43. * - string $config['mustBeBefore'] Validates the date to be before this.
  44. * In the 'YYYY-MM-DD' or 'YYYY-MM' format, depending on `precision`.
  45. */
  46. public function __construct( array $config = [] ) {
  47. $config = array_merge( [
  48. // Default config values
  49. 'precision' => 'day',
  50. 'longDisplayFormat' => false,
  51. ], $config );
  52. // Properties
  53. if ( isset( $config['inputFormat'] ) ) {
  54. $this->inputFormat = $config['inputFormat'];
  55. }
  56. if ( isset( $config['placeholderDateFormat'] ) ) {
  57. $this->placeholderDateFormat = $config['placeholderDateFormat'];
  58. }
  59. $this->precision = $config['precision'];
  60. if ( isset( $config['mustBeAfter'] ) ) {
  61. $this->mustBeAfter = $config['mustBeAfter'];
  62. }
  63. if ( isset( $config['mustBeBefore'] ) ) {
  64. $this->mustBeBefore = $config['mustBeBefore'];
  65. }
  66. // Properties stored for the infused JS widget
  67. if ( isset( $config['displayFormat'] ) ) {
  68. $this->displayFormat = $config['displayFormat'];
  69. }
  70. if ( isset( $config['longDisplayFormat'] ) ) {
  71. $this->longDisplayFormat = $config['longDisplayFormat'];
  72. }
  73. if ( isset( $config['placeholderLabel'] ) ) {
  74. $this->placeholderLabel = $config['placeholderLabel'];
  75. }
  76. // Set up placeholder text visible if the browser doesn't override it (logic taken from JS)
  77. if ( $this->placeholderDateFormat !== null ) {
  78. $placeholder = $this->placeholderDateFormat;
  79. } elseif ( $this->inputFormat !== null ) {
  80. // We have no way to display a translated placeholder for custom formats
  81. $placeholder = '';
  82. } else {
  83. $placeholder = wfMessage( "mw-widgets-dateinput-placeholder-$this->precision" )->text();
  84. }
  85. $config = array_merge( [
  86. // Processed config values
  87. 'placeholder' => $placeholder,
  88. ], $config );
  89. parent::__construct( $config );
  90. // Calculate min/max attributes (which are skipped by TextInputWidget) and add to <input>
  91. // min/max attributes are inclusive, but mustBeAfter/Before are exclusive
  92. if ( $this->mustBeAfter !== null ) {
  93. $min = new DateTime( $this->mustBeAfter );
  94. $min = $min->modify( '+1 day' );
  95. $min = $min->format( 'Y-m-d' );
  96. $this->input->setAttributes( [ 'min' => $min ] );
  97. }
  98. if ( $this->mustBeBefore !== null ) {
  99. $max = new DateTime( $this->mustBeBefore );
  100. $max = $max->modify( '-1 day' );
  101. $max = $max->format( 'Y-m-d' );
  102. $this->input->setAttributes( [ 'max' => $max ] );
  103. }
  104. // Initialization
  105. $this->addClasses( [ 'mw-widget-dateInputWidget' ] );
  106. }
  107. protected function getJavaScriptClassName() {
  108. return 'mw.widgets.DateInputWidget';
  109. }
  110. public function getConfig( &$config ) {
  111. if ( $this->inputFormat !== null ) {
  112. $config['inputFormat'] = $this->inputFormat;
  113. }
  114. if ( $this->displayFormat !== null ) {
  115. $config['displayFormat'] = $this->displayFormat;
  116. }
  117. if ( $this->longDisplayFormat !== null ) {
  118. $config['longDisplayFormat'] = $this->longDisplayFormat;
  119. }
  120. if ( $this->placeholderLabel !== null ) {
  121. $config['placeholderLabel'] = $this->placeholderLabel;
  122. }
  123. if ( $this->placeholderDateFormat !== null ) {
  124. $config['placeholderDateFormat'] = $this->placeholderDateFormat;
  125. }
  126. if ( $this->precision !== null ) {
  127. $config['precision'] = $this->precision;
  128. }
  129. if ( $this->mustBeAfter !== null ) {
  130. $config['mustBeAfter'] = $this->mustBeAfter;
  131. }
  132. if ( $this->mustBeBefore !== null ) {
  133. $config['mustBeBefore'] = $this->mustBeBefore;
  134. }
  135. $config['$overlay'] = true;
  136. return parent::getConfig( $config );
  137. }
  138. public function getInputElement( $config ) {
  139. // Inserts date/month type attribute
  140. return parent::getInputElement( $config )
  141. ->setAttributes( [
  142. 'type' => ( $config['precision'] === 'month' ) ? 'month' : 'date'
  143. ] );
  144. }
  145. }