20553c1afe
This reverts commit dccdeca258
.
1527 lines
No EOL
41 KiB
PHP
1527 lines
No EOL
41 KiB
PHP
<?php
|
|
/**
|
|
* Base include file for SimpleTest.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
* @version $Id: tag.php 2011 2011-04-29 08:22:48Z pp11 $
|
|
*/
|
|
|
|
/**#@+
|
|
* include SimpleTest files
|
|
*/
|
|
require_once(dirname(__FILE__) . '/page.php');
|
|
require_once(dirname(__FILE__) . '/encoding.php');
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Creates tags and widgets given HTML tag
|
|
* attributes.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTagBuilder {
|
|
|
|
/**
|
|
* Factory for the tag objects. Creates the
|
|
* appropriate tag object for the incoming tag name
|
|
* and attributes.
|
|
* @param string $name HTML tag name.
|
|
* @param hash $attributes Element attributes.
|
|
* @return SimpleTag Tag object.
|
|
* @access public
|
|
*/
|
|
function createTag($name, $attributes) {
|
|
static $map = array(
|
|
'a' => 'SimpleAnchorTag',
|
|
'title' => 'SimpleTitleTag',
|
|
'base' => 'SimpleBaseTag',
|
|
'button' => 'SimpleButtonTag',
|
|
'textarea' => 'SimpleTextAreaTag',
|
|
'option' => 'SimpleOptionTag',
|
|
'label' => 'SimpleLabelTag',
|
|
'form' => 'SimpleFormTag',
|
|
'frame' => 'SimpleFrameTag');
|
|
$attributes = $this->keysToLowerCase($attributes);
|
|
if (array_key_exists($name, $map)) {
|
|
$tag_class = $map[$name];
|
|
return new $tag_class($attributes);
|
|
} elseif ($name == 'select') {
|
|
return $this->createSelectionTag($attributes);
|
|
} elseif ($name == 'input') {
|
|
return $this->createInputTag($attributes);
|
|
}
|
|
return new SimpleTag($name, $attributes);
|
|
}
|
|
|
|
/**
|
|
* Factory for selection fields.
|
|
* @param hash $attributes Element attributes.
|
|
* @return SimpleTag Tag object.
|
|
* @access protected
|
|
*/
|
|
protected function createSelectionTag($attributes) {
|
|
if (isset($attributes['multiple'])) {
|
|
return new MultipleSelectionTag($attributes);
|
|
}
|
|
return new SimpleSelectionTag($attributes);
|
|
}
|
|
|
|
/**
|
|
* Factory for input tags.
|
|
* @param hash $attributes Element attributes.
|
|
* @return SimpleTag Tag object.
|
|
* @access protected
|
|
*/
|
|
protected function createInputTag($attributes) {
|
|
if (! isset($attributes['type'])) {
|
|
return new SimpleTextTag($attributes);
|
|
}
|
|
$type = strtolower(trim($attributes['type']));
|
|
$map = array(
|
|
'submit' => 'SimpleSubmitTag',
|
|
'image' => 'SimpleImageSubmitTag',
|
|
'checkbox' => 'SimpleCheckboxTag',
|
|
'radio' => 'SimpleRadioButtonTag',
|
|
'text' => 'SimpleTextTag',
|
|
'hidden' => 'SimpleTextTag',
|
|
'password' => 'SimpleTextTag',
|
|
'file' => 'SimpleUploadTag');
|
|
if (array_key_exists($type, $map)) {
|
|
$tag_class = $map[$type];
|
|
return new $tag_class($attributes);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Make the keys lower case for case insensitive look-ups.
|
|
* @param hash $map Hash to convert.
|
|
* @return hash Unchanged values, but keys lower case.
|
|
* @access private
|
|
*/
|
|
protected function keysToLowerCase($map) {
|
|
$lower = array();
|
|
foreach ($map as $key => $value) {
|
|
$lower[strtolower($key)] = $value;
|
|
}
|
|
return $lower;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* HTML or XML tag.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTag {
|
|
private $name;
|
|
private $attributes;
|
|
private $content;
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param string $name Tag name.
|
|
* @param hash $attributes Attribute names and
|
|
* string values. Note that
|
|
* the keys must have been
|
|
* converted to lower case.
|
|
*/
|
|
function __construct($name, $attributes) {
|
|
$this->name = strtolower(trim($name));
|
|
$this->attributes = $attributes;
|
|
$this->content = '';
|
|
}
|
|
|
|
/**
|
|
* Check to see if the tag can have both start and
|
|
* end tags with content in between.
|
|
* @return boolean True if content allowed.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* The current tag should not swallow all content for
|
|
* itself as it's searchable page content. Private
|
|
* content tags are usually widgets that contain default
|
|
* values.
|
|
* @return boolean False as content is available
|
|
* to other tags by default.
|
|
* @access public
|
|
*/
|
|
function isPrivateContent() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Appends string content to the current content.
|
|
* @param string $content Additional text.
|
|
* @access public
|
|
*/
|
|
function addContent($content) {
|
|
$this->content .= (string)$content;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Adds an enclosed tag to the content.
|
|
* @param SimpleTag $tag New tag.
|
|
* @access public
|
|
*/
|
|
function addTag($tag) {
|
|
}
|
|
|
|
/**
|
|
* Adds multiple enclosed tags to the content.
|
|
* @param array List of SimpleTag objects to be added.
|
|
*/
|
|
function addTags($tags) {
|
|
foreach ($tags as $tag) {
|
|
$this->addTag($tag);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accessor for tag name.
|
|
* @return string Name of tag.
|
|
* @access public
|
|
*/
|
|
function getTagName() {
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* List of legal child elements.
|
|
* @return array List of element names.
|
|
* @access public
|
|
*/
|
|
function getChildElements() {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Accessor for an attribute.
|
|
* @param string $label Attribute name.
|
|
* @return string Attribute value.
|
|
* @access public
|
|
*/
|
|
function getAttribute($label) {
|
|
$label = strtolower($label);
|
|
if (! isset($this->attributes[$label])) {
|
|
return false;
|
|
}
|
|
return (string)$this->attributes[$label];
|
|
}
|
|
|
|
/**
|
|
* Sets an attribute.
|
|
* @param string $label Attribute name.
|
|
* @return string $value New attribute value.
|
|
* @access protected
|
|
*/
|
|
protected function setAttribute($label, $value) {
|
|
$this->attributes[strtolower($label)] = $value;
|
|
}
|
|
|
|
/**
|
|
* Accessor for the whole content so far.
|
|
* @return string Content as big raw string.
|
|
* @access public
|
|
*/
|
|
function getContent() {
|
|
return $this->content;
|
|
}
|
|
|
|
/**
|
|
* Accessor for content reduced to visible text. Acts
|
|
* like a text mode browser, normalising space and
|
|
* reducing images to their alt text.
|
|
* @return string Content as plain text.
|
|
* @access public
|
|
*/
|
|
function getText() {
|
|
return SimplePage::normalise($this->content);
|
|
}
|
|
|
|
/**
|
|
* Test to see if id attribute matches.
|
|
* @param string $id ID to test against.
|
|
* @return boolean True on match.
|
|
* @access public
|
|
*/
|
|
function isId($id) {
|
|
return ($this->getAttribute('id') == $id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base url.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleBaseTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('base', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Base tag is not a block tag.
|
|
* @return boolean false
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Page title.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTitleTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('title', $attributes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Link.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleAnchorTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('a', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Accessor for URL as string.
|
|
* @return string Coerced as string.
|
|
* @access public
|
|
*/
|
|
function getHref() {
|
|
$url = $this->getAttribute('href');
|
|
if (is_bool($url)) {
|
|
$url = '';
|
|
}
|
|
return $url;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Form element.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleWidget extends SimpleTag {
|
|
private $value;
|
|
private $label;
|
|
private $is_set;
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param string $name Tag name.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($name, $attributes) {
|
|
parent::__construct($name, $attributes);
|
|
$this->value = false;
|
|
$this->label = false;
|
|
$this->is_set = false;
|
|
}
|
|
|
|
/**
|
|
* Accessor for name submitted as the key in
|
|
* GET/POST privateiables hash.
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getName() {
|
|
return $this->getAttribute('name');
|
|
}
|
|
|
|
/**
|
|
* Accessor for default value parsed with the tag.
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
return $this->getAttribute('value');
|
|
}
|
|
|
|
/**
|
|
* Accessor for currently set value or default if
|
|
* none.
|
|
* @return string Value set by form or default
|
|
* if none.
|
|
* @access public
|
|
*/
|
|
function getValue() {
|
|
if (! $this->is_set) {
|
|
return $this->getDefault();
|
|
}
|
|
return $this->value;
|
|
}
|
|
|
|
/**
|
|
* Sets the current form element value.
|
|
* @param string $value New value.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
$this->value = $value;
|
|
$this->is_set = true;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Resets the form element value back to the
|
|
* default.
|
|
* @access public
|
|
*/
|
|
function resetValue() {
|
|
$this->is_set = false;
|
|
}
|
|
|
|
/**
|
|
* Allows setting of a label externally, say by a
|
|
* label tag.
|
|
* @param string $label Label to attach.
|
|
* @access public
|
|
*/
|
|
function setLabel($label) {
|
|
$this->label = trim($label);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Reads external or internal label.
|
|
* @param string $label Label to test.
|
|
* @return boolean True is match.
|
|
* @access public
|
|
*/
|
|
function isLabel($label) {
|
|
return $this->label == trim($label);
|
|
}
|
|
|
|
/**
|
|
* Dispatches the value into the form encoded packet.
|
|
* @param SimpleEncoding $encoding Form packet.
|
|
* @access public
|
|
*/
|
|
function write($encoding) {
|
|
if ($this->getName()) {
|
|
$encoding->add($this->getName(), $this->getValue());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Text, password and hidden field.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTextTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
if ($this->getAttribute('value') === false) {
|
|
$this->setAttribute('value', '');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag contains no content.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets the current form element value. Cannot
|
|
* change the value of a hidden field.
|
|
* @param string $value New value.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
if ($this->getAttribute('type') == 'hidden') {
|
|
return false;
|
|
}
|
|
return parent::setValue($value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Submit button as input tag.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleSubmitTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
if ($this->getAttribute('value') === false) {
|
|
$this->setAttribute('value', 'Submit');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag contains no end element.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Disables the setting of the button value.
|
|
* @param string $value Ignored.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Value of browser visible text.
|
|
* @return string Visible label.
|
|
* @access public
|
|
*/
|
|
function getLabel() {
|
|
return $this->getValue();
|
|
}
|
|
|
|
/**
|
|
* Test for a label match when searching.
|
|
* @param string $label Label to test.
|
|
* @return boolean True on match.
|
|
* @access public
|
|
*/
|
|
function isLabel($label) {
|
|
return trim($label) == trim($this->getLabel());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Image button as input tag.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleImageSubmitTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Tag contains no end element.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Disables the setting of the button value.
|
|
* @param string $value Ignored.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Value of browser visible text.
|
|
* @return string Visible label.
|
|
* @access public
|
|
*/
|
|
function getLabel() {
|
|
if ($this->getAttribute('title')) {
|
|
return $this->getAttribute('title');
|
|
}
|
|
return $this->getAttribute('alt');
|
|
}
|
|
|
|
/**
|
|
* Test for a label match when searching.
|
|
* @param string $label Label to test.
|
|
* @return boolean True on match.
|
|
* @access public
|
|
*/
|
|
function isLabel($label) {
|
|
return trim($label) == trim($this->getLabel());
|
|
}
|
|
|
|
/**
|
|
* Dispatches the value into the form encoded packet.
|
|
* @param SimpleEncoding $encoding Form packet.
|
|
* @param integer $x X coordinate of click.
|
|
* @param integer $y Y coordinate of click.
|
|
* @access public
|
|
*/
|
|
function write($encoding, $x = 1, $y = 1) {
|
|
if ($this->getName()) {
|
|
$encoding->add($this->getName() . '.x', $x);
|
|
$encoding->add($this->getName() . '.y', $y);
|
|
} else {
|
|
$encoding->add('x', $x);
|
|
$encoding->add('y', $y);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Submit button as button tag.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleButtonTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* Defaults are very browser dependent.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('button', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Check to see if the tag can have both start and
|
|
* end tags with content in between.
|
|
* @return boolean True if content allowed.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Disables the setting of the button value.
|
|
* @param string $value Ignored.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Value of browser visible text.
|
|
* @return string Visible label.
|
|
* @access public
|
|
*/
|
|
function getLabel() {
|
|
return $this->getContent();
|
|
}
|
|
|
|
/**
|
|
* Test for a label match when searching.
|
|
* @param string $label Label to test.
|
|
* @return boolean True on match.
|
|
* @access public
|
|
*/
|
|
function isLabel($label) {
|
|
return trim($label) == trim($this->getLabel());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Content tag for text area.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTextAreaTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('textarea', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value.
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
return $this->wrap(html_entity_decode($this->getContent(), ENT_QUOTES));
|
|
}
|
|
|
|
/**
|
|
* Applies word wrapping if needed.
|
|
* @param string $value New value.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
return parent::setValue($this->wrap($value));
|
|
}
|
|
|
|
/**
|
|
* Test to see if text should be wrapped.
|
|
* @return boolean True if wrapping on.
|
|
* @access private
|
|
*/
|
|
function wrapIsEnabled() {
|
|
if ($this->getAttribute('cols')) {
|
|
$wrap = $this->getAttribute('wrap');
|
|
if (($wrap == 'physical') || ($wrap == 'hard')) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Performs the formatting that is peculiar to
|
|
* this tag. There is strange behaviour in this
|
|
* one, including stripping a leading new line.
|
|
* Go figure. I am using Firefox as a guide.
|
|
* @param string $text Text to wrap.
|
|
* @return string Text wrapped with carriage
|
|
* returns and line feeds
|
|
* @access private
|
|
*/
|
|
protected function wrap($text) {
|
|
$text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text));
|
|
$text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text));
|
|
if (strncmp($text, "\r\n", strlen("\r\n")) == 0) {
|
|
$text = substr($text, strlen("\r\n"));
|
|
}
|
|
if ($this->wrapIsEnabled()) {
|
|
return wordwrap(
|
|
$text,
|
|
(integer)$this->getAttribute('cols'),
|
|
"\r\n");
|
|
}
|
|
return $text;
|
|
}
|
|
|
|
/**
|
|
* The content of textarea is not part of the page.
|
|
* @return boolean True.
|
|
* @access public
|
|
*/
|
|
function isPrivateContent() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* File upload widget.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleUploadTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Tag contains no content.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Dispatches the value into the form encoded packet.
|
|
* @param SimpleEncoding $encoding Form packet.
|
|
* @access public
|
|
*/
|
|
function write($encoding) {
|
|
if (! file_exists($this->getValue())) {
|
|
return;
|
|
}
|
|
$encoding->attach(
|
|
$this->getName(),
|
|
implode('', file($this->getValue())),
|
|
basename($this->getValue()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drop down widget.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleSelectionTag extends SimpleWidget {
|
|
private $options;
|
|
private $choice;
|
|
|
|
/**
|
|
* Starts with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('select', $attributes);
|
|
$this->options = array();
|
|
$this->choice = false;
|
|
}
|
|
|
|
/**
|
|
* Adds an option tag to a selection field.
|
|
* @param SimpleOptionTag $tag New option.
|
|
* @access public
|
|
*/
|
|
function addTag($tag) {
|
|
if ($tag->getTagName() == 'option') {
|
|
$this->options[] = $tag;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Text within the selection element is ignored.
|
|
* @param string $content Ignored.
|
|
* @access public
|
|
*/
|
|
function addContent($content) {
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Scans options for defaults. If none, then
|
|
* the first option is selected.
|
|
* @return string Selected field.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
for ($i = 0, $count = count($this->options); $i < $count; $i++) {
|
|
if ($this->options[$i]->getAttribute('selected') !== false) {
|
|
return $this->options[$i]->getDefault();
|
|
}
|
|
}
|
|
if ($count > 0) {
|
|
return $this->options[0]->getDefault();
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Can only set allowed values.
|
|
* @param string $value New choice.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
for ($i = 0, $count = count($this->options); $i < $count; $i++) {
|
|
if ($this->options[$i]->isValue($value)) {
|
|
$this->choice = $i;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Accessor for current selection value.
|
|
* @return string Value attribute or
|
|
* content of opton.
|
|
* @access public
|
|
*/
|
|
function getValue() {
|
|
if ($this->choice === false) {
|
|
return $this->getDefault();
|
|
}
|
|
return $this->options[$this->choice]->getValue();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drop down widget.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class MultipleSelectionTag extends SimpleWidget {
|
|
private $options;
|
|
private $values;
|
|
|
|
/**
|
|
* Starts with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('select', $attributes);
|
|
$this->options = array();
|
|
$this->values = false;
|
|
}
|
|
|
|
/**
|
|
* Adds an option tag to a selection field.
|
|
* @param SimpleOptionTag $tag New option.
|
|
* @access public
|
|
*/
|
|
function addTag($tag) {
|
|
if ($tag->getTagName() == 'option') {
|
|
$this->options[] = &$tag;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Text within the selection element is ignored.
|
|
* @param string $content Ignored.
|
|
* @access public
|
|
*/
|
|
function addContent($content) {
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Scans options for defaults to populate the
|
|
* value array().
|
|
* @return array Selected fields.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
$default = array();
|
|
for ($i = 0, $count = count($this->options); $i < $count; $i++) {
|
|
if ($this->options[$i]->getAttribute('selected') !== false) {
|
|
$default[] = $this->options[$i]->getDefault();
|
|
}
|
|
}
|
|
return $default;
|
|
}
|
|
|
|
/**
|
|
* Can only set allowed values. Any illegal value
|
|
* will result in a failure, but all correct values
|
|
* will be set.
|
|
* @param array $desired New choices.
|
|
* @return boolean True if all allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($desired) {
|
|
$achieved = array();
|
|
foreach ($desired as $value) {
|
|
$success = false;
|
|
for ($i = 0, $count = count($this->options); $i < $count; $i++) {
|
|
if ($this->options[$i]->isValue($value)) {
|
|
$achieved[] = $this->options[$i]->getValue();
|
|
$success = true;
|
|
break;
|
|
}
|
|
}
|
|
if (! $success) {
|
|
return false;
|
|
}
|
|
}
|
|
$this->values = $achieved;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Accessor for current selection value.
|
|
* @return array List of currently set options.
|
|
* @access public
|
|
*/
|
|
function getValue() {
|
|
if ($this->values === false) {
|
|
return $this->getDefault();
|
|
}
|
|
return $this->values;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Option for selection field.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleOptionTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Stashes the attributes.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('option', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Does nothing.
|
|
* @param string $value Ignored.
|
|
* @return boolean Not allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Test to see if a value matches the option.
|
|
* @param string $compare Value to compare with.
|
|
* @return boolean True if possible match.
|
|
* @access public
|
|
*/
|
|
function isValue($compare) {
|
|
$compare = trim($compare);
|
|
if (trim($this->getValue()) == $compare) {
|
|
return true;
|
|
}
|
|
return trim(strip_tags($this->getContent())) == $compare;
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value. Will be set to
|
|
* the option label if no value exists.
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
if ($this->getAttribute('value') === false) {
|
|
return strip_tags($this->getContent());
|
|
}
|
|
return $this->getAttribute('value');
|
|
}
|
|
|
|
/**
|
|
* The content of options is not part of the page.
|
|
* @return boolean True.
|
|
* @access public
|
|
*/
|
|
function isPrivateContent() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Radio button.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleRadioButtonTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Stashes the attributes.
|
|
* @param array $attributes Hash of attributes.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
if ($this->getAttribute('value') === false) {
|
|
$this->setAttribute('value', 'on');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag contains no content.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* The only allowed value sn the one in the
|
|
* "value" attribute.
|
|
* @param string $value New value.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
if ($value === false) {
|
|
return parent::setValue($value);
|
|
}
|
|
if ($value != $this->getAttribute('value')) {
|
|
return false;
|
|
}
|
|
return parent::setValue($value);
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value.
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
if ($this->getAttribute('checked') !== false) {
|
|
return $this->getAttribute('value');
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checkbox widget.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleCheckboxTag extends SimpleWidget {
|
|
|
|
/**
|
|
* Starts with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('input', $attributes);
|
|
if ($this->getAttribute('value') === false) {
|
|
$this->setAttribute('value', 'on');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag contains no content.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* The only allowed value in the one in the
|
|
* "value" attribute. The default for this
|
|
* attribute is "on". If this widget is set to
|
|
* true, then the usual value will be taken.
|
|
* @param string $value New value.
|
|
* @return boolean True if allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
if ($value === false) {
|
|
return parent::setValue($value);
|
|
}
|
|
if ($value === true) {
|
|
return parent::setValue($this->getAttribute('value'));
|
|
}
|
|
if ($value != $this->getAttribute('value')) {
|
|
return false;
|
|
}
|
|
return parent::setValue($value);
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value. The default
|
|
* value is "on".
|
|
* @return string Parsed value.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
if ($this->getAttribute('checked') !== false) {
|
|
return $this->getAttribute('value');
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A group of multiple widgets with some shared behaviour.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleTagGroup {
|
|
private $widgets = array();
|
|
|
|
/**
|
|
* Adds a tag to the group.
|
|
* @param SimpleWidget $widget
|
|
* @access public
|
|
*/
|
|
function addWidget($widget) {
|
|
$this->widgets[] = $widget;
|
|
}
|
|
|
|
/**
|
|
* Accessor to widget set.
|
|
* @return array All widgets.
|
|
* @access protected
|
|
*/
|
|
protected function &getWidgets() {
|
|
return $this->widgets;
|
|
}
|
|
|
|
/**
|
|
* Accessor for an attribute.
|
|
* @param string $label Attribute name.
|
|
* @return boolean Always false.
|
|
* @access public
|
|
*/
|
|
function getAttribute($label) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Fetches the name for the widget from the first
|
|
* member.
|
|
* @return string Name of widget.
|
|
* @access public
|
|
*/
|
|
function getName() {
|
|
if (count($this->widgets) > 0) {
|
|
return $this->widgets[0]->getName();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Scans the widgets for one with the appropriate
|
|
* ID field.
|
|
* @param string $id ID value to try.
|
|
* @return boolean True if matched.
|
|
* @access public
|
|
*/
|
|
function isId($id) {
|
|
for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
|
|
if ($this->widgets[$i]->isId($id)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Scans the widgets for one with the appropriate
|
|
* attached label.
|
|
* @param string $label Attached label to try.
|
|
* @return boolean True if matched.
|
|
* @access public
|
|
*/
|
|
function isLabel($label) {
|
|
for ($i = 0, $count = count($this->widgets); $i < $count; $i++) {
|
|
if ($this->widgets[$i]->isLabel($label)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Dispatches the value into the form encoded packet.
|
|
* @param SimpleEncoding $encoding Form packet.
|
|
* @access public
|
|
*/
|
|
function write($encoding) {
|
|
$encoding->add($this->getName(), $this->getValue());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A group of tags with the same name within a form.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleCheckboxGroup extends SimpleTagGroup {
|
|
|
|
/**
|
|
* Accessor for current selected widget or false
|
|
* if none.
|
|
* @return string/array Widget values or false if none.
|
|
* @access public
|
|
*/
|
|
function getValue() {
|
|
$values = array();
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if ($widgets[$i]->getValue() !== false) {
|
|
$values[] = $widgets[$i]->getValue();
|
|
}
|
|
}
|
|
return $this->coerceValues($values);
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value that is active.
|
|
* @return string/array Widget values or false if none.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
$values = array();
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if ($widgets[$i]->getDefault() !== false) {
|
|
$values[] = $widgets[$i]->getDefault();
|
|
}
|
|
}
|
|
return $this->coerceValues($values);
|
|
}
|
|
|
|
/**
|
|
* Accessor for current set values.
|
|
* @param string/array/boolean $values Either a single string, a
|
|
* hash or false for nothing set.
|
|
* @return boolean True if all values can be set.
|
|
* @access public
|
|
*/
|
|
function setValue($values) {
|
|
$values = $this->makeArray($values);
|
|
if (! $this->valuesArePossible($values)) {
|
|
return false;
|
|
}
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
$possible = $widgets[$i]->getAttribute('value');
|
|
if (in_array($widgets[$i]->getAttribute('value'), $values)) {
|
|
$widgets[$i]->setValue($possible);
|
|
} else {
|
|
$widgets[$i]->setValue(false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Tests to see if a possible value set is legal.
|
|
* @param string/array/boolean $values Either a single string, a
|
|
* hash or false for nothing set.
|
|
* @return boolean False if trying to set a
|
|
* missing value.
|
|
* @access private
|
|
*/
|
|
protected function valuesArePossible($values) {
|
|
$matches = array();
|
|
$widgets = &$this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
$possible = $widgets[$i]->getAttribute('value');
|
|
if (in_array($possible, $values)) {
|
|
$matches[] = $possible;
|
|
}
|
|
}
|
|
return ($values == $matches);
|
|
}
|
|
|
|
/**
|
|
* Converts the output to an appropriate format. This means
|
|
* that no values is false, a single value is just that
|
|
* value and only two or more are contained in an array.
|
|
* @param array $values List of values of widgets.
|
|
* @return string/array/boolean Expected format for a tag.
|
|
* @access private
|
|
*/
|
|
protected function coerceValues($values) {
|
|
if (count($values) == 0) {
|
|
return false;
|
|
} elseif (count($values) == 1) {
|
|
return $values[0];
|
|
} else {
|
|
return $values;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts false or string into array. The opposite of
|
|
* the coercian method.
|
|
* @param string/array/boolean $value A single item is converted
|
|
* to a one item list. False
|
|
* gives an empty list.
|
|
* @return array List of values, possibly empty.
|
|
* @access private
|
|
*/
|
|
protected function makeArray($value) {
|
|
if ($value === false) {
|
|
return array();
|
|
}
|
|
if (is_string($value)) {
|
|
return array($value);
|
|
}
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A group of tags with the same name within a form.
|
|
* Used for radio buttons.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleRadioGroup extends SimpleTagGroup {
|
|
|
|
/**
|
|
* Each tag is tried in turn until one is
|
|
* successfully set. The others will be
|
|
* unchecked if successful.
|
|
* @param string $value New value.
|
|
* @return boolean True if any allowed.
|
|
* @access public
|
|
*/
|
|
function setValue($value) {
|
|
if (! $this->valueIsPossible($value)) {
|
|
return false;
|
|
}
|
|
$index = false;
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if (! $widgets[$i]->setValue($value)) {
|
|
$widgets[$i]->setValue(false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Tests to see if a value is allowed.
|
|
* @param string Attempted value.
|
|
* @return boolean True if a valid value.
|
|
* @access private
|
|
*/
|
|
protected function valueIsPossible($value) {
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if ($widgets[$i]->getAttribute('value') == $value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Accessor for current selected widget or false
|
|
* if none.
|
|
* @return string/boolean Value attribute or
|
|
* content of opton.
|
|
* @access public
|
|
*/
|
|
function getValue() {
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if ($widgets[$i]->getValue() !== false) {
|
|
return $widgets[$i]->getValue();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Accessor for starting value that is active.
|
|
* @return string/boolean Value of first checked
|
|
* widget or false if none.
|
|
* @access public
|
|
*/
|
|
function getDefault() {
|
|
$widgets = $this->getWidgets();
|
|
for ($i = 0, $count = count($widgets); $i < $count; $i++) {
|
|
if ($widgets[$i]->getDefault() !== false) {
|
|
return $widgets[$i]->getDefault();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag to keep track of labels.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleLabelTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('label', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Access for the ID to attach the label to.
|
|
* @return string For attribute.
|
|
* @access public
|
|
*/
|
|
function getFor() {
|
|
return $this->getAttribute('for');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag to aid parsing the form.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleFormTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('form', $attributes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tag to aid parsing the frames in a page.
|
|
* @package SimpleTest
|
|
* @subpackage WebTester
|
|
*/
|
|
class SimpleFrameTag extends SimpleTag {
|
|
|
|
/**
|
|
* Starts with a named tag with attributes only.
|
|
* @param hash $attributes Attribute names and
|
|
* string values.
|
|
*/
|
|
function __construct($attributes) {
|
|
parent::__construct('frame', $attributes);
|
|
}
|
|
|
|
/**
|
|
* Tag contains no content.
|
|
* @return boolean False.
|
|
* @access public
|
|
*/
|
|
function expectEndTag() {
|
|
return false;
|
|
}
|
|
}
|
|
?>
|