361 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 *  Base include file for SimpleTest.
 | 
						|
 *  @package    SimpleTest
 | 
						|
 *  @subpackage WebTester
 | 
						|
 *  @version    $Id: form.php 2013 2011-04-29 09:29:45Z pp11 $
 | 
						|
 */
 | 
						|
 | 
						|
/**#@+
 | 
						|
 * include SimpleTest files
 | 
						|
 */
 | 
						|
require_once(dirname(__FILE__) . '/tag.php');
 | 
						|
require_once(dirname(__FILE__) . '/encoding.php');
 | 
						|
require_once(dirname(__FILE__) . '/selector.php');
 | 
						|
/**#@-*/
 | 
						|
 | 
						|
/**
 | 
						|
 *    Form tag class to hold widget values.
 | 
						|
 *    @package SimpleTest
 | 
						|
 *    @subpackage WebTester
 | 
						|
 */
 | 
						|
class SimpleForm {
 | 
						|
    private $method;
 | 
						|
    private $action;
 | 
						|
    private $encoding;
 | 
						|
    private $default_target;
 | 
						|
    private $id;
 | 
						|
    private $buttons;
 | 
						|
    private $images;
 | 
						|
    private $widgets;
 | 
						|
    private $radios;
 | 
						|
    private $checkboxes;
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Starts with no held controls/widgets.
 | 
						|
     *    @param SimpleTag $tag        Form tag to read.
 | 
						|
     *    @param SimplePage $page      Holding page.
 | 
						|
     */
 | 
						|
    function __construct($tag, $page) {
 | 
						|
        $this->method = $tag->getAttribute('method');
 | 
						|
        $this->action = $this->createAction($tag->getAttribute('action'), $page);
 | 
						|
        $this->encoding = $this->setEncodingClass($tag);
 | 
						|
        $this->default_target = false;
 | 
						|
        $this->id = $tag->getAttribute('id');
 | 
						|
        $this->buttons = array();
 | 
						|
        $this->images = array();
 | 
						|
        $this->widgets = array();
 | 
						|
        $this->radios = array();
 | 
						|
        $this->checkboxes = array();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Creates the request packet to be sent by the form.
 | 
						|
     *    @param SimpleTag $tag        Form tag to read.
 | 
						|
     *    @return string               Packet class.
 | 
						|
     *    @access private
 | 
						|
     */
 | 
						|
    protected function setEncodingClass($tag) {
 | 
						|
        if (strtolower($tag->getAttribute('method')) == 'post') {
 | 
						|
            if (strtolower($tag->getAttribute('enctype')) == 'multipart/form-data') {
 | 
						|
                return 'SimpleMultipartEncoding';
 | 
						|
            }
 | 
						|
            return 'SimplePostEncoding';
 | 
						|
        }
 | 
						|
        return 'SimpleGetEncoding';
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Sets the frame target within a frameset.
 | 
						|
     *    @param string $frame        Name of frame.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function setDefaultTarget($frame) {
 | 
						|
        $this->default_target = $frame;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Accessor for method of form submission.
 | 
						|
     *    @return string           Either get or post.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function getMethod() {
 | 
						|
        return ($this->method ? strtolower($this->method) : 'get');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Combined action attribute with current location
 | 
						|
     *    to get an absolute form target.
 | 
						|
     *    @param string $action    Action attribute from form tag.
 | 
						|
     *    @param SimpleUrl $base   Page location.
 | 
						|
     *    @return SimpleUrl        Absolute form target.
 | 
						|
     */
 | 
						|
    protected function createAction($action, $page) {
 | 
						|
        if (($action === '') || ($action === false)) {
 | 
						|
            return $page->expandUrl($page->getUrl());
 | 
						|
        }
 | 
						|
        return $page->expandUrl(new SimpleUrl($action));;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Absolute URL of the target.
 | 
						|
     *    @return SimpleUrl           URL target.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function getAction() {
 | 
						|
        $url = $this->action;
 | 
						|
        if ($this->default_target && ! $url->getTarget()) {
 | 
						|
            $url->setTarget($this->default_target);
 | 
						|
        }
 | 
						|
        if ($this->getMethod() == 'get') {
 | 
						|
            $url->clearRequest();
 | 
						|
        }
 | 
						|
        return $url;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Creates the encoding for the current values in the
 | 
						|
     *    form.
 | 
						|
     *    @return SimpleFormEncoding    Request to submit.
 | 
						|
     *    @access private
 | 
						|
     */
 | 
						|
    protected function encode() {
 | 
						|
        $class = $this->encoding;
 | 
						|
        $encoding = new $class();
 | 
						|
        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
 | 
						|
            $this->widgets[$i]->write($encoding);
 | 
						|
        }
 | 
						|
        return $encoding;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    ID field of form for unique identification.
 | 
						|
     *    @return string           Unique tag ID.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function getId() {
 | 
						|
        return $this->id;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Adds a tag contents to the form.
 | 
						|
     *    @param SimpleWidget $tag        Input tag to add.
 | 
						|
     */
 | 
						|
    function addWidget($tag) {
 | 
						|
        if (strtolower($tag->getAttribute('type')) == 'submit') {
 | 
						|
            $this->buttons[] = $tag;
 | 
						|
        } elseif (strtolower($tag->getAttribute('type')) == 'image') {
 | 
						|
            $this->images[] = $tag;
 | 
						|
        } elseif ($tag->getName()) {
 | 
						|
            $this->setWidget($tag);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Sets the widget into the form, grouping radio
 | 
						|
     *    buttons if any.
 | 
						|
     *    @param SimpleWidget $tag   Incoming form control.
 | 
						|
     *    @access private
 | 
						|
     */
 | 
						|
    protected function setWidget($tag) {
 | 
						|
        if (strtolower($tag->getAttribute('type')) == 'radio') {
 | 
						|
            $this->addRadioButton($tag);
 | 
						|
        } elseif (strtolower($tag->getAttribute('type')) == 'checkbox') {
 | 
						|
            $this->addCheckbox($tag);
 | 
						|
        } else {
 | 
						|
            $this->widgets[] = &$tag;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Adds a radio button, building a group if necessary.
 | 
						|
     *    @param SimpleRadioButtonTag $tag   Incoming form control.
 | 
						|
     *    @access private
 | 
						|
     */
 | 
						|
    protected function addRadioButton($tag) {
 | 
						|
        if (! isset($this->radios[$tag->getName()])) {
 | 
						|
            $this->widgets[] = new SimpleRadioGroup();
 | 
						|
            $this->radios[$tag->getName()] = count($this->widgets) - 1;
 | 
						|
        }
 | 
						|
        $this->widgets[$this->radios[$tag->getName()]]->addWidget($tag);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Adds a checkbox, making it a group on a repeated name.
 | 
						|
     *    @param SimpleCheckboxTag $tag   Incoming form control.
 | 
						|
     *    @access private
 | 
						|
     */
 | 
						|
    protected function addCheckbox($tag) {
 | 
						|
        if (! isset($this->checkboxes[$tag->getName()])) {
 | 
						|
            $this->widgets[] = $tag;
 | 
						|
            $this->checkboxes[$tag->getName()] = count($this->widgets) - 1;
 | 
						|
        } else {
 | 
						|
            $index = $this->checkboxes[$tag->getName()];
 | 
						|
            if (! SimpleTestCompatibility::isA($this->widgets[$index], 'SimpleCheckboxGroup')) {
 | 
						|
                $previous = $this->widgets[$index];
 | 
						|
                $this->widgets[$index] = new SimpleCheckboxGroup();
 | 
						|
                $this->widgets[$index]->addWidget($previous);
 | 
						|
            }
 | 
						|
            $this->widgets[$index]->addWidget($tag);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Extracts current value from form.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @return string/array              Value(s) as string or null
 | 
						|
     *                                      if not set.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function getValue($selector) {
 | 
						|
        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
 | 
						|
            if ($selector->isMatch($this->widgets[$i])) {
 | 
						|
                return $this->widgets[$i]->getValue();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        foreach ($this->buttons as $button) {
 | 
						|
            if ($selector->isMatch($button)) {
 | 
						|
                return $button->getValue();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Sets a widget value within the form.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @param string $value              Value to input into the widget.
 | 
						|
     *    @return boolean                   True if value is legal, false
 | 
						|
     *                                      otherwise. If the field is not
 | 
						|
     *                                      present, nothing will be set.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function setField($selector, $value, $position=false) {
 | 
						|
        $success = false;
 | 
						|
        $_position = 0;
 | 
						|
        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
 | 
						|
            if ($selector->isMatch($this->widgets[$i])) {
 | 
						|
                $_position++;
 | 
						|
                if ($position === false or $_position === (int)$position) {
 | 
						|
                    if ($this->widgets[$i]->setValue($value)) {
 | 
						|
                        $success = true;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return $success;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Used by the page object to set widgets labels to
 | 
						|
     *    external label tags.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function attachLabelBySelector($selector, $label) {
 | 
						|
        for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
 | 
						|
            if ($selector->isMatch($this->widgets[$i])) {
 | 
						|
                if (method_exists($this->widgets[$i], 'setLabel')) {
 | 
						|
                    $this->widgets[$i]->setLabel($label);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Test to see if a form has a submit button.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @return boolean                   True if present.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function hasSubmit($selector) {
 | 
						|
        foreach ($this->buttons as $button) {
 | 
						|
            if ($selector->isMatch($button)) {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Test to see if a form has an image control.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @return boolean                   True if present.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function hasImage($selector) {
 | 
						|
        foreach ($this->images as $image) {
 | 
						|
            if ($selector->isMatch($image)) {
 | 
						|
                return true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Gets the submit values for a selected button.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @param hash $additional           Additional data for the form.
 | 
						|
     *    @return SimpleEncoding            Submitted values or false
 | 
						|
     *                                      if there is no such button
 | 
						|
     *                                      in the form.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function submitButton($selector, $additional = false) {
 | 
						|
        $additional = $additional ? $additional : array();
 | 
						|
        foreach ($this->buttons as $button) {
 | 
						|
            if ($selector->isMatch($button)) {
 | 
						|
                $encoding = $this->encode();
 | 
						|
                $button->write($encoding);
 | 
						|
                if ($additional) {
 | 
						|
                    $encoding->merge($additional);
 | 
						|
                }
 | 
						|
                return $encoding;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Gets the submit values for an image.
 | 
						|
     *    @param SimpleSelector $selector   Criteria to apply.
 | 
						|
     *    @param integer $x                 X-coordinate of click.
 | 
						|
     *    @param integer $y                 Y-coordinate of click.
 | 
						|
     *    @param hash $additional           Additional data for the form.
 | 
						|
     *    @return SimpleEncoding            Submitted values or false
 | 
						|
     *                                      if there is no such button in the
 | 
						|
     *                                      form.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function submitImage($selector, $x, $y, $additional = false) {
 | 
						|
        $additional = $additional ? $additional : array();
 | 
						|
        foreach ($this->images as $image) {
 | 
						|
            if ($selector->isMatch($image)) {
 | 
						|
                $encoding = $this->encode();
 | 
						|
                $image->write($encoding, $x, $y);
 | 
						|
                if ($additional) {
 | 
						|
                    $encoding->merge($additional);
 | 
						|
                }
 | 
						|
                return $encoding;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     *    Simply submits the form without the submit button
 | 
						|
     *    value. Used when there is only one button or it
 | 
						|
     *    is unimportant.
 | 
						|
     *    @return hash           Submitted values.
 | 
						|
     *    @access public
 | 
						|
     */
 | 
						|
    function submit($additional = false) {
 | 
						|
        $encoding = $this->encode();
 | 
						|
        if ($additional) {
 | 
						|
            $encoding->merge($additional);
 | 
						|
        }
 | 
						|
        return $encoding;
 | 
						|
    }
 | 
						|
}
 | 
						|
?>
 |