<commit_before><?php

/**
 * @copyright Copyright &copy; <NAME>, <EMAIL>, 2014
 * @package yii2-widgets
 * @version 1.0.0
 */

namespace kartik\builder;

use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;

/**
 * Base form widget
 *
 * @property $form kartik\widgets\ActiveForm
 *
 * @author <NAME> <<EMAIL>>
 * @since 1.0
 */
class BaseForm extends \yii\bootstrap\Widget
{
    // form inputs
    const INPUT_TEXT = 'textInput';
    const INPUT_TEXTAREA = 'textarea';
    const INPUT_PASSWORD = '<PASSWORD>';
    const INPUT_DROPDOWN_LIST = 'dropdownList';
    const INPUT_LIST_BOX = 'listBox';
    const INPUT_CHECKBOX = 'checkbox';
    const INPUT_RADIO = 'radio';
    const INPUT_CHECKBOX_LIST = 'checkboxList';
    const INPUT_RADIO_LIST = 'radioList';
    const INPUT_MULTISELECT = 'multiselect';
    const INPUT_STATIC = 'staticInput';
    const INPUT_FILE = 'fileInput';
    const INPUT_HTML5 = 'input';
    const INPUT_WIDGET = 'widget';
    const INPUT_RAW = 'raw'; // any free text or html markup

    /**
     * @var ActiveForm the form instance
     */
    public $form;

    /**
     * @var array the attribute settings. This is an associative array, which needs to be setup as
     * `$attribute_name => $attribute_settings`, where:
     * - `attribute_name`: string, the name of the attribute
     * - `attribute_settings`: array, the settings for the attribute, where you can set the following:
     *    - 'type': string, the input type for the attribute. Should be one of the INPUT_ constants.
     *       Defaults to `INPUT_TEXT`.
     *    - 'label': string, (optional) the custom attribute label. If this is not set, the model attribute label
     *      will be automatically used. If you set it to an empty string or null, it will not be displayed.
     *    - 'value': string|Closure, the value to be displayed if the `type` is set to `INPUT_RAW`. This will display
     *       the raw text from value field if it is a string. If this is a Closure, your anonymous function call should
     *       be of the type: `function ($model, $index, $widget) { }, where $model is the current model, $index is the
     *       zero based index of the dataProvider, and $widget is the current widget instance.`
     *    - 'fieldConfig': array, the configuration for the active field.
     *    - 'items': array, the list of items if input type is one of the following:
     *      `INPUT_DROPDOWN_LIST`, `INPUT_LIST_BOX`, `INPUT_CHECKBOX_LIST`, `INPUT_RADIO_LIST`, `INPUT_MULTISELECT`
     *    - `enclosedByLabel`: bool, if the `INPUT_CHECKBOX` or `INPUT_RADIO` is to be enclosed by label. Defaults
     *      to `true`.
     *    - html5type: string, the type of HTML5 input, if input type is set to `INPUT_HTML5`.
     *    - 'widgetClass': string, the classname if input type is `INPUT_WIDGET`.
     *    - 'options': array, the HTML attributes or widget settings to be applied to the input.
     *    - 'columnOptions': array, for a `Form`, it will override columnOptions setup at `Form` level. For
     *      a `TabularForm` it will allow you to append additional column options for the grid data column.
     */
    public $attributes = [];

    /**
     * Initializes the widget
     *
     * @throws \yii\base\InvalidConfigException
     */
    public function init()
    {
        parent::init();
        if (empty($this->form) || !$this->form instanceof \kartik\widgets\ActiveForm) {
            throw new InvalidConfigException("The 'form' property must be set and must be an instance of '\\kartik\\widgets\\ActiveForm'.");
        }
        if (empty($this->attributes)) {
            throw new InvalidConfigException("The 'attributes' array must be set.");
        }
    }

    /**
     * Renders each input based on the attribute settings
     *
     * @param $form \kartik\widgets\ActiveForm the form instance
     * @param $model \yii\db\ActiveRecord|\yii\base\Model
     * @param $attribute string the name of the attribute
     * @param $settings array the attribute settings
     * @return \kartik\widgets\ActiveField
     * @throws \yii\base\InvalidConfigException
     *
     */
    protected static function renderInput($form, $model, $attribute, $settings)
    {
        $type = ArrayHelper::getValue($settings, 'type', self::INPUT_TEXT);
        $fieldConfig = ArrayHelper::getValue($settings, 'fieldConfig', []);
        if (isset($settings['label'])) {
            $template = ArrayHelper::getValue($fieldConfig, 'template', "{label}\n{input}\n{hint}\n{error}");
            $fieldConfig['template'] = strtr($template, ["{label}\n" => $settings['label'], "{label}" => $settings['label']]);
        }

        $options = ArrayHelper::getValue($settings, 'options', []);
        if ($type === self::INPUT_TEXT || $type === self::INPUT_PASSWORD || $type === self::INPUT_TEXTAREA ||
            $type === self::INPUT_FILE || $type === self::INPUT_STATIC) {
            return $form->field($model, $attribute, $fieldConfig)->$type($options);
        }
        if ($type === self::INPUT_DROPDOWN_LIST || $type === self::INPUT_LIST_BOX || $type === self::INPUT_CHECKBOX_LIST ||
            $type === self::INPUT_RADIO_LIST || $type === self::INPUT_MULTISELECT
        ) {
            $items = ArrayHelper::getValue($settings, 'items', []);
            if (empty($items)) {
                throw new InvalidConfigException("You must setup the 'items' array for '{$attribute}' since it is a '{$type}'.");
            }
            return $form->field($model, $attribute, $fieldConfig)->$type($items, $options);
        }
        if ($type === self::INPUT_CHECKBOX || $type === self::INPUT_RADIO) {
            $enclosedByLabel = ArrayHelper::getValue($settings, 'enclosedByLabel', true);
            return $form->field($model, $attribute, $fieldConfig)->$type($options, $enclosedByLabel);
        }
        if ($type === self::INPUT_HTML5) {
            $html5type = ArrayHelper::getValue($settings, 'html5type', 'text');
            return $form->field($model, $attribute, $fieldConfig)->$type($html5type, $options);
        }
        if ($type === self::INPUT_WIDGET) {
            $widgetClass = ArrayHelper::getValue($settings, 'widgetClass', []);
            if (empty($widgetClass) && !$widgetClass instanceof yii\widgets\InputWidget) {
                throw new InvalidConfigException("A valid 'widgetClass' for '{$attribute}' must be setup and extend from 'yii\\widgets\\InputWidget'.");
            }
            return $form->field($model, $attribute, $fieldConfig)->$type($widgetClass, $options);
        }
        if ($type === self::INPUT_RAW) {
            return ArrayHelper::getValue($settings, 'value', '');
        }
    }
}<commit_msg>Fix #4: Disallow invalid input types<commit_after><?php

/**
 * @copyright Copyright &copy; <NAME>, <EMAIL>, 2014
 * @package yii2-widgets
 * @version 1.0.0
 */

namespace kartik\builder;

use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;

/**
 * Base form widget
 *
 * @property $form kartik\widgets\ActiveForm
 *
 * @author <NAME> <<EMAIL>>
 * @since 1.0
 */
class BaseForm extends \yii\bootstrap\Widget
{
    // form inputs
    const INPUT_TEXT = 'textInput';
    const INPUT_TEXTAREA = 'textarea';
    const INPUT_PASSWORD = '<PASSWORD>';
    const INPUT_DROPDOWN_LIST = 'dropdownList';
    const INPUT_LIST_BOX = 'listBox';
    const INPUT_CHECKBOX = 'checkbox';
    const INPUT_RADIO = 'radio';
    const INPUT_CHECKBOX_LIST = 'checkboxList';
    const INPUT_RADIO_LIST = 'radioList';
    const INPUT_MULTISELECT = 'multiselect';
    const INPUT_STATIC = 'staticInput';
    const INPUT_FILE = 'fileInput';
    const INPUT_HTML5 = 'input';
    const INPUT_WIDGET = 'widget';
    const INPUT_RAW = 'raw'; // any free text or html markup

    /**
     * @var array the allowed valid list of input types
     */
    protected static $_validInputs = [
        self::INPUT_TEXT,
        self::INPUT_TEXTAREA,
        self::INPUT_PASSWORD,
        self::INPUT_DROPDOWN_LIST,
        self::INPUT_LIST_BOX,
        self::INPUT_CHECKBOX,
        self::INPUT_RADIO,
        self::INPUT_CHECKBOX_LIST,
        self::INPUT_RADIO_LIST,
        self::INPUT_MULTISELECT,
        self::INPUT_STATIC,
        self::INPUT_FILE,
        self::INPUT_HTML5,
        self::INPUT_WIDGET,
        self::INPUT_RAW
    ];

    /**
     * @var ActiveForm the form instance
     */
    public $form;

    /**
     * @var array the attribute settings. This is an associative array, which needs to be setup as
     * `$attribute_name => $attribute_settings`, where:
     * - `attribute_name`: string, the name of the attribute
     * - `attribute_settings`: array, the settings for the attribute, where you can set the following:
     *    - 'type': string, the input type for the attribute. Should be one of the INPUT_ constants.
     *       Defaults to `INPUT_TEXT`.
     *    - 'label': string, (optional) the custom attribute label. If this is not set, the model attribute label
     *      will be automatically used. If you set it to an empty string or null, it will not be displayed.
     *    - 'value': string|Closure, the value to be displayed if the `type` is set to `INPUT_RAW`. This will display
     *       the raw text from value field if it is a string. If this is a Closure, your anonymous function call should
     *       be of the type: `function ($model, $index, $widget) { }, where $model is the current model, $index is the
     *       zero based index of the dataProvider, and $widget is the current widget instance.`
     *    - 'fieldConfig': array, the configuration for the active field.
     *    - 'items': array, the list of items if input type is one of the following:
     *      `INPUT_DROPDOWN_LIST`, `INPUT_LIST_BOX`, `INPUT_CHECKBOX_LIST`, `INPUT_RADIO_LIST`, `INPUT_MULTISELECT`
     *    - `enclosedByLabel`: bool, if the `INPUT_CHECKBOX` or `INPUT_RADIO` is to be enclosed by label. Defaults
     *      to `true`.
     *    - html5type: string, the type of HTML5 input, if input type is set to `INPUT_HTML5`.
     *    - 'widgetClass': string, the classname if input type is `INPUT_WIDGET`.
     *    - 'options': array, the HTML attributes or widget settings to be applied to the input.
     *    - 'columnOptions': array, for a `Form`, it will override columnOptions setup at `Form` level. For
     *      a `TabularForm` it will allow you to append additional column options for the grid data column.
     */
    public $attributes = [];

    /**
     * Initializes the widget
     *
     * @throws \yii\base\InvalidConfigException
     */
    public function init()
    {
        parent::init();
        if (empty($this->form) || !$this->form instanceof \kartik\widgets\ActiveForm) {
            throw new InvalidConfigException("The 'form' property must be set and must be an instance of '\\kartik\\widgets\\ActiveForm'.");
        }
        if (empty($this->attributes)) {
            throw new InvalidConfigException("The 'attributes' array must be set.");
        }
    }

    /**
     * Renders each input based on the attribute settings
     *
     * @param $form \kartik\widgets\ActiveForm the form instance
     * @param $model \yii\db\ActiveRecord|\yii\base\Model
     * @param $attribute string the name of the attribute
     * @param $settings array the attribute settings
     * @return \kartik\widgets\ActiveField
     * @throws \yii\base\InvalidConfigException
     *
     */
    protected static function renderInput($form, $model, $attribute, $settings)
    {
        $type = ArrayHelper::getValue($settings, 'type', self::INPUT_TEXT);
        $i = strpos($attribute, ']');
        $attribName = $i > 0 ? substr($attribute, $i + 1) : $attribute;
        if (!in_array($type, static::$_validInputs)) {
            throw new InvalidConfigException("Invalid input type '{$type}' configured for the attribute '{$attribName}'.'");
        }
        $fieldConfig = ArrayHelper::getValue($settings, 'fieldConfig', []);
        if (isset($settings['label'])) {
            $template = ArrayHelper::getValue($fieldConfig, 'template', "{label}\n{input}\n{hint}\n{error}");
            $fieldConfig['template'] = strtr($template, ["{label}\n" => $settings['label'], "{label}" => $settings['label']]);
        }

        $options = ArrayHelper::getValue($settings, 'options', []);
        if ($type === self::INPUT_TEXT || $type === self::INPUT_PASSWORD || $type === self::INPUT_TEXTAREA ||
            $type === self::INPUT_FILE || $type === self::INPUT_STATIC
        ) {
            return $form->field($model, $attribute, $fieldConfig)->$type($options);
        }
        if ($type === self::INPUT_DROPDOWN_LIST || $type === self::INPUT_LIST_BOX || $type === self::INPUT_CHECKBOX_LIST ||
            $type === self::INPUT_RADIO_LIST || $type === self::INPUT_MULTISELECT
        ) {
            $items = ArrayHelper::getValue($settings, 'items', []);
            if (empty($items)) {
                throw new InvalidConfigException("You must setup the 'items' array for attribute '{$attribName}' since it is a '{$type}'.");
            }
            return $form->field($model, $attribute, $fieldConfig)->$type($items, $options);
        }
        if ($type === self::INPUT_CHECKBOX || $type === self::INPUT_RADIO) {
            $enclosedByLabel = ArrayHelper::getValue($settings, 'enclosedByLabel', true);
            return $form->field($model, $attribute, $fieldConfig)->$type($options, $enclosedByLabel);
        }
        if ($type === self::INPUT_HTML5) {
            $html5type = ArrayHelper::getValue($settings, 'html5type', 'text');
            return $form->field($model, $attribute, $fieldConfig)->$type($html5type, $options);
        }
        if ($type === self::INPUT_WIDGET) {
            $widgetClass = ArrayHelper::getValue($settings, 'widgetClass', []);
            if (empty($widgetClass) && !$widgetClass instanceof yii\widgets\InputWidget) {
                throw new InvalidConfigException("A valid 'widgetClass' for '{$attribute}' must be setup and extend from 'yii\\widgets\\InputWidget'.");
            }
            return $form->field($model, $attribute, $fieldConfig)->$type($widgetClass, $options);
        }
        if ($type === self::INPUT_RAW) {
            return ArrayHelper::getValue($settings, 'value', '');
        }
    }
}
{'fraction_non_alphanumeric': 0.1346140412155082, 'fraction_numerical': 0.0027942717429269995, 'mean_word_length': 2.876523151909017, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5141667', 'n_tokens_mistral': 4139, 'n_tokens_neox': 4059, 'n_words': 1216}