Proyectos de Subversion Moodle

Rev

| 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) {
57
            // Split and decode values. Comma separated list of values allowed. With valuable commas escaped with backslash.
58
            $options = preg_replace('/\\\,/', ',',  preg_split('/(?<!\\\),/', trim($value)));
59
            // This is a multiple select, let's pass the multiple flag after first option.
60
            $afterfirstoption = false;
61
            foreach ($options as $option) {
62
                $this->field->selectOption(trim($option), $afterfirstoption);
63
                $afterfirstoption = true;
64
            }
65
        } else {
66
            // By default, assume the passed value is a non-multiple option.
67
            $this->field->selectOption(trim($value));
68
       }
69
    }
70
 
71
    /**
72
     * Returns the text of the currently selected options.
73
     *
74
     * @return string Comma separated if multiple options are selected. Commas in option texts escaped with backslash.
75
     */
76
    public function get_value() {
77
        return $this->get_selected_options();
78
    }
79
 
80
    /**
81
     * Returns whether the provided argument matches the current value.
82
     *
83
     * @param mixed $expectedvalue
84
     * @return bool
85
     */
86
    public function matches($expectedvalue) {
87
 
88
        $multiple = $this->field->hasAttribute('multiple');
89
 
90
        // Same implementation as the parent if it is a single select.
91
        if (!$multiple) {
92
            $cleanexpectedvalue = trim($expectedvalue);
93
            $selectedtext = trim($this->get_selected_options());
94
            $selectedvalue = trim($this->get_selected_options(false));
95
            if ($cleanexpectedvalue != $selectedvalue && $cleanexpectedvalue != $selectedtext) {
96
                return false;
97
            }
98
            return true;
99
        }
100
 
101
        // We are dealing with a multi-select.
102
 
103
        // Unescape + trim all options and flip it to have the expected values as keys.
104
        $expectedoptions = $this->get_unescaped_options($expectedvalue);
105
 
106
        // Get currently selected option's texts.
107
        $texts = $this->get_selected_options(true);
108
        $selectedoptiontexts = $this->get_unescaped_options($texts);
109
 
110
        // Get currently selected option's values.
111
        $values = $this->get_selected_options(false);
112
        $selectedoptionvalues = $this->get_unescaped_options($values);
113
 
114
        // We check against string-ordered lists of options.
115
        if ($expectedoptions !== $selectedoptiontexts &&
116
                $expectedoptions !== $selectedoptionvalues) {
117
            return false;
118
        }
119
 
120
        return true;
121
    }
122
 
123
    /**
124
     * Cleans the list of options and returns it as a string separating options with |||.
125
     *
126
     * @param string $value The string containing the escaped options.
127
     * @return string The options
128
     */
129
    protected function get_unescaped_options($value) {
130
 
131
        // Can be multiple comma separated, with valuable commas escaped with backslash.
132
        $optionsarray = array_map(
133
            'trim',
134
            preg_replace('/\\\,/', ',',
135
                preg_split('/(?<!\\\),/', $value)
136
           )
137
        );
138
 
139
        // Sort by value (keeping the keys is irrelevant).
140
        core_collator::asort($optionsarray, SORT_STRING);
141
 
142
        // Returning it as a string which is easier to match against other values.
143
        return implode('|||', $optionsarray);
144
    }
145
 
146
    /**
147
     * Returns the field selected values.
148
     *
149
     * Externalized from the common behat_form_field API method get_value() as
150
     * matches() needs to check against both values and texts.
151
     *
152
     * @param bool $returntexts Returns the options texts or the options values.
153
     * @return string
154
     */
155
    protected function get_selected_options($returntexts = true) {
156
 
157
        $method = 'getHtml';
158
        if ($returntexts === false) {
159
            $method = 'getValue';
160
        }
161
 
162
        // Is the select multiple?
163
        $multiple = $this->field->hasAttribute('multiple');
164
 
165
        $selectedoptions = array(); // To accumulate found selected options.
166
 
167
        // Driver returns the values as an array or as a string depending
168
        // on whether multiple options are selected or not.
169
        $values = $this->field->getValue();
170
        if (!is_array($values)) {
171
            $values = array($values);
172
        }
173
 
174
        // Get all the options in the select and extract their value/text pairs.
175
        $alloptions = $this->field->findAll('xpath', '//option');
176
        foreach ($alloptions as $option) {
177
            // Is it selected?
178
            if (in_array($option->getValue(), $values)) {
179
                if ($multiple) {
180
                    // If the select is multiple, text commas must be encoded.
181
                    $selectedoptions[] = trim(str_replace(',', '\,', $option->{$method}()));
182
                } else {
183
                    $selectedoptions[] = trim($option->{$method}());
184
                }
185
            }
186
        }
187
 
188
        return implode(', ', $selectedoptions);
189
    }
190
 
191
    /**
192
     * Returns the opton XPath based on it's select xpath.
193
     *
194
     * @param string $option
195
     * @param string $selectxpath
196
     * @return string xpath
197
     */
198
    protected function get_option_xpath($option, $selectxpath) {
199
        $valueliteral = behat_context_helper::escape(trim($option));
200
        return $selectxpath . "/descendant::option[(./@value=$valueliteral or normalize-space(.)=$valueliteral)]";
201
    }
202
}