Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** Base include file for SimpleTest.* @package SimpleTest* @subpackage WebTester* @version $Id: tag.php 1398 2006-09-08 19:31:03Z xue $*//**#@+* include SimpleTest files*/require_once(dirname(__FILE__) . '/parser.php');require_once(dirname(__FILE__) . '/encoding.php');/**#@-*//*** HTML or XML tag.* @package SimpleTest* @subpackage WebTester*/class SimpleTag {protected $_name;protected $_attributes;protected $_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 SimpleTag($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;}/*** Adds an enclosed tag to the content.* @param SimpleTag $tag New tag.* @access public*/function 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*/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 SimpleHtmlSaxParser::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);}}/*** 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 SimpleTitleTag($attributes) {$this->SimpleTag('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 SimpleAnchorTag($attributes) {$this->SimpleTag('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 {protected $_value;protected $_label;protected $_is_set;/*** Starts with a named tag with attributes only.* @param string $name Tag name.* @param hash $attributes Attribute names and* string values.*/function SimpleWidget($name, $attributes) {$this->SimpleTag($name, $attributes);$this->_value = false;$this->_label = false;$this->_is_set = false;}/*** Accessor for name submitted as the key in* GET/POST variables 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);}/*** 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 SimpleTextTag($attributes) {$this->SimpleWidget('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 SimpleSubmitTag($attributes) {$this->SimpleWidget('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 SimpleImageSubmitTag($attributes) {$this->SimpleWidget('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, $y) {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 SimpleButtonTag($attributes) {$this->SimpleWidget('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 SimpleTextAreaTag($attributes) {$this->SimpleWidget('textarea', $attributes);}/*** Accessor for starting value.* @return string Parsed value.* @access public*/function getDefault() {return $this->_wrap(SimpleHtmlSaxParser::decodeHtml($this->getContent()));}/*** 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*/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 SimpleUploadTag($attributes) {$this->SimpleWidget('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 {protected $_options;protected $_choice;/*** Starts with attributes only.* @param hash $attributes Attribute names and* string values.*/function SimpleSelectionTag($attributes) {$this->SimpleWidget('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) {}/*** 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 {protected $_options;protected $_values;/*** Starts with attributes only.* @param hash $attributes Attribute names and* string values.*/function MultipleSelectionTag($attributes) {$this->SimpleWidget('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) {}/*** 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 SimpleOptionTag($attributes) {$this->SimpleWidget('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($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 $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 SimpleRadioButtonTag($attributes) {$this->SimpleWidget('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 SimpleCheckboxTag($attributes) {$this->SimpleWidget('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 {protected $_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*/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*/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*/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*/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*/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 SimpleLabelTag($attributes) {$this->SimpleTag('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 SimpleFormTag($attributes) {$this->SimpleTag('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 SimpleFrameTag($attributes) {$this->SimpleTag('frame', $attributes);}/*** Tag contains no content.* @return boolean False.* @access public*/function expectEndTag() {return false;}}?>