<?php
declare(strict_types=1);
namespace HTML5required;

// Reject attempt to launch this script stand-alone.
if ( !defined( '\ABSPATH' ) ) { http_response_code( 403 ); exit( 'This script must not be launched stand-alone!' ); }

/**
 * HTML5 "required" Bug Widget.
 *
 * @author  	Andy Schmidt <Andy_Schmidt@HM-Software.com>
 * @copyright	2017 H&M Systems Software, Inc.
 *
 * @wordpress-plugin
 * Plugin Name: HTML5required
 * Description: Reproduces bug with HTML5 "required" attribute in Widget form. Tested with WordPress 4.9.1 on PHP 7.1.12.
 * Version:     1.00.00
 * Author:      H&M Systems Software, Inc.
 */

error_reporting( E_ALL ); 
ini_set( 'display_errors', '1' );

\add_action( 'widgets_init', function(): void { \register_widget( __NAMESPACE__.'\Widget_HTML5works' ); } );
\add_action( 'widgets_init', function(): void { \register_widget( __NAMESPACE__.'\Widget_HTML5fails' ); } );

return;

class Widget_HTML5works extends \WP_Widget 
{
	public const BASE_ID 		= 'html_does_work';		// Unique, lowercase base ID within WordPress.
	public const REQUIRED_ATTR 	= '';					// NO "required" attribute in form();
	
	/*
	 * Initializes the instance variables.
	 */
	public function __construct() 
	{
		parent::__construct(	// Initialize instance variables.
			static::BASE_ID, 
			static::BASE_ID,							// Name for the widget displayed on the configuration page.
			[	//  Widget options for wp_register_sidebar_widget().
				'description'	=> 'Reproduces bug with HTML5 required attribute in Widget form.',
				'classname'		=> static::BASE_ID,
			]	
		);
	}
	
	/**
	 * Front-end display of widget.
	 *
	 * @param array $args     			Display arguments, including the opening/closing HTML elements. 
	 * @param array $instance 			Saved settings for this instance of the widget.
	 *
	 * @see WP_Widget::widget()
	 */
	public function widget( $args, $instance )
	{
		/*
		 * Opening HTML Elements for the Container.
		 */
		echo $args[ 'before_widget' ];
		if ( !empty( $title ) ) {
			echo $args[ 'before_title' ] . \apply_filters( 'widget_title', $instance[ 'title' ] ) . $args[ 'after_title' ];
		}
		
		/*
		 * Display Content.
		 */
		echo 'Hello World';
		
		/*
		 * Closing HTML Elements for the Container.
		 */
		echo $args[ 'after_widget' ];
	}
	
	/**
	 * Back-end widget form.
	 * 
	 * Outputs the settings update form. The default width of the fully expanded
	 * control form is 250 and changing it is discouraged.
	 *
	 * @param array $old_settings 		Current settings for this instance.
	 *
	 * @return string 					'noform' will hide the "save" button.
	 * 
	 * @see WP_Widget::form()
	 */
	public function form( $old_settings )
	{
		?>
<p>
	<label for="<?php echo \esc_attr( $this->get_field_id( 'title' ) ); ?>">Title:</label> 
	<input class="widefat" title="Optional title used for this instance." type="text" id="<?php echo \esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo \esc_attr( $this->get_field_name( 'title' ) ); ?>" value="<?php echo \esc_attr( $old_settings[ 'title' ] ?? '' ); ?>">
</p>
<p>
	<label for="<?php echo \esc_attr( $this->get_field_id( 'addtlfld' ) ); ?>">Text:</label> 
	<input class="widefat" title="Additional text fails if required input." type="text" <?php echo static::REQUIRED_ATTR; ?>id="<?php echo \esc_attr( $this->get_field_id( 'addtlfld' ) ); ?>" name="<?php echo \esc_attr( $this->get_field_name( 'addtlfld' ) ); ?>" value="<?php echo \esc_attr( $old_settings[ 'addtlfld' ] ?? '' ); ?>">
</p>

    	<?php
		return ''; 
	}
	
	/**
	 * Sanitize and widget form values before saving.
	 *
	 * @param array $input 				Values gathered by settings update form.
	 * @param array $old_settings 		Previously saved instance settings from database.
	 *
	 * @return array|bool 				Sanitized instance settings to be saved. FALSE = Skip saving.
	 * 
	 * @see WP_Widget::update()
	 */
	public function update( $input, $old_settings )
	{
		// processes widget options to be saved
		return $input;
	}
}

class Widget_HTML5fails extends Widget_HTML5works
{
	public const BASE_ID 		= 'html_will_fail';			// Unique, lowercase base ID within WordPress.
	public const REQUIRED_ATTR 	= ' required="required" ';
}


/*EOF*/