Completed
Push — 3.5 ( 1a9180...1bec8a )
by Daniel
24s
created

SimpleWidget::SimpleWidget()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 2
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
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
 */
12
require_once(dirname(__FILE__) . '/parser.php');
13
require_once(dirname(__FILE__) . '/encoding.php');
14
/**#@-*/
15
16
/**
17
 *    HTML or XML tag.
18
 *    @package SimpleTest
19
 *    @subpackage WebTester
20
 */
21
class 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
 */
158
class 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
 */
184
class 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
 */
201
class 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
 */
231
class 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, $x, $y) {
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
 */
340
class 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
 */
383
class 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
 */
441
class 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
 */
516
class 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
 */
573
class 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
 */
658
class 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, $x, $y) {
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
 */
699
class 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
 */
786
class 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
 */
881
class 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
 */
942
class 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
 */
999
class 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
 */
1063
class 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
 */
1153
class 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
 */
1276
class 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
 */
1355
class 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
 */
1381
class 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
 */
1398
class 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