3 * Base include file for SimpleTest
5 * @subpackage WebTester
6 * @version $Id: frames.php,v 1.28 2004/08/18 23:10:19 lastcraft Exp $
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__
) . '/page.php');
13 require_once(dirname(__FILE__
) . '/user_agent.php');
17 * A composite page. Wraps a frameset page and
18 * adds subframes. The original page will be
19 * mostly ignored. Implements the SimplePage
20 * interface so as to be interchangeable.
22 * @subpackage WebTester
24 class SimpleFrameset
{
31 * Stashes the frameset page. Will make use of the
32 * browser to fetch the sub frames recursively.
33 * @param SimplePage $page Frameset page.
35 function SimpleFrameset(&$page) {
36 $this->_frameset
= &$page;
37 $this->_frames
= array();
38 $this->_focus
= false
;
39 $this->_names
= array();
43 * Adds a parsed page to the frameset.
44 * @param SimplePage $page Frame page.
45 * @param string $name Name of frame in frameset.
48 function addFrame(&$page, $name = false
) {
49 $this->_frames
[] = &$page;
51 $this->_names
[$name] = count($this->_frames
) - 1;
56 * Replaces existing frame with another. If the
57 * frame is nested, then the call is passed down
59 * @param array $path Path of frame in frameset.
60 * @param SimplePage $page Frame source.
63 function setFrame($path, &$page) {
64 $name = array_shift($path);
65 if (isset($this->_names
[$name])) {
66 $index = $this->_names
[$name];
70 if (count($path) == 0) {
71 $this->_frames
[$index] = &$page;
74 $this->_frames
[$index]->setFrame($path, $page);
78 * Accessor for current frame focus. Will be
79 * false if no frame has focus. Will have the nested
81 * @return array Labels or indexes of nested frames.
84 function getFrameFocus() {
85 if ($this->_focus
=== false
) {
89 array($this->_getPublicNameFromIndex($this->_focus
)),
90 $this->_frames
[$this->_focus
]->getFrameFocus());
94 * Turns an internal array index into the frames list
95 * into a public name, or if none, then a one offset
97 * @param integer $subject Internal index.
98 * @return integer/string Public name.
101 function _getPublicNameFromIndex($subject) {
102 foreach ($this->_names
as $name => $index) {
103 if ($subject == $index) {
111 * Sets the focus by index. The integer index starts from 1.
112 * If already focused and the target frame also has frames,
113 * then the nested frame will be focused.
114 * @param integer $choice Chosen frame.
115 * @return boolean True if frame exists.
118 function setFrameFocusByIndex($choice) {
119 if (is_integer($this->_focus
)) {
120 if ($this->_frames
[$this->_focus
]->hasFrames()) {
121 return $this->_frames
[$this->_focus
]->setFrameFocusByIndex($choice);
124 if (($choice < 1) ||
($choice > count($this->_frames
))) {
127 $this->_focus
= $choice - 1;
132 * Sets the focus by name. If already focused and the
133 * target frame also has frames, then the nested frame
135 * @param string $name Chosen frame.
136 * @return boolean True if frame exists.
139 function setFrameFocus($name) {
140 if (is_integer($this->_focus
)) {
141 if ($this->_frames
[$this->_focus
]->hasFrames()) {
142 return $this->_frames
[$this->_focus
]->setFrameFocus($name);
145 if (in_array($name, array_keys($this->_names
))) {
146 $this->_focus
= $this->_names
[$name];
153 * Clears the frame focus.
156 function clearFrameFocus() {
157 $this->_focus
= false
;
158 $this->_clearNestedFramesFocus();
162 * Clears the frame focus for any nested frames.
165 function _clearNestedFramesFocus() {
166 for ($i = 0; $i < count($this->_frames
); $i++
) {
167 $this->_frames
[$i]->clearFrameFocus();
172 * Test for the presence of a frameset.
173 * @return boolean Always true.
176 function hasFrames() {
181 * Accessor for frames information.
182 * @return array/string Recursive hash of frame URL strings.
183 * The key is either a numerical
184 * index or the name attribute.
187 function getFrames() {
189 for ($i = 0; $i < count($this->_frames
); $i++
) {
190 $report[$this->_getPublicNameFromIndex($i)] =
191 $this->_frames
[$i]->getFrames();
197 * Accessor for raw text of either all the pages or
198 * the frame in focus.
199 * @return string Raw unparsed content.
203 if (is_integer($this->_focus
)) {
204 return $this->_frames
[$this->_focus
]->getRaw();
207 for ($i = 0; $i < count($this->_frames
); $i++
) {
208 $raw .= $this->_frames
[$i]->getRaw();
214 * Accessor for last error.
215 * @return string Error from last response.
218 function getTransportError() {
219 if (is_integer($this->_focus
)) {
220 return $this->_frames
[$this->_focus
]->getTransportError();
222 return $this->_frameset
->getTransportError();
226 * Request method used to fetch this frame.
227 * @return string GET, POST or HEAD.
230 function getMethod() {
231 if (is_integer($this->_focus
)) {
232 return $this->_frames
[$this->_focus
]->getMethod();
234 return $this->_frameset
->getMethod();
238 * Original resource name.
239 * @return SimpleUrl Current url.
243 if (is_integer($this->_focus
)) {
244 $url = $this->_frames
[$this->_focus
]->getUrl();
245 $url->setTarget($this->_getPublicNameFromIndex($this->_focus
));
247 $url = $this->_frameset
->getUrl();
253 * Original request data.
254 * @return mixed Sent content.
257 function getRequestData() {
258 if (is_integer($this->_focus
)) {
259 return $this->_frames
[$this->_focus
]->getRequestData();
261 return $this->_frameset
->getRequestData();
265 * Accessor for current MIME type.
266 * @return string MIME type as string; e.g. 'text/html'
269 function getMimeType() {
270 if (is_integer($this->_focus
)) {
271 return $this->_frames
[$this->_focus
]->getMimeType();
273 return $this->_frameset
->getMimeType();
277 * Accessor for last response code.
278 * @return integer Last HTTP response code received.
281 function getResponseCode() {
282 if (is_integer($this->_focus
)) {
283 return $this->_frames
[$this->_focus
]->getResponseCode();
285 return $this->_frameset
->getResponseCode();
289 * Accessor for last Authentication type. Only valid
290 * straight after a challenge (401).
291 * @return string Description of challenge type.
294 function getAuthentication() {
295 if (is_integer($this->_focus
)) {
296 return $this->_frames
[$this->_focus
]->getAuthentication();
298 return $this->_frameset
->getAuthentication();
302 * Accessor for last Authentication realm. Only valid
303 * straight after a challenge (401).
304 * @return string Name of security realm.
307 function getRealm() {
308 if (is_integer($this->_focus
)) {
309 return $this->_frames
[$this->_focus
]->getRealm();
311 return $this->_frameset
->getRealm();
315 * Accessor for outgoing header information.
316 * @return string Header block.
319 function getRequest() {
320 if (is_integer($this->_focus
)) {
321 return $this->_frames
[$this->_focus
]->getRequest();
323 return $this->_frameset
->getRequest();
327 * Accessor for raw header information.
328 * @return string Header block.
331 function getHeaders() {
332 if (is_integer($this->_focus
)) {
333 return $this->_frames
[$this->_focus
]->getHeaders();
335 return $this->_frameset
->getHeaders();
339 * Accessor for parsed title.
340 * @return string Title or false if no title is present.
343 function getTitle() {
344 return $this->_frameset
->getTitle();
348 * Accessor for a list of all fixed links.
349 * @return array List of urls with scheme of
350 * http or https and hostname.
353 function getAbsoluteUrls() {
354 if (is_integer($this->_focus
)) {
355 return $this->_frames
[$this->_focus
]->getAbsoluteUrls();
358 foreach ($this->_frames
as $frame) {
359 $urls = array_merge($urls, $frame->getAbsoluteUrls());
361 return array_values(array_unique($urls));
365 * Accessor for a list of all relative links.
366 * @return array List of urls without hostname.
369 function getRelativeUrls() {
370 if (is_integer($this->_focus
)) {
371 return $this->_frames
[$this->_focus
]->getRelativeUrls();
374 foreach ($this->_frames
as $frame) {
375 $urls = array_merge($urls, $frame->getRelativeUrls());
377 return array_values(array_unique($urls));
381 * Accessor for URLs by the link label. Label will match
382 * regardess of whitespace issues and case.
383 * @param string $label Text of link.
384 * @return array List of links with that label.
387 function getUrlsByLabel($label) {
388 if (is_integer($this->_focus
)) {
389 return $this->_tagUrlsWithFrame(
390 $this->_frames
[$this->_focus
]->getUrlsByLabel($label),
394 foreach ($this->_frames
as $index => $frame) {
397 $this->_tagUrlsWithFrame(
398 $frame->getUrlsByLabel($label),
405 * Accessor for a URL by the id attribute. If in a frameset
406 * then the first link found with that ID attribute is
407 * returned only. Focus on a frame if you want one from
408 * a specific part of the frameset.
409 * @param string $id Id attribute of link.
410 * @return string URL with that id.
413 function getUrlById($id) {
414 foreach ($this->_frames
as $index => $frame) {
415 if ($url = $frame->getUrlById($id)) {
416 if (! $url->gettarget()) {
417 $url->setTarget($this->_getPublicNameFromIndex($index));
426 * Attaches the intended frame index to a list of URLs.
427 * @param array $urls List of SimpleUrls.
428 * @param string $frame Name of frame or index.
429 * @return array List of tagged URLs.
432 function _tagUrlsWithFrame($urls, $frame) {
434 foreach ($urls as $url) {
435 if (! $url->getTarget()) {
436 $url->setTarget($this->_getPublicNameFromIndex($frame));
444 * Finds a held form by button label. Will only
445 * search correctly built forms. The first form found
446 * either within the focused frame, or across frames,
447 * will be the one returned.
448 * @param string $label Button label, default 'Submit'.
449 * @return SimpleForm Form object containing the button.
452 function &getFormBySubmitLabel($label) {
453 return $this->_findForm('getFormBySubmitLabel', $label);
457 * Finds a held form by button label. Will only
458 * search correctly built forms. The first form found
459 * either within the focused frame, or across frames,
460 * will be the one returned.
461 * @param string $name Button name attribute.
462 * @return SimpleForm Form object containing the button.
465 function &getFormBySubmitName($name) {
466 return $this->_findForm('getFormBySubmitName', $name);
470 * Finds a held form by button id. Will only
471 * search correctly built forms. The first form found
472 * either within the focused frame, or across frames,
473 * will be the one returned.
474 * @param string $id Button ID attribute.
475 * @return SimpleForm Form object containing the button.
478 function &getFormBySubmitId($id) {
479 return $this->_findForm('getFormBySubmitId', $id);
483 * Finds a held form by image label. Will only
484 * search correctly built forms. The first form found
485 * either within the focused frame, or across frames,
486 * will be the one returned.
487 * @param string $label Usually the alt attribute.
488 * @return SimpleForm Form object containing the image.
491 function &getFormByImageLabel($label) {
492 return $this->_findForm('getFormByImageLabel', $label);
496 * Finds a held form by image button id. Will only
497 * search correctly built forms. The first form found
498 * either within the focused frame, or across frames,
499 * will be the one returned.
500 * @param string $name Image name.
501 * @return SimpleForm Form object containing the image.
504 function &getFormByImageName($name) {
505 return $this->_findForm('getFormByImageName', $name);
509 * Finds a held form by image button id. Will only
510 * search correctly built forms. The first form found
511 * either within the focused frame, or across frames,
512 * will be the one returned.
513 * @param string $id Image ID attribute.
514 * @return SimpleForm Form object containing the image.
517 function &getFormByImageId($id) {
518 return $this->_findForm('getFormByImageId', $id);
522 * Finds a held form by the form ID. A way of
523 * identifying a specific form when we have control
524 * of the HTML code. The first form found
525 * either within the focused frame, or across frames,
526 * will be the one returned.
527 * @param string $id Form label.
528 * @return SimpleForm Form object containing the matching ID.
531 function &getFormById($id) {
532 return $this->_findForm('getFormById', $id);
536 * General form finder. Will search all the frames or
537 * just the one in focus.
538 * @param string $method Method to use to find in a page.
539 * @param string $attribute Label, name or ID.
540 * @return SimpleForm Form object containing the matching ID.
543 function &_findForm($method, $attribute) {
544 if (is_integer($this->_focus
)) {
545 return $this->_findFormInFrame(
546 $this->_frames
[$this->_focus
],
551 for ($i = 0; $i < count($this->_frames
); $i++
) {
552 $form = &$this->_findFormInFrame(
565 * Finds a form in a page using a form finding method. Will
566 * also tag the form with the frame name it belongs in.
567 * @param SimplePage $page Page content of frame.
568 * @param integer $index Internal frame representation.
569 * @param string $method Method to use to find in a page.
570 * @param string $attribute Label, name or ID.
571 * @return SimpleForm Form object containing the matching ID.
574 function &_findFormInFrame(&$page, $index, $method, $attribute) {
575 $form = &$this->_frames
[$index]->$method($attribute);
577 $form->setDefaultTarget($this->_getPublicNameFromIndex($index));
583 * Sets a field on each form in which the field is
585 * @param string $name Field name.
586 * @param string $value Value to set field to.
587 * @return boolean True if value is valid.
590 function setField($name, $value) {
591 if (is_integer($this->_focus
)) {
592 $this->_frames
[$this->_focus
]->setField($name, $value);
594 for ($i = 0; $i < count($this->_frames
); $i++
) {
595 $this->_frames
[$i]->setField($name, $value);
601 * Sets a field on the form in which the unique field is
603 * @param string/integer $id Field ID attribute.
604 * @param string $value Value to set field to.
605 * @return boolean True if value is valid.
608 function setFieldById($id, $value) {
609 if (is_integer($this->_focus
)) {
610 $this->_frames
[$this->_focus
]->setFieldById($id, $value);
612 for ($i = 0; $i < count($this->_frames
); $i++
) {
613 $this->_frames
[$i]->setFieldById($id, $value);
619 * Accessor for a form element value within a frameset.
620 * Finds the first match amongst the frames.
621 * @param string $name Field name.
622 * @return string/boolean A string if the field is
623 * present, false if unchecked
624 * and null if missing.
627 function getField($name) {
628 for ($i = 0; $i < count($this->_frames
); $i++
) {
629 $value = $this->_frames
[$i]->getField($name);
638 * Accessor for a form element value within a page.
639 * Finds the first match.
640 * @param string/integer $id Field ID attribute.
641 * @return string/boolean A string if the field is
642 * present, false if unchecked
643 * and null if missing.
646 function getFieldById($id) {
647 for ($i = 0; $i < count($this->_frames
); $i++
) {
648 $value = $this->_frames
[$i]->getFieldById($id);