<?php

/**
 * Performs miscellaneous cross attribute validation and filtering for
 * HTML5 input elements. This is meant to be a post-transform.
 */
class HTMLPurifier_AttrTransform_HTML5_Input extends HTMLPurifier_AttrTransform
{
    /**
     * Allowed attributes vs input type lookup
     * @var array
     * @link https://html.spec.whatwg.org/dev/input.html#input-type-attr-summary
     * @version 22 July 2022
     * @note Generated by maintenance/generate-input-lookups.php script
     */
    protected static $attributes = array(
        'accept' => array(
            'file' => true,
        ),
        'alt' => array(
            'image' => true,
        ),
        'autocomplete' => array(
            'color' => true,
            'date' => true,
            'datetime-local' => true,
            'email' => true,
            'hidden' => true,
            'month' => true,
            'number' => true,
            'password' => true,
            'range' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'time' => true,
            'url' => true,
            'week' => true,
        ),
        'checked' => array(
            'checkbox' => true,
            'radio' => true,
        ),
        'dirname' => array(
            'search' => true,
            'text' => true,
        ),
        'formaction' => array(
            'image' => true,
            'submit' => true,
        ),
        'formenctype' => array(
            'image' => true,
            'submit' => true,
        ),
        'formmethod' => array(
            'image' => true,
            'submit' => true,
        ),
        'formnovalidate' => array(
            'image' => true,
            'submit' => true,
        ),
        'formtarget' => array(
            'image' => true,
            'submit' => true,
        ),
        'height' => array(
            'image' => true,
        ),
        'list' => array(
            'color' => true,
            'date' => true,
            'datetime-local' => true,
            'email' => true,
            'month' => true,
            'number' => true,
            'range' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'time' => true,
            'url' => true,
            'week' => true,
        ),
        'max' => array(
            'date' => true,
            'datetime-local' => true,
            'month' => true,
            'number' => true,
            'range' => true,
            'time' => true,
            'week' => true,
        ),
        'maxlength' => array(
            'email' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'url' => true,
        ),
        'min' => array(
            'date' => true,
            'datetime-local' => true,
            'month' => true,
            'number' => true,
            'range' => true,
            'time' => true,
            'week' => true,
        ),
        'minlength' => array(
            'email' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'url' => true,
        ),
        'multiple' => array(
            'email' => true,
            'file' => true,
        ),
        'pattern' => array(
            'email' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'url' => true,
        ),
        'placeholder' => array(
            'email' => true,
            'number' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'url' => true,
        ),
        'readonly' => array(
            'date' => true,
            'datetime-local' => true,
            'email' => true,
            'month' => true,
            'number' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'time' => true,
            'url' => true,
            'week' => true,
        ),
        'required' => array(
            'checkbox' => true,
            'date' => true,
            'datetime-local' => true,
            'email' => true,
            'file' => true,
            'month' => true,
            'number' => true,
            'password' => true,
            'radio' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'time' => true,
            'url' => true,
            'week' => true,
        ),
        'size' => array(
            'email' => true,
            'password' => true,
            'search' => true,
            'tel' => true,
            'text' => true,
            'url' => true,
        ),
        'src' => array(
            'image' => true,
        ),
        'step' => array(
            'date' => true,
            'datetime-local' => true,
            'month' => true,
            'number' => true,
            'range' => true,
            'time' => true,
            'week' => true,
        ),
        'value' => array(
            'button' => true,
            'checkbox' => true,
            'color' => true,
            'date' => true,
            'datetime-local' => true,
            'email' => true,
            'hidden' => true,
            'month' => true,
            'number' => true,
            'password' => true,
            'radio' => true,
            'range' => true,
            'reset' => true,
            'search' => true,
            'submit' => true,
            'tel' => true,
            'text' => true,
            'time' => true,
            'url' => true,
            'week' => true,
        ),
        'width' => array(
            'image' => true,
        ),
    );

    /**
     * @param array $attr
     * @param HTMLPurifier_Config $config
     * @param HTMLPurifier_Context $context
     * @return array
     */
    public function transform($attr, $config, $context)
    {
        if (empty($attr['type'])) {
            $t = 'text';
        } else {
            $t = strtolower($attr['type']);
        }

        // Remove attributes not allowed for detected input type
        foreach (self::$attributes as $a => $types) {
            if (array_key_exists($a, $attr) && !isset($types[$t])) {
                unset($attr[$a]);
            }
        }

        // Non-empty 'alt' attribute is required for 'image' input
        if ($t === 'image' && !isset($attr['alt'])) {
            $alt = trim((string) $config->get('Attr.DefaultImageAlt'));
            if ($alt === '') {
                $name = isset($attr['name']) ? trim($attr['name']) : '';
                $alt = $name !== '' ? $name : 'image';
            }
            $attr['alt'] = $alt;
        }

        // The value attribute is always optional, though should be considered
        // mandatory for checkbox, radio, and hidden.
        // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-value
        // Nu Validator diverges from the WHATWG spec, as it defines 'value'
        // attribute as required, where in fact it is optional, and may be an empty string:
        // https://html.spec.whatwg.org/multipage/input.html#button-state-(type=button)
        if (!isset($attr['value']) && ($t === 'checkbox' || $t === 'radio' || $t === 'hidden')) {
            $attr['value'] = '';
        }

        return $attr;
    }
}
