source: trunk/server/www/vendors/simpletest/tag.php @ 6

Last change on this file since 6 was 6, checked in by sander, 11 years ago

Added SimpleTest? test framework

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