<commit_before><?php

namespace Collective\Html\Traits;

use Illuminate\Support\Collection;
use Illuminate\Contracts\Support\Arrayable;

trait SelectionTrait
{
    /**
     * Create a select box field.
     *
     * @param  string $name
     * @param  array  $list
     * @param  string $selected
     * @param  array  $selectAttributes
     * @param  array  $optionsAttributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    public function select(
        $name,
        $list = [],
        $selected = null,
        array $selectAttributes = [],
        array $optionsAttributes = [],
        array $optgroupsAttributes = []
    ) {
        $this->type = 'select';

        // When building a select box the "value" attribute is really the selected one
        // so we will use that when checking the model or session for a value which
        // should provide a convenient method of re-populating the forms on post.
        $selected = $this->getValueAttribute($name, $selected);

        $selectAttributes['id'] = $this->getIdAttribute($name, $selectAttributes);

        if (! isset($selectAttributes['name'])) {
            $selectAttributes['name'] = $name;
        }

        // We will simply loop through the options and build an HTML value for each of
        // them until we have an array of HTML declarations. Then we will join them
        // all together into one single HTML element that can be put on the form.
        $html = [];

        if (isset($selectAttributes['placeholder'])) {
            $html[] = $this->placeholderOption($selectAttributes['placeholder'], $selected);
            unset($selectAttributes['placeholder']);
        }

        if (isset($selectAttributes['native-placeholder'])) {
            $selectAttributes['placeholder'] = $selectAttributes['native-placeholder'];
            unset($selectAttributes['native-placeholder']);
        }

        foreach ($list as $value => $display) {
            $html[] = $this->getSelectOption(
                $display, $value, $selected, $optionsAttributes[$value] ?? [], $optgroupsAttributes[$value] ?? []
            );
        }

        // Once we have all of this HTML, we can join this into a single element after
        // formatting the attributes into an HTML "attributes" string, then we will
        // build out a final select statement, which will contain all the values.
        $options = $this->getHtmlBuilder()->attributes($selectAttributes);

        $list = implode('', $html);

        return $this->toHtmlString("<select{$options}>{$list}</select>");
    }

    /**
     * Get the select option for the given value.
     *
     * @param  string  $display
     * @param  string  $value
     * @param  string  $selected
     * @param  array  $attributes
     * @param  array  $optgroups
     *
     * @return \Illuminate\Support\HtmlString
     */
    public function getSelectOption(
        $display,
        $value,
        $selected,
        array $attributes = [],
        array $optgroups = []
    ) {
        if (is_array($display)) {
            return $this->optionGroup($display, $value, $selected, $optgroups, $attributes);
        }

        return $this->option($display, $value, $selected, $attributes);
    }

    /**
     * Create an option group form element.
     *
     * @param  array   $list
     * @param  string  $label
     * @param  string  $selected
     * @param  array  $attributes
     * @param  array  $optionsAttributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function optionGroup(
        $list,
        $label,
        $selected,
        array $attributes = [],
        array $optionsAttributes = []
    ) {
        $html = [];

        foreach ($list as $value => $display) {
            $html[] = $this->option(
                $display, $value, $selected, $optionsAttributes[$value] ?? []
            );
        }

        return $this->toHtmlString(sprintf(
            '<optgroup label="%s"%s>%s</optgroup>',
            $this->entities($label),
            $this->getHtmlBuilder()->attributes($attributes),
            implode('', $html)
        ));
    }

    /**
     * Create a select element option.
     *
     * @param  string  $display
     * @param  string  $value
     * @param  string|array|\Illuminate\Contracts\Support\Arrayable|bool  $selected
     * @param  array   $attributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function option($display, $value, $selected, array $attributes = [])
    {
        $selected = $this->getSelectedValue($value, $selected);

        $options = ['value' => $value, 'selected' => $selected] + $attributes;

        return $this->toHtmlString(sprintf(
            '<option%s>%s</option>',
            $this->getHtmlBuilder()->attributes($options),
            $this->entities($display)
        ));
    }

    /**
     * Create a placeholder select element option.
     *
     * @param string  $display
     * @param string  $selected
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function placeholderOption($display, $selected)
    {
        $options = [
            'selected' => $this->getSelectedValue(null, $selected),
            'value'    => '',
        ];

        return $this->toHtmlString(sprintf(
            '<option%s>%s</option>',
            $this->getHtmlBuilder()->attributes($options),
            $this->entities($display)
        ));
    }

    /**
     * Determine if the value is selected.
     *
     * @param  string  $value
     * @param  string|array|\Illuminate\Contracts\Support\Arrayable|bool  $selected
     *
     * @return string
     */
    protected function getSelectedValue($value, $selected)
    {
        if ($selected instanceof Collection) {
            return $selected->contains($value) ? 'selected' : null;
        } elseif ($selected instanceof Arrayable) {
            $selected = $selected->toArray();
        }

        if (is_array($selected)) {
            return in_array($value, $selected, true) || in_array((string) $value, $selected, true)
                        ? 'selected'
                        : null;
        }

        if (is_int($value) && is_bool($selected)) {
            return (bool) $value === $selected;
        }

        return ((string) $value === (string) $selected) ? 'selected' : null;
    }

    /**
     * Create a select range field.<commit_msg>in_array() should have priority over Collection::contains().<commit_after><?php

namespace Collective\Html\Traits;

use Illuminate\Support\Collection;
use Illuminate\Contracts\Support\Arrayable;

trait SelectionTrait
{
    /**
     * Create a select box field.
     *
     * @param  string $name
     * @param  array  $list
     * @param  string $selected
     * @param  array  $selectAttributes
     * @param  array  $optionsAttributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    public function select(
        $name,
        $list = [],
        $selected = null,
        array $selectAttributes = [],
        array $optionsAttributes = [],
        array $optgroupsAttributes = []
    ) {
        $this->type = 'select';

        // When building a select box the "value" attribute is really the selected one
        // so we will use that when checking the model or session for a value which
        // should provide a convenient method of re-populating the forms on post.
        $selected = $this->getValueAttribute($name, $selected);

        $selectAttributes['id'] = $this->getIdAttribute($name, $selectAttributes);

        if (! isset($selectAttributes['name'])) {
            $selectAttributes['name'] = $name;
        }

        // We will simply loop through the options and build an HTML value for each of
        // them until we have an array of HTML declarations. Then we will join them
        // all together into one single HTML element that can be put on the form.
        $html = [];

        if (isset($selectAttributes['placeholder'])) {
            $html[] = $this->placeholderOption($selectAttributes['placeholder'], $selected);
            unset($selectAttributes['placeholder']);
        }

        if (isset($selectAttributes['native-placeholder'])) {
            $selectAttributes['placeholder'] = $selectAttributes['native-placeholder'];
            unset($selectAttributes['native-placeholder']);
        }

        foreach ($list as $value => $display) {
            $html[] = $this->getSelectOption(
                $display, $value, $selected, $optionsAttributes[$value] ?? [], $optgroupsAttributes[$value] ?? []
            );
        }

        // Once we have all of this HTML, we can join this into a single element after
        // formatting the attributes into an HTML "attributes" string, then we will
        // build out a final select statement, which will contain all the values.
        $options = $this->getHtmlBuilder()->attributes($selectAttributes);

        $list = implode('', $html);

        return $this->toHtmlString("<select{$options}>{$list}</select>");
    }

    /**
     * Get the select option for the given value.
     *
     * @param  string  $display
     * @param  string  $value
     * @param  string  $selected
     * @param  array  $attributes
     * @param  array  $optgroups
     *
     * @return \Illuminate\Support\HtmlString
     */
    public function getSelectOption(
        $display,
        $value,
        $selected,
        array $attributes = [],
        array $optgroups = []
    ) {
        if (is_array($display)) {
            return $this->optionGroup($display, $value, $selected, $optgroups, $attributes);
        }

        return $this->option($display, $value, $selected, $attributes);
    }

    /**
     * Create an option group form element.
     *
     * @param  array   $list
     * @param  string  $label
     * @param  string  $selected
     * @param  array  $attributes
     * @param  array  $optionsAttributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function optionGroup(
        $list,
        $label,
        $selected,
        array $attributes = [],
        array $optionsAttributes = []
    ) {
        $html = [];

        foreach ($list as $value => $display) {
            $html[] = $this->option(
                $display, $value, $selected, $optionsAttributes[$value] ?? []
            );
        }

        return $this->toHtmlString(sprintf(
            '<optgroup label="%s"%s>%s</optgroup>',
            $this->entities($label),
            $this->getHtmlBuilder()->attributes($attributes),
            implode('', $html)
        ));
    }

    /**
     * Create a select element option.
     *
     * @param  string  $display
     * @param  string  $value
     * @param  string|array|\Illuminate\Contracts\Support\Arrayable|bool  $selected
     * @param  array   $attributes
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function option($display, $value, $selected, array $attributes = [])
    {
        $selected = $this->getSelectedValue($value, $selected);

        $options = ['value' => $value, 'selected' => $selected] + $attributes;

        return $this->toHtmlString(sprintf(
            '<option%s>%s</option>',
            $this->getHtmlBuilder()->attributes($options),
            $this->entities($display)
        ));
    }

    /**
     * Create a placeholder select element option.
     *
     * @param string  $display
     * @param string  $selected
     *
     * @return \Illuminate\Support\HtmlString
     */
    protected function placeholderOption($display, $selected)
    {
        $options = [
            'selected' => $this->getSelectedValue(null, $selected),
            'value'    => '',
        ];

        return $this->toHtmlString(sprintf(
            '<option%s>%s</option>',
            $this->getHtmlBuilder()->attributes($options),
            $this->entities($display)
        ));
    }

    /**
     * Determine if the value is selected.
     *
     * @param  string  $value
     * @param  string|array|\Illuminate\Contracts\Support\Arrayable|bool  $selected
     *
     * @return string
     */
    protected function getSelectedValue($value, $selected)
    {
        $selection = $selected instanceof Arrayable ? $selected->toArray() : $selected;

        if (is_array($selection)) {
            if (in_array($value, $selection, true) || in_array((string) $value, $selection, true)) {
                return 'selected';
            } elseif ($selected instanceof Collection) {
                return $selected->contains($value) ? 'selected' : null;
            }

            return null;
        }

        if (is_int($value) && is_bool($selected)) {
            return (bool) $value === $selected;
        }

        return ((string) $value === (string) $selected) ? 'selected' : null;
    }

    /**
     * Create a select range field.
{'fraction_non_alphanumeric': 0.13315259488768397, 'fraction_numerical': 0.0, 'mean_word_length': 2.1261501210653755, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 85, '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': '5691697', 'n_tokens_mistral': 3420, 'n_tokens_neox': 3432, 'n_words': 886}