Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Single select form field class.
19
 *
20
 * @package    core_form
21
 * @category   test
22
 * @copyright  2012 David Monllaó
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
27
 
28
require_once(__DIR__  . '/behat_form_field.php');
29
 
30
/**
31
 * Single select form field.
32
 *
33
 * @package    core_form
34
 * @category   test
35
 * @copyright  2012 David Monllaó
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
class behat_form_select extends behat_form_field {
39
 
40
    /**
41
     * Sets the value(s) of a select element.
42
     *
43
     * Seems an easy select, but there are lots of combinations
44
     * of browsers and operative systems and each one manages the
45
     * autosubmits and the multiple option selects in a different way.
46
     *
47
     * @param string $value plain value or comma separated values if multiple. Commas in values escaped with backslash.
48
     * @return void
49
     */
50
    public function set_value($value) {
51
 
52
        // Is the select multiple?
53
        $multiple = $this->field->hasAttribute('multiple');
54
 
55
        // Here we select the option(s).
56
        if ($multiple) {
1441 ariadna 57
            // Is the value empty?
58
            if (empty(trim($value))) {
59
                // Reset selection to nothing.
60
                $this->field->setValue([]);
61
                return;
62
            }
63
 
1 efrain 64
            // Split and decode values. Comma separated list of values allowed. With valuable commas escaped with backslash.
65
            $options = preg_replace('/\\\,/', ',',  preg_split('/(?<!\\\),/', trim($value)));
66
            // This is a multiple select, let's pass the multiple flag after first option.
67
            $afterfirstoption = false;
68
            foreach ($options as $option) {
69
                $this->field->selectOption(trim($option), $afterfirstoption);
70
                $afterfirstoption = true;
71
            }
72
        } else {
73
            // By default, assume the passed value is a non-multiple option.
74
            $this->field->selectOption(trim($value));
75
       }
76
    }
77
 
78
    /**
79
     * Returns the text of the currently selected options.
80
     *
81
     * @return string Comma separated if multiple options are selected. Commas in option texts escaped with backslash.
82
     */
83
    public function get_value() {
84
        return $this->get_selected_options();
85
    }
86
 
87
    /**
88
     * Returns whether the provided argument matches the current value.
89
     *
90
     * @param mixed $expectedvalue
91
     * @return bool
92
     */
93
    public function matches($expectedvalue) {
94
 
95
        $multiple = $this->field->hasAttribute('multiple');
96
 
97
        // Same implementation as the parent if it is a single select.
98
        if (!$multiple) {
99
            $cleanexpectedvalue = trim($expectedvalue);
100
            $selectedtext = trim($this->get_selected_options());
101
            $selectedvalue = trim($this->get_selected_options(false));
102
            if ($cleanexpectedvalue != $selectedvalue && $cleanexpectedvalue != $selectedtext) {
103
                return false;
104
            }
105
            return true;
106
        }
107
 
108
        // We are dealing with a multi-select.
109
 
110
        // Unescape + trim all options and flip it to have the expected values as keys.
111
        $expectedoptions = $this->get_unescaped_options($expectedvalue);
112
 
113
        // Get currently selected option's texts.
114
        $texts = $this->get_selected_options(true);
115
        $selectedoptiontexts = $this->get_unescaped_options($texts);
116
 
117
        // Get currently selected option's values.
118
        $values = $this->get_selected_options(false);
119
        $selectedoptionvalues = $this->get_unescaped_options($values);
120
 
121
        // We check against string-ordered lists of options.
122
        if ($expectedoptions !== $selectedoptiontexts &&
123
                $expectedoptions !== $selectedoptionvalues) {
124
            return false;
125
        }
126
 
127
        return true;
128
    }
129
 
130
    /**
131
     * Cleans the list of options and returns it as a string separating options with |||.
132
     *
133
     * @param string $value The string containing the escaped options.
134
     * @return string The options
135
     */
136
    protected function get_unescaped_options($value) {
137
 
138
        // Can be multiple comma separated, with valuable commas escaped with backslash.
139
        $optionsarray = array_map(
140
            'trim',
141
            preg_replace('/\\\,/', ',',
142
                preg_split('/(?<!\\\),/', $value)
143
           )
144
        );
145
 
146
        // Sort by value (keeping the keys is irrelevant).
147
        core_collator::asort($optionsarray, SORT_STRING);
148
 
149
        // Returning it as a string which is easier to match against other values.
150
        return implode('|||', $optionsarray);
151
    }
152
 
153
    /**
154
     * Returns the field selected values.
155
     *
156
     * Externalized from the common behat_form_field API method get_value() as
157
     * matches() needs to check against both values and texts.
158
     *
159
     * @param bool $returntexts Returns the options texts or the options values.
160
     * @return string
161
     */
162
    protected function get_selected_options($returntexts = true) {
163
 
164
        $method = 'getHtml';
165
        if ($returntexts === false) {
166
            $method = 'getValue';
167
        }
168
 
169
        // Is the select multiple?
170
        $multiple = $this->field->hasAttribute('multiple');
171
 
172
        $selectedoptions = array(); // To accumulate found selected options.
173
 
174
        // Driver returns the values as an array or as a string depending
175
        // on whether multiple options are selected or not.
176
        $values = $this->field->getValue();
177
        if (!is_array($values)) {
178
            $values = array($values);
179
        }
180
 
181
        // Get all the options in the select and extract their value/text pairs.
182
        $alloptions = $this->field->findAll('xpath', '//option');
183
        foreach ($alloptions as $option) {
184
            // Is it selected?
185
            if (in_array($option->getValue(), $values)) {
186
                if ($multiple) {
187
                    // If the select is multiple, text commas must be encoded.
188
                    $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}()));
189
                } else {
190
                    $selectedoptions[] = trim($option->{$method}());
191
                }
192
            }
193
        }
194
 
195
        return implode(', ', $selectedoptions);
196
    }
197
 
198
    /**
199
     * Returns the opton XPath based on it's select xpath.
200
     *
201
     * @param string $option
202
     * @param string $selectxpath
203
     * @return string xpath
204
     */
205
    protected function get_option_xpath($option, $selectxpath) {
206
        $valueliteral = behat_context_helper::escape(trim($option));
207
        return $selectxpath . "/descendant::option[(./@value=$valueliteral or normalize-space(.)=$valueliteral)]";
208
    }
209
}