/Server/SWXPHP/2.00/php/tests/simpletest/tag.php

http://swx-format.googlecode.com/ · PHP · 1392 lines · 582 code · 121 blank · 689 comment · 87 complexity · b9153e8fdaf7c10c7fdd30609a02a9e9 MD5 · raw file

  1. <?php
  2. /**
  3. * Base include file for SimpleTest.
  4. * @package SimpleTest
  5. * @subpackage WebTester
  6. * @version $Id: tag.php,v 1.95 2006/02/05 00:34:29 lastcraft Exp $
  7. */
  8. /**#@+
  9. * include SimpleTest files
  10. */
  11. require_once(dirname(__FILE__) . '/parser.php');
  12. require_once(dirname(__FILE__) . '/encoding.php');
  13. /**#@-*/
  14. /**
  15. * HTML or XML tag.
  16. * @package SimpleTest
  17. * @subpackage WebTester
  18. */
  19. class SimpleTag {
  20. var $_name;
  21. var $_attributes;
  22. var $_content;
  23. /**
  24. * Starts with a named tag with attributes only.
  25. * @param string $name Tag name.
  26. * @param hash $attributes Attribute names and
  27. * string values. Note that
  28. * the keys must have been
  29. * converted to lower case.
  30. */
  31. function SimpleTag($name, $attributes) {
  32. $this->_name = strtolower(trim($name));
  33. $this->_attributes = $attributes;
  34. $this->_content = '';
  35. }
  36. /**
  37. * Check to see if the tag can have both start and
  38. * end tags with content in between.
  39. * @return boolean True if content allowed.
  40. * @access public
  41. */
  42. function expectEndTag() {
  43. return true;
  44. }
  45. /**
  46. * The current tag should not swallow all content for
  47. * itself as it's searchable page content. Private
  48. * content tags are usually widgets that contain default
  49. * values.
  50. * @return boolean False as content is available
  51. * to other tags by default.
  52. * @access public
  53. */
  54. function isPrivateContent() {
  55. return false;
  56. }
  57. /**
  58. * Appends string content to the current content.
  59. * @param string $content Additional text.
  60. * @access public
  61. */
  62. function addContent($content) {
  63. $this->_content .= (string)$content;
  64. }
  65. /**
  66. * Adds an enclosed tag to the content.
  67. * @param SimpleTag $tag New tag.
  68. * @access public
  69. */
  70. function addTag(&$tag) {
  71. }
  72. /**
  73. * Accessor for tag name.
  74. * @return string Name of tag.
  75. * @access public
  76. */
  77. function getTagName() {
  78. return $this->_name;
  79. }
  80. /**
  81. * List of legal child elements.
  82. * @return array List of element names.
  83. * @access public
  84. */
  85. function getChildElements() {
  86. return array();
  87. }
  88. /**
  89. * Accessor for an attribute.
  90. * @param string $label Attribute name.
  91. * @return string Attribute value.
  92. * @access public
  93. */
  94. function getAttribute($label) {
  95. $label = strtolower($label);
  96. if (! isset($this->_attributes[$label])) {
  97. return false;
  98. }
  99. return (string)$this->_attributes[$label];
  100. }
  101. /**
  102. * Sets an attribute.
  103. * @param string $label Attribute name.
  104. * @return string $value New attribute value.
  105. * @access protected
  106. */
  107. function _setAttribute($label, $value) {
  108. $this->_attributes[strtolower($label)] = $value;
  109. }
  110. /**
  111. * Accessor for the whole content so far.
  112. * @return string Content as big raw string.
  113. * @access public
  114. */
  115. function getContent() {
  116. return $this->_content;
  117. }
  118. /**
  119. * Accessor for content reduced to visible text. Acts
  120. * like a text mode browser, normalising space and
  121. * reducing images to their alt text.
  122. * @return string Content as plain text.
  123. * @access public
  124. */
  125. function getText() {
  126. return SimpleHtmlSaxParser::normalise($this->_content);
  127. }
  128. /**
  129. * Test to see if id attribute matches.
  130. * @param string $id ID to test against.
  131. * @return boolean True on match.
  132. * @access public
  133. */
  134. function isId($id) {
  135. return ($this->getAttribute('id') == $id);
  136. }
  137. }
  138. /**
  139. * Page title.
  140. * @package SimpleTest
  141. * @subpackage WebTester
  142. */
  143. class SimpleTitleTag extends SimpleTag {
  144. /**
  145. * Starts with a named tag with attributes only.
  146. * @param hash $attributes Attribute names and
  147. * string values.
  148. */
  149. function SimpleTitleTag($attributes) {
  150. $this->SimpleTag('title', $attributes);
  151. }
  152. }
  153. /**
  154. * Link.
  155. * @package SimpleTest
  156. * @subpackage WebTester
  157. */
  158. class SimpleAnchorTag extends SimpleTag {
  159. /**
  160. * Starts with a named tag with attributes only.
  161. * @param hash $attributes Attribute names and
  162. * string values.
  163. */
  164. function SimpleAnchorTag($attributes) {
  165. $this->SimpleTag('a', $attributes);
  166. }
  167. /**
  168. * Accessor for URL as string.
  169. * @return string Coerced as string.
  170. * @access public
  171. */
  172. function getHref() {
  173. $url = $this->getAttribute('href');
  174. if (is_bool($url)) {
  175. $url = '';
  176. }
  177. return $url;
  178. }
  179. }
  180. /**
  181. * Form element.
  182. * @package SimpleTest
  183. * @subpackage WebTester
  184. */
  185. class SimpleWidget extends SimpleTag {
  186. var $_value;
  187. var $_label;
  188. var $_is_set;
  189. /**
  190. * Starts with a named tag with attributes only.
  191. * @param string $name Tag name.
  192. * @param hash $attributes Attribute names and
  193. * string values.
  194. */
  195. function SimpleWidget($name, $attributes) {
  196. $this->SimpleTag($name, $attributes);
  197. $this->_value = false;
  198. $this->_label = false;
  199. $this->_is_set = false;
  200. }
  201. /**
  202. * Accessor for name submitted as the key in
  203. * GET/POST variables hash.
  204. * @return string Parsed value.
  205. * @access public
  206. */
  207. function getName() {
  208. return $this->getAttribute('name');
  209. }
  210. /**
  211. * Accessor for default value parsed with the tag.
  212. * @return string Parsed value.
  213. * @access public
  214. */
  215. function getDefault() {
  216. return $this->getAttribute('value');
  217. }
  218. /**
  219. * Accessor for currently set value or default if
  220. * none.
  221. * @return string Value set by form or default
  222. * if none.
  223. * @access public
  224. */
  225. function getValue() {
  226. if (! $this->_is_set) {
  227. return $this->getDefault();
  228. }
  229. return $this->_value;
  230. }
  231. /**
  232. * Sets the current form element value.
  233. * @param string $value New value.
  234. * @return boolean True if allowed.
  235. * @access public
  236. */
  237. function setValue($value) {
  238. $this->_value = $value;
  239. $this->_is_set = true;
  240. return true;
  241. }
  242. /**
  243. * Resets the form element value back to the
  244. * default.
  245. * @access public
  246. */
  247. function resetValue() {
  248. $this->_is_set = false;
  249. }
  250. /**
  251. * Allows setting of a label externally, say by a
  252. * label tag.
  253. * @param string $label Label to attach.
  254. * @access public
  255. */
  256. function setLabel($label) {
  257. $this->_label = trim($label);
  258. }
  259. /**
  260. * Reads external or internal label.
  261. * @param string $label Label to test.
  262. * @return boolean True is match.
  263. * @access public
  264. */
  265. function isLabel($label) {
  266. return $this->_label == trim($label);
  267. }
  268. /**
  269. * Dispatches the value into the form encoded packet.
  270. * @param SimpleEncoding $encoding Form packet.
  271. * @access public
  272. */
  273. function write(&$encoding) {
  274. if ($this->getName()) {
  275. $encoding->add($this->getName(), $this->getValue());
  276. }
  277. }
  278. }
  279. /**
  280. * Text, password and hidden field.
  281. * @package SimpleTest
  282. * @subpackage WebTester
  283. */
  284. class SimpleTextTag extends SimpleWidget {
  285. /**
  286. * Starts with a named tag with attributes only.
  287. * @param hash $attributes Attribute names and
  288. * string values.
  289. */
  290. function SimpleTextTag($attributes) {
  291. $this->SimpleWidget('input', $attributes);
  292. if ($this->getAttribute('value') === false) {
  293. $this->_setAttribute('value', '');
  294. }
  295. }
  296. /**
  297. * Tag contains no content.
  298. * @return boolean False.
  299. * @access public
  300. */
  301. function expectEndTag() {
  302. return false;
  303. }
  304. /**
  305. * Sets the current form element value. Cannot
  306. * change the value of a hidden field.
  307. * @param string $value New value.
  308. * @return boolean True if allowed.
  309. * @access public
  310. */
  311. function setValue($value) {
  312. if ($this->getAttribute('type') == 'hidden') {
  313. return false;
  314. }
  315. return parent::setValue($value);
  316. }
  317. }
  318. /**
  319. * Submit button as input tag.
  320. * @package SimpleTest
  321. * @subpackage WebTester
  322. */
  323. class SimpleSubmitTag extends SimpleWidget {
  324. /**
  325. * Starts with a named tag with attributes only.
  326. * @param hash $attributes Attribute names and
  327. * string values.
  328. */
  329. function SimpleSubmitTag($attributes) {
  330. $this->SimpleWidget('input', $attributes);
  331. if ($this->getAttribute('value') === false) {
  332. $this->_setAttribute('value', 'Submit');
  333. }
  334. }
  335. /**
  336. * Tag contains no end element.
  337. * @return boolean False.
  338. * @access public
  339. */
  340. function expectEndTag() {
  341. return false;
  342. }
  343. /**
  344. * Disables the setting of the button value.
  345. * @param string $value Ignored.
  346. * @return boolean True if allowed.
  347. * @access public
  348. */
  349. function setValue($value) {
  350. return false;
  351. }
  352. /**
  353. * Value of browser visible text.
  354. * @return string Visible label.
  355. * @access public
  356. */
  357. function getLabel() {
  358. return $this->getValue();
  359. }
  360. /**
  361. * Test for a label match when searching.
  362. * @param string $label Label to test.
  363. * @return boolean True on match.
  364. * @access public
  365. */
  366. function isLabel($label) {
  367. return trim($label) == trim($this->getLabel());
  368. }
  369. }
  370. /**
  371. * Image button as input tag.
  372. * @package SimpleTest
  373. * @subpackage WebTester
  374. */
  375. class SimpleImageSubmitTag extends SimpleWidget {
  376. /**
  377. * Starts with a named tag with attributes only.
  378. * @param hash $attributes Attribute names and
  379. * string values.
  380. */
  381. function SimpleImageSubmitTag($attributes) {
  382. $this->SimpleWidget('input', $attributes);
  383. }
  384. /**
  385. * Tag contains no end element.
  386. * @return boolean False.
  387. * @access public
  388. */
  389. function expectEndTag() {
  390. return false;
  391. }
  392. /**
  393. * Disables the setting of the button value.
  394. * @param string $value Ignored.
  395. * @return boolean True if allowed.
  396. * @access public
  397. */
  398. function setValue($value) {
  399. return false;
  400. }
  401. /**
  402. * Value of browser visible text.
  403. * @return string Visible label.
  404. * @access public
  405. */
  406. function getLabel() {
  407. if ($this->getAttribute('title')) {
  408. return $this->getAttribute('title');
  409. }
  410. return $this->getAttribute('alt');
  411. }
  412. /**
  413. * Test for a label match when searching.
  414. * @param string $label Label to test.
  415. * @return boolean True on match.
  416. * @access public
  417. */
  418. function isLabel($label) {
  419. return trim($label) == trim($this->getLabel());
  420. }
  421. /**
  422. * Dispatches the value into the form encoded packet.
  423. * @param SimpleEncoding $encoding Form packet.
  424. * @param integer $x X coordinate of click.
  425. * @param integer $y Y coordinate of click.
  426. * @access public
  427. */
  428. function write(&$encoding, $x, $y) {
  429. if ($this->getName()) {
  430. $encoding->add($this->getName() . '.x', $x);
  431. $encoding->add($this->getName() . '.y', $y);
  432. } else {
  433. $encoding->add('x', $x);
  434. $encoding->add('y', $y);
  435. }
  436. }
  437. }
  438. /**
  439. * Submit button as button tag.
  440. * @package SimpleTest
  441. * @subpackage WebTester
  442. */
  443. class SimpleButtonTag extends SimpleWidget {
  444. /**
  445. * Starts with a named tag with attributes only.
  446. * Defaults are very browser dependent.
  447. * @param hash $attributes Attribute names and
  448. * string values.
  449. */
  450. function SimpleButtonTag($attributes) {
  451. $this->SimpleWidget('button', $attributes);
  452. }
  453. /**
  454. * Check to see if the tag can have both start and
  455. * end tags with content in between.
  456. * @return boolean True if content allowed.
  457. * @access public
  458. */
  459. function expectEndTag() {
  460. return true;
  461. }
  462. /**
  463. * Disables the setting of the button value.
  464. * @param string $value Ignored.
  465. * @return boolean True if allowed.
  466. * @access public
  467. */
  468. function setValue($value) {
  469. return false;
  470. }
  471. /**
  472. * Value of browser visible text.
  473. * @return string Visible label.
  474. * @access public
  475. */
  476. function getLabel() {
  477. return $this->getContent();
  478. }
  479. /**
  480. * Test for a label match when searching.
  481. * @param string $label Label to test.
  482. * @return boolean True on match.
  483. * @access public
  484. */
  485. function isLabel($label) {
  486. return trim($label) == trim($this->getLabel());
  487. }
  488. }
  489. /**
  490. * Content tag for text area.
  491. * @package SimpleTest
  492. * @subpackage WebTester
  493. */
  494. class SimpleTextAreaTag extends SimpleWidget {
  495. /**
  496. * Starts with a named tag with attributes only.
  497. * @param hash $attributes Attribute names and
  498. * string values.
  499. */
  500. function SimpleTextAreaTag($attributes) {
  501. $this->SimpleWidget('textarea', $attributes);
  502. }
  503. /**
  504. * Accessor for starting value.
  505. * @return string Parsed value.
  506. * @access public
  507. */
  508. function getDefault() {
  509. return $this->_wrap(SimpleHtmlSaxParser::decodeHtml($this->getContent()));
  510. }
  511. /**
  512. * Applies word wrapping if needed.
  513. * @param string $value New value.
  514. * @return boolean True if allowed.
  515. * @access public
  516. */
  517. function setValue($value) {
  518. return parent::setValue($this->_wrap($value));
  519. }
  520. /**
  521. * Test to see if text should be wrapped.
  522. * @return boolean True if wrapping on.
  523. * @access private
  524. */
  525. function _wrapIsEnabled() {
  526. if ($this->getAttribute('cols')) {
  527. $wrap = $this->getAttribute('wrap');
  528. if (($wrap == 'physical') || ($wrap == 'hard')) {
  529. return true;
  530. }
  531. }
  532. return false;
  533. }
  534. /**
  535. * Performs the formatting that is peculiar to
  536. * this tag. There is strange behaviour in this
  537. * one, including stripping a leading new line.
  538. * Go figure. I am using Firefox as a guide.
  539. * @param string $text Text to wrap.
  540. * @return string Text wrapped with carriage
  541. * returns and line feeds
  542. * @access private
  543. */
  544. function _wrap($text) {
  545. $text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text));
  546. $text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text));
  547. if (strncmp($text, "\r\n", strlen("\r\n")) == 0) {
  548. $text = substr($text, strlen("\r\n"));
  549. }
  550. if ($this->_wrapIsEnabled()) {
  551. return wordwrap(
  552. $text,
  553. (integer)$this->getAttribute('cols'),
  554. "\r\n");
  555. }
  556. return $text;
  557. }
  558. /**
  559. * The content of textarea is not part of the page.
  560. * @return boolean True.
  561. * @access public
  562. */
  563. function isPrivateContent() {
  564. return true;
  565. }
  566. }
  567. /**
  568. * File upload widget.
  569. * @package SimpleTest
  570. * @subpackage WebTester
  571. */
  572. class SimpleUploadTag extends SimpleWidget {
  573. /**
  574. * Starts with attributes only.
  575. * @param hash $attributes Attribute names and
  576. * string values.
  577. */
  578. function SimpleUploadTag($attributes) {
  579. $this->SimpleWidget('input', $attributes);
  580. }
  581. /**
  582. * Tag contains no content.
  583. * @return boolean False.
  584. * @access public
  585. */
  586. function expectEndTag() {
  587. return false;
  588. }
  589. /**
  590. * Dispatches the value into the form encoded packet.
  591. * @param SimpleEncoding $encoding Form packet.
  592. * @access public
  593. */
  594. function write(&$encoding) {
  595. if (! file_exists($this->getValue())) {
  596. return;
  597. }
  598. $encoding->attach(
  599. $this->getName(),
  600. implode('', file($this->getValue())),
  601. basename($this->getValue()));
  602. }
  603. }
  604. /**
  605. * Drop down widget.
  606. * @package SimpleTest
  607. * @subpackage WebTester
  608. */
  609. class SimpleSelectionTag extends SimpleWidget {
  610. var $_options;
  611. var $_choice;
  612. /**
  613. * Starts with attributes only.
  614. * @param hash $attributes Attribute names and
  615. * string values.
  616. */
  617. function SimpleSelectionTag($attributes) {
  618. $this->SimpleWidget('select', $attributes);
  619. $this->_options = array();
  620. $this->_choice = false;
  621. }
  622. /**
  623. * Adds an option tag to a selection field.
  624. * @param SimpleOptionTag $tag New option.
  625. * @access public
  626. */
  627. function addTag(&$tag) {
  628. if ($tag->getTagName() == 'option') {
  629. $this->_options[] = &$tag;
  630. }
  631. }
  632. /**
  633. * Text within the selection element is ignored.
  634. * @param string $content Ignored.
  635. * @access public
  636. */
  637. function addContent($content) {
  638. }
  639. /**
  640. * Scans options for defaults. If none, then
  641. * the first option is selected.
  642. * @return string Selected field.
  643. * @access public
  644. */
  645. function getDefault() {
  646. for ($i = 0, $count = count($this->_options); $i < $count; $i++) {
  647. if ($this->_options[$i]->getAttribute('selected') !== false) {
  648. return $this->_options[$i]->getDefault();
  649. }
  650. }
  651. if ($count > 0) {
  652. return $this->_options[0]->getDefault();
  653. }
  654. return '';
  655. }
  656. /**
  657. * Can only set allowed values.
  658. * @param string $value New choice.
  659. * @return boolean True if allowed.
  660. * @access public
  661. */
  662. function setValue($value) {
  663. for ($i = 0, $count = count($this->_options); $i < $count; $i++) {
  664. if ($this->_options[$i]->isValue($value)) {
  665. $this->_choice = $i;
  666. return true;
  667. }
  668. }
  669. return false;
  670. }
  671. /**
  672. * Accessor for current selection value.
  673. * @return string Value attribute or
  674. * content of opton.
  675. * @access public
  676. */
  677. function getValue() {
  678. if ($this->_choice === false) {
  679. return $this->getDefault();
  680. }
  681. return $this->_options[$this->_choice]->getValue();
  682. }
  683. }
  684. /**
  685. * Drop down widget.
  686. * @package SimpleTest
  687. * @subpackage WebTester
  688. */
  689. class MultipleSelectionTag extends SimpleWidget {
  690. var $_options;
  691. var $_values;
  692. /**
  693. * Starts with attributes only.
  694. * @param hash $attributes Attribute names and
  695. * string values.
  696. */
  697. function MultipleSelectionTag($attributes) {
  698. $this->SimpleWidget('select', $attributes);
  699. $this->_options = array();
  700. $this->_values = false;
  701. }
  702. /**
  703. * Adds an option tag to a selection field.
  704. * @param SimpleOptionTag $tag New option.
  705. * @access public
  706. */
  707. function addTag(&$tag) {
  708. if ($tag->getTagName() == 'option') {
  709. $this->_options[] = &$tag;
  710. }
  711. }
  712. /**
  713. * Text within the selection element is ignored.
  714. * @param string $content Ignored.
  715. * @access public
  716. */
  717. function addContent($content) {
  718. }
  719. /**
  720. * Scans options for defaults to populate the
  721. * value array().
  722. * @return array Selected fields.
  723. * @access public
  724. */
  725. function getDefault() {
  726. $default = array();
  727. for ($i = 0, $count = count($this->_options); $i < $count; $i++) {
  728. if ($this->_options[$i]->getAttribute('selected') !== false) {
  729. $default[] = $this->_options[$i]->getDefault();
  730. }
  731. }
  732. return $default;
  733. }
  734. /**
  735. * Can only set allowed values. Any illegal value
  736. * will result in a failure, but all correct values
  737. * will be set.
  738. * @param array $desired New choices.
  739. * @return boolean True if all allowed.
  740. * @access public
  741. */
  742. function setValue($desired) {
  743. $achieved = array();
  744. foreach ($desired as $value) {
  745. $success = false;
  746. for ($i = 0, $count = count($this->_options); $i < $count; $i++) {
  747. if ($this->_options[$i]->isValue($value)) {
  748. $achieved[] = $this->_options[$i]->getValue();
  749. $success = true;
  750. break;
  751. }
  752. }
  753. if (! $success) {
  754. return false;
  755. }
  756. }
  757. $this->_values = $achieved;
  758. return true;
  759. }
  760. /**
  761. * Accessor for current selection value.
  762. * @return array List of currently set options.
  763. * @access public
  764. */
  765. function getValue() {
  766. if ($this->_values === false) {
  767. return $this->getDefault();
  768. }
  769. return $this->_values;
  770. }
  771. }
  772. /**
  773. * Option for selection field.
  774. * @package SimpleTest
  775. * @subpackage WebTester
  776. */
  777. class SimpleOptionTag extends SimpleWidget {
  778. /**
  779. * Stashes the attributes.
  780. */
  781. function SimpleOptionTag($attributes) {
  782. $this->SimpleWidget('option', $attributes);
  783. }
  784. /**
  785. * Does nothing.
  786. * @param string $value Ignored.
  787. * @return boolean Not allowed.
  788. * @access public
  789. */
  790. function setValue($value) {
  791. return false;
  792. }
  793. /**
  794. * Test to see if a value matches the option.
  795. * @param string $compare Value to compare with.
  796. * @return boolean True if possible match.
  797. * @access public
  798. */
  799. function isValue($compare) {
  800. $compare = trim($compare);
  801. if (trim($this->getValue()) == $compare) {
  802. return true;
  803. }
  804. return trim($this->getContent()) == $compare;
  805. }
  806. /**
  807. * Accessor for starting value. Will be set to
  808. * the option label if no value exists.
  809. * @return string Parsed value.
  810. * @access public
  811. */
  812. function getDefault() {
  813. if ($this->getAttribute('value') === false) {
  814. return $this->getContent();
  815. }
  816. return $this->getAttribute('value');
  817. }
  818. /**
  819. * The content of options is not part of the page.
  820. * @return boolean True.
  821. * @access public
  822. */
  823. function isPrivateContent() {
  824. return true;
  825. }
  826. }
  827. /**
  828. * Radio button.
  829. * @package SimpleTest
  830. * @subpackage WebTester
  831. */
  832. class SimpleRadioButtonTag extends SimpleWidget {
  833. /**
  834. * Stashes the attributes.
  835. * @param array $attributes Hash of attributes.
  836. */
  837. function SimpleRadioButtonTag($attributes) {
  838. $this->SimpleWidget('input', $attributes);
  839. if ($this->getAttribute('value') === false) {
  840. $this->_setAttribute('value', 'on');
  841. }
  842. }
  843. /**
  844. * Tag contains no content.
  845. * @return boolean False.
  846. * @access public
  847. */
  848. function expectEndTag() {
  849. return false;
  850. }
  851. /**
  852. * The only allowed value sn the one in the
  853. * "value" attribute.
  854. * @param string $value New value.
  855. * @return boolean True if allowed.
  856. * @access public
  857. */
  858. function setValue($value) {
  859. if ($value === false) {
  860. return parent::setValue($value);
  861. }
  862. if ($value !== $this->getAttribute('value')) {
  863. return false;
  864. }
  865. return parent::setValue($value);
  866. }
  867. /**
  868. * Accessor for starting value.
  869. * @return string Parsed value.
  870. * @access public
  871. */
  872. function getDefault() {
  873. if ($this->getAttribute('checked') !== false) {
  874. return $this->getAttribute('value');
  875. }
  876. return false;
  877. }
  878. }
  879. /**
  880. * Checkbox widget.
  881. * @package SimpleTest
  882. * @subpackage WebTester
  883. */
  884. class SimpleCheckboxTag extends SimpleWidget {
  885. /**
  886. * Starts with attributes only.
  887. * @param hash $attributes Attribute names and
  888. * string values.
  889. */
  890. function SimpleCheckboxTag($attributes) {
  891. $this->SimpleWidget('input', $attributes);
  892. if ($this->getAttribute('value') === false) {
  893. $this->_setAttribute('value', 'on');
  894. }
  895. }
  896. /**
  897. * Tag contains no content.
  898. * @return boolean False.
  899. * @access public
  900. */
  901. function expectEndTag() {
  902. return false;
  903. }
  904. /**
  905. * The only allowed value in the one in the
  906. * "value" attribute. The default for this
  907. * attribute is "on". If this widget is set to
  908. * true, then the usual value will be taken.
  909. * @param string $value New value.
  910. * @return boolean True if allowed.
  911. * @access public
  912. */
  913. function setValue($value) {
  914. if ($value === false) {
  915. return parent::setValue($value);
  916. }
  917. if ($value === true) {
  918. return parent::setValue($this->getAttribute('value'));
  919. }
  920. if ($value != $this->getAttribute('value')) {
  921. return false;
  922. }
  923. return parent::setValue($value);
  924. }
  925. /**
  926. * Accessor for starting value. The default
  927. * value is "on".
  928. * @return string Parsed value.
  929. * @access public
  930. */
  931. function getDefault() {
  932. if ($this->getAttribute('checked') !== false) {
  933. return $this->getAttribute('value');
  934. }
  935. return false;
  936. }
  937. }
  938. /**
  939. * A group of multiple widgets with some shared behaviour.
  940. * @package SimpleTest
  941. * @subpackage WebTester
  942. */
  943. class SimpleTagGroup {
  944. var $_widgets = array();
  945. /**
  946. * Adds a tag to the group.
  947. * @param SimpleWidget $widget
  948. * @access public
  949. */
  950. function addWidget(&$widget) {
  951. $this->_widgets[] = &$widget;
  952. }
  953. /**
  954. * Accessor to widget set.
  955. * @return array All widgets.
  956. * @access protected
  957. */
  958. function &_getWidgets() {
  959. return $this->_widgets;
  960. }
  961. /**
  962. * Accessor for an attribute.
  963. * @param string $label Attribute name.
  964. * @return boolean Always false.
  965. * @access public
  966. */
  967. function getAttribute($label) {
  968. return false;
  969. }
  970. /**
  971. * Fetches the name for the widget from the first
  972. * member.
  973. * @return string Name of widget.
  974. * @access public
  975. */
  976. function getName() {
  977. if (count($this->_widgets) > 0) {
  978. return $this->_widgets[0]->getName();
  979. }
  980. }
  981. /**
  982. * Scans the widgets for one with the appropriate
  983. * ID field.
  984. * @param string $id ID value to try.
  985. * @return boolean True if matched.
  986. * @access public
  987. */
  988. function isId($id) {
  989. for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) {
  990. if ($this->_widgets[$i]->isId($id)) {
  991. return true;
  992. }
  993. }
  994. return false;
  995. }
  996. /**
  997. * Scans the widgets for one with the appropriate
  998. * attached label.
  999. * @param string $label Attached label to try.
  1000. * @return boolean True if matched.
  1001. * @access public
  1002. */
  1003. function isLabel($label) {
  1004. for ($i = 0, $count = count($this->_widgets); $i < $count; $i++) {
  1005. if ($this->_widgets[$i]->isLabel($label)) {
  1006. return true;
  1007. }
  1008. }
  1009. return false;
  1010. }
  1011. /**
  1012. * Dispatches the value into the form encoded packet.
  1013. * @param SimpleEncoding $encoding Form packet.
  1014. * @access public
  1015. */
  1016. function write(&$encoding) {
  1017. $encoding->add($this->getName(), $this->getValue());
  1018. }
  1019. }
  1020. /**
  1021. * A group of tags with the same name within a form.
  1022. * @package SimpleTest
  1023. * @subpackage WebTester
  1024. */
  1025. class SimpleCheckboxGroup extends SimpleTagGroup {
  1026. /**
  1027. * Accessor for current selected widget or false
  1028. * if none.
  1029. * @return string/array Widget values or false if none.
  1030. * @access public
  1031. */
  1032. function getValue() {
  1033. $values = array();
  1034. $widgets = &$this->_getWidgets();
  1035. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1036. if ($widgets[$i]->getValue() !== false) {
  1037. $values[] = $widgets[$i]->getValue();
  1038. }
  1039. }
  1040. return $this->_coerceValues($values);
  1041. }
  1042. /**
  1043. * Accessor for starting value that is active.
  1044. * @return string/array Widget values or false if none.
  1045. * @access public
  1046. */
  1047. function getDefault() {
  1048. $values = array();
  1049. $widgets = &$this->_getWidgets();
  1050. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1051. if ($widgets[$i]->getDefault() !== false) {
  1052. $values[] = $widgets[$i]->getDefault();
  1053. }
  1054. }
  1055. return $this->_coerceValues($values);
  1056. }
  1057. /**
  1058. * Accessor for current set values.
  1059. * @param string/array/boolean $values Either a single string, a
  1060. * hash or false for nothing set.
  1061. * @return boolean True if all values can be set.
  1062. * @access public
  1063. */
  1064. function setValue($values) {
  1065. $values = $this->_makeArray($values);
  1066. if (! $this->_valuesArePossible($values)) {
  1067. return false;
  1068. }
  1069. $widgets = &$this->_getWidgets();
  1070. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1071. $possible = $widgets[$i]->getAttribute('value');
  1072. if (in_array($widgets[$i]->getAttribute('value'), $values)) {
  1073. $widgets[$i]->setValue($possible);
  1074. } else {
  1075. $widgets[$i]->setValue(false);
  1076. }
  1077. }
  1078. return true;
  1079. }
  1080. /**
  1081. * Tests to see if a possible value set is legal.
  1082. * @param string/array/boolean $values Either a single string, a
  1083. * hash or false for nothing set.
  1084. * @return boolean False if trying to set a
  1085. * missing value.
  1086. * @access private
  1087. */
  1088. function _valuesArePossible($values) {
  1089. $matches = array();
  1090. $widgets = &$this->_getWidgets();
  1091. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1092. $possible = $widgets[$i]->getAttribute('value');
  1093. if (in_array($possible, $values)) {
  1094. $matches[] = $possible;
  1095. }
  1096. }
  1097. return ($values == $matches);
  1098. }
  1099. /**
  1100. * Converts the output to an appropriate format. This means
  1101. * that no values is false, a single value is just that
  1102. * value and only two or more are contained in an array.
  1103. * @param array $values List of values of widgets.
  1104. * @return string/array/boolean Expected format for a tag.
  1105. * @access private
  1106. */
  1107. function _coerceValues($values) {
  1108. if (count($values) == 0) {
  1109. return false;
  1110. } elseif (count($values) == 1) {
  1111. return $values[0];
  1112. } else {
  1113. return $values;
  1114. }
  1115. }
  1116. /**
  1117. * Converts false or string into array. The opposite of
  1118. * the coercian method.
  1119. * @param string/array/boolean $value A single item is converted
  1120. * to a one item list. False
  1121. * gives an empty list.
  1122. * @return array List of values, possibly empty.
  1123. * @access private
  1124. */
  1125. function _makeArray($value) {
  1126. if ($value === false) {
  1127. return array();
  1128. }
  1129. if (is_string($value)) {
  1130. return array($value);
  1131. }
  1132. return $value;
  1133. }
  1134. }
  1135. /**
  1136. * A group of tags with the same name within a form.
  1137. * Used for radio buttons.
  1138. * @package SimpleTest
  1139. * @subpackage WebTester
  1140. */
  1141. class SimpleRadioGroup extends SimpleTagGroup {
  1142. /**
  1143. * Each tag is tried in turn until one is
  1144. * successfully set. The others will be
  1145. * unchecked if successful.
  1146. * @param string $value New value.
  1147. * @return boolean True if any allowed.
  1148. * @access public
  1149. */
  1150. function setValue($value) {
  1151. if (! $this->_valueIsPossible($value)) {
  1152. return false;
  1153. }
  1154. $index = false;
  1155. $widgets = &$this->_getWidgets();
  1156. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1157. if (! $widgets[$i]->setValue($value)) {
  1158. $widgets[$i]->setValue(false);
  1159. }
  1160. }
  1161. return true;
  1162. }
  1163. /**
  1164. * Tests to see if a value is allowed.
  1165. * @param string Attempted value.
  1166. * @return boolean True if a valid value.
  1167. * @access private
  1168. */
  1169. function _valueIsPossible($value) {
  1170. $widgets = &$this->_getWidgets();
  1171. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1172. if ($widgets[$i]->getAttribute('value') == $value) {
  1173. return true;
  1174. }
  1175. }
  1176. return false;
  1177. }
  1178. /**
  1179. * Accessor for current selected widget or false
  1180. * if none.
  1181. * @return string/boolean Value attribute or
  1182. * content of opton.
  1183. * @access public
  1184. */
  1185. function getValue() {
  1186. $widgets = &$this->_getWidgets();
  1187. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1188. if ($widgets[$i]->getValue() !== false) {
  1189. return $widgets[$i]->getValue();
  1190. }
  1191. }
  1192. return false;
  1193. }
  1194. /**
  1195. * Accessor for starting value that is active.
  1196. * @return string/boolean Value of first checked
  1197. * widget or false if none.
  1198. * @access public
  1199. */
  1200. function getDefault() {
  1201. $widgets = &$this->_getWidgets();
  1202. for ($i = 0, $count = count($widgets); $i < $count; $i++) {
  1203. if ($widgets[$i]->getDefault() !== false) {
  1204. return $widgets[$i]->getDefault();
  1205. }
  1206. }
  1207. return false;
  1208. }
  1209. }
  1210. /**
  1211. * Tag to keep track of labels.
  1212. * @package SimpleTest
  1213. * @subpackage WebTester
  1214. */
  1215. class SimpleLabelTag extends SimpleTag {
  1216. /**
  1217. * Starts with a named tag with attributes only.
  1218. * @param hash $attributes Attribute names and
  1219. * string values.
  1220. */
  1221. function SimpleLabelTag($attributes) {
  1222. $this->SimpleTag('label', $attributes);
  1223. }
  1224. /**
  1225. * Access for the ID to attach the label to.
  1226. * @return string For attribute.
  1227. * @access public
  1228. */
  1229. function getFor() {
  1230. return $this->getAttribute('for');
  1231. }
  1232. }
  1233. /**
  1234. * Tag to aid parsing the form.
  1235. * @package SimpleTest
  1236. * @subpackage WebTester
  1237. */
  1238. class SimpleFormTag extends SimpleTag {
  1239. /**
  1240. * Starts with a named tag with attributes only.
  1241. * @param hash $attributes Attribute names and
  1242. * string values.
  1243. */
  1244. function SimpleFormTag($attributes) {
  1245. $this->SimpleTag('form', $attributes);
  1246. }
  1247. }
  1248. /**
  1249. * Tag to aid parsing the frames in a page.
  1250. * @package SimpleTest
  1251. * @subpackage WebTester
  1252. */
  1253. class SimpleFrameTag extends SimpleTag {
  1254. /**
  1255. * Starts with a named tag with attributes only.
  1256. * @param hash $attributes Attribute names and
  1257. * string values.
  1258. */
  1259. function SimpleFrameTag($attributes) {
  1260. $this->SimpleTag('frame', $attributes);
  1261. }
  1262. /**
  1263. * Tag contains no content.
  1264. * @return boolean False.
  1265. * @access public
  1266. */
  1267. function expectEndTag() {
  1268. return false;
  1269. }
  1270. }
  1271. ?>