PageRenderTime 205ms CodeModel.GetById 101ms app.highlight 12ms RepoModel.GetById 88ms app.codeStats 0ms

/lib/form.php

https://bitbucket.org/photocrati/simpletest-for-wordpress
PHP | 361 lines | 199 code | 22 blank | 140 comment | 39 complexity | 6e90378af951013b84552d8bfadeba90 MD5 | raw file
  1<?php
  2/**
  3 *  Base include file for SimpleTest.
  4 *  @package    SimpleTest
  5 *  @subpackage WebTester
  6 *  @version    $Id: form.php 2013 2011-04-29 09:29:45Z pp11 $
  7 */
  8
  9/**#@+
 10 * include SimpleTest files
 11 */
 12require_once(dirname(__FILE__) . '/tag.php');
 13require_once(dirname(__FILE__) . '/encoding.php');
 14require_once(dirname(__FILE__) . '/selector.php');
 15/**#@-*/
 16
 17/**
 18 *    Form tag class to hold widget values.
 19 *    @package SimpleTest
 20 *    @subpackage WebTester
 21 */
 22class SimpleForm {
 23    private $method;
 24    private $action;
 25    private $encoding;
 26    private $default_target;
 27    private $id;
 28    private $buttons;
 29    private $images;
 30    private $widgets;
 31    private $radios;
 32    private $checkboxes;
 33
 34    /**
 35     *    Starts with no held controls/widgets.
 36     *    @param SimpleTag $tag        Form tag to read.
 37     *    @param SimplePage $page      Holding page.
 38     */
 39    function __construct($tag, $page) {
 40        $this->method = $tag->getAttribute('method');
 41        $this->action = $this->createAction($tag->getAttribute('action'), $page);
 42        $this->encoding = $this->setEncodingClass($tag);
 43        $this->default_target = false;
 44        $this->id = $tag->getAttribute('id');
 45        $this->buttons = array();
 46        $this->images = array();
 47        $this->widgets = array();
 48        $this->radios = array();
 49        $this->checkboxes = array();
 50    }
 51
 52    /**
 53     *    Creates the request packet to be sent by the form.
 54     *    @param SimpleTag $tag        Form tag to read.
 55     *    @return string               Packet class.
 56     *    @access private
 57     */
 58    protected function setEncodingClass($tag) {
 59        if (strtolower($tag->getAttribute('method')) == 'post') {
 60            if (strtolower($tag->getAttribute('enctype')) == 'multipart/form-data') {
 61                return 'SimpleMultipartEncoding';
 62            }
 63            return 'SimplePostEncoding';
 64        }
 65        return 'SimpleGetEncoding';
 66    }
 67
 68    /**
 69     *    Sets the frame target within a frameset.
 70     *    @param string $frame        Name of frame.
 71     *    @access public
 72     */
 73    function setDefaultTarget($frame) {
 74        $this->default_target = $frame;
 75    }
 76
 77    /**
 78     *    Accessor for method of form submission.
 79     *    @return string           Either get or post.
 80     *    @access public
 81     */
 82    function getMethod() {
 83        return ($this->method ? strtolower($this->method) : 'get');
 84    }
 85
 86    /**
 87     *    Combined action attribute with current location
 88     *    to get an absolute form target.
 89     *    @param string $action    Action attribute from form tag.
 90     *    @param SimpleUrl $base   Page location.
 91     *    @return SimpleUrl        Absolute form target.
 92     */
 93    protected function createAction($action, $page) {
 94        if (($action === '') || ($action === false)) {
 95            return $page->expandUrl($page->getUrl());
 96        }
 97        return $page->expandUrl(new SimpleUrl($action));;
 98    }
 99
100    /**
101     *    Absolute URL of the target.
102     *    @return SimpleUrl           URL target.
103     *    @access public
104     */
105    function getAction() {
106        $url = $this->action;
107        if ($this->default_target && ! $url->getTarget()) {
108            $url->setTarget($this->default_target);
109        }
110        if ($this->getMethod() == 'get') {
111            $url->clearRequest();
112        }
113        return $url;
114    }
115
116    /**
117     *    Creates the encoding for the current values in the
118     *    form.
119     *    @return SimpleFormEncoding    Request to submit.
120     *    @access private
121     */
122    protected function encode() {
123        $class = $this->encoding;
124        $encoding = new $class();
125        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
126            $this->widgets[$i]->write($encoding);
127        }
128        return $encoding;
129    }
130
131    /**
132     *    ID field of form for unique identification.
133     *    @return string           Unique tag ID.
134     *    @access public
135     */
136    function getId() {
137        return $this->id;
138    }
139
140    /**
141     *    Adds a tag contents to the form.
142     *    @param SimpleWidget $tag        Input tag to add.
143     */
144    function addWidget($tag) {
145        if (strtolower($tag->getAttribute('type')) == 'submit') {
146            $this->buttons[] = $tag;
147        } elseif (strtolower($tag->getAttribute('type')) == 'image') {
148            $this->images[] = $tag;
149        } elseif ($tag->getName()) {
150            $this->setWidget($tag);
151        }
152    }
153
154    /**
155     *    Sets the widget into the form, grouping radio
156     *    buttons if any.
157     *    @param SimpleWidget $tag   Incoming form control.
158     *    @access private
159     */
160    protected function setWidget($tag) {
161        if (strtolower($tag->getAttribute('type')) == 'radio') {
162            $this->addRadioButton($tag);
163        } elseif (strtolower($tag->getAttribute('type')) == 'checkbox') {
164            $this->addCheckbox($tag);
165        } else {
166            $this->widgets[] = &$tag;
167        }
168    }
169
170    /**
171     *    Adds a radio button, building a group if necessary.
172     *    @param SimpleRadioButtonTag $tag   Incoming form control.
173     *    @access private
174     */
175    protected function addRadioButton($tag) {
176        if (! isset($this->radios[$tag->getName()])) {
177            $this->widgets[] = new SimpleRadioGroup();
178            $this->radios[$tag->getName()] = count($this->widgets) - 1;
179        }
180        $this->widgets[$this->radios[$tag->getName()]]->addWidget($tag);
181    }
182
183    /**
184     *    Adds a checkbox, making it a group on a repeated name.
185     *    @param SimpleCheckboxTag $tag   Incoming form control.
186     *    @access private
187     */
188    protected function addCheckbox($tag) {
189        if (! isset($this->checkboxes[$tag->getName()])) {
190            $this->widgets[] = $tag;
191            $this->checkboxes[$tag->getName()] = count($this->widgets) - 1;
192        } else {
193            $index = $this->checkboxes[$tag->getName()];
194            if (! SimpleTestCompatibility::isA($this->widgets[$index], 'SimpleCheckboxGroup')) {
195                $previous = $this->widgets[$index];
196                $this->widgets[$index] = new SimpleCheckboxGroup();
197                $this->widgets[$index]->addWidget($previous);
198            }
199            $this->widgets[$index]->addWidget($tag);
200        }
201    }
202
203    /**
204     *    Extracts current value from form.
205     *    @param SimpleSelector $selector   Criteria to apply.
206     *    @return string/array              Value(s) as string or null
207     *                                      if not set.
208     *    @access public
209     */
210    function getValue($selector) {
211        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
212            if ($selector->isMatch($this->widgets[$i])) {
213                return $this->widgets[$i]->getValue();
214            }
215        }
216        foreach ($this->buttons as $button) {
217            if ($selector->isMatch($button)) {
218                return $button->getValue();
219            }
220        }
221        return null;
222    }
223
224    /**
225     *    Sets a widget value within the form.
226     *    @param SimpleSelector $selector   Criteria to apply.
227     *    @param string $value              Value to input into the widget.
228     *    @return boolean                   True if value is legal, false
229     *                                      otherwise. If the field is not
230     *                                      present, nothing will be set.
231     *    @access public
232     */
233    function setField($selector, $value, $position=false) {
234        $success = false;
235        $_position = 0;
236        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
237            if ($selector->isMatch($this->widgets[$i])) {
238                $_position++;
239                if ($position === false or $_position === (int)$position) {
240                    if ($this->widgets[$i]->setValue($value)) {
241                        $success = true;
242                    }
243                }
244            }
245        }
246        return $success;
247    }
248
249    /**
250     *    Used by the page object to set widgets labels to
251     *    external label tags.
252     *    @param SimpleSelector $selector   Criteria to apply.
253     *    @access public
254     */
255    function attachLabelBySelector($selector, $label) {
256        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
257            if ($selector->isMatch($this->widgets[$i])) {
258                if (method_exists($this->widgets[$i], 'setLabel')) {
259                    $this->widgets[$i]->setLabel($label);
260                    return;
261                }
262            }
263        }
264    }
265
266    /**
267     *    Test to see if a form has a submit button.
268     *    @param SimpleSelector $selector   Criteria to apply.
269     *    @return boolean                   True if present.
270     *    @access public
271     */
272    function hasSubmit($selector) {
273        foreach ($this->buttons as $button) {
274            if ($selector->isMatch($button)) {
275                return true;
276            }
277        }
278        return false;
279    }
280
281    /**
282     *    Test to see if a form has an image control.
283     *    @param SimpleSelector $selector   Criteria to apply.
284     *    @return boolean                   True if present.
285     *    @access public
286     */
287    function hasImage($selector) {
288        foreach ($this->images as $image) {
289            if ($selector->isMatch($image)) {
290                return true;
291            }
292        }
293        return false;
294    }
295
296    /**
297     *    Gets the submit values for a selected button.
298     *    @param SimpleSelector $selector   Criteria to apply.
299     *    @param hash $additional           Additional data for the form.
300     *    @return SimpleEncoding            Submitted values or false
301     *                                      if there is no such button
302     *                                      in the form.
303     *    @access public
304     */
305    function submitButton($selector, $additional = false) {
306        $additional = $additional ? $additional : array();
307        foreach ($this->buttons as $button) {
308            if ($selector->isMatch($button)) {
309                $encoding = $this->encode();
310                $button->write($encoding);
311                if ($additional) {
312                    $encoding->merge($additional);
313                }
314                return $encoding;
315            }
316        }
317        return false;
318    }
319
320    /**
321     *    Gets the submit values for an image.
322     *    @param SimpleSelector $selector   Criteria to apply.
323     *    @param integer $x                 X-coordinate of click.
324     *    @param integer $y                 Y-coordinate of click.
325     *    @param hash $additional           Additional data for the form.
326     *    @return SimpleEncoding            Submitted values or false
327     *                                      if there is no such button in the
328     *                                      form.
329     *    @access public
330     */
331    function submitImage($selector, $x, $y, $additional = false) {
332        $additional = $additional ? $additional : array();
333        foreach ($this->images as $image) {
334            if ($selector->isMatch($image)) {
335                $encoding = $this->encode();
336                $image->write($encoding, $x, $y);
337                if ($additional) {
338                    $encoding->merge($additional);
339                }
340                return $encoding;
341            }
342        }
343        return false;
344    }
345
346    /**
347     *    Simply submits the form without the submit button
348     *    value. Used when there is only one button or it
349     *    is unimportant.
350     *    @return hash           Submitted values.
351     *    @access public
352     */
353    function submit($additional = false) {
354        $encoding = $this->encode();
355        if ($additional) {
356            $encoding->merge($additional);
357        }
358        return $encoding;
359    }
360}
361?>