Whoops - parameters need to match category check and display of course.
[moodle-linuxchix.git] / lib / simpletestlib / frames.php
blobce669eaab116a96eff1f0815fc3849b2dba17d44
1 <?php
2 /**
3 * Base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage WebTester
6 * @version $Id$
7 */
9 /**#@+
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__) . '/page.php');
13 require_once(dirname(__FILE__) . '/user_agent.php');
14 /**#@-*/
16 /**
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.
21 * @package SimpleTest
22 * @subpackage WebTester
24 class SimpleFrameset {
25 var $_frameset;
26 var $_frames;
27 var $_focus;
28 var $_names;
30 /**
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();
42 /**
43 * Adds a parsed page to the frameset.
44 * @param SimplePage $page Frame page.
45 * @param string $name Name of frame in frameset.
46 * @access public
48 function addFrame(&$page, $name = false) {
49 $this->_frames[] = &$page;
50 if ($name) {
51 $this->_names[$name] = count($this->_frames) - 1;
55 /**
56 * Replaces existing frame with another. If the
57 * frame is nested, then the call is passed down
58 * one level.
59 * @param array $path Path of frame in frameset.
60 * @param SimplePage $page Frame source.
61 * @access public
63 function setFrame($path, &$page) {
64 $name = array_shift($path);
65 if (isset($this->_names[$name])) {
66 $index = $this->_names[$name];
67 } else {
68 $index = $name - 1;
70 if (count($path) == 0) {
71 $this->_frames[$index] = &$page;
72 return;
74 $this->_frames[$index]->setFrame($path, $page);
77 /**
78 * Accessor for current frame focus. Will be
79 * false if no frame has focus. Will have the nested
80 * frame focus if any.
81 * @return array Labels or indexes of nested frames.
82 * @access public
84 function getFrameFocus() {
85 if ($this->_focus === false) {
86 return array();
88 return array_merge(
89 array($this->_getPublicNameFromIndex($this->_focus)),
90 $this->_frames[$this->_focus]->getFrameFocus());
93 /**
94 * Turns an internal array index into the frames list
95 * into a public name, or if none, then a one offset
96 * index.
97 * @param integer $subject Internal index.
98 * @return integer/string Public name.
99 * @access private
101 function _getPublicNameFromIndex($subject) {
102 foreach ($this->_names as $name => $index) {
103 if ($subject == $index) {
104 return $name;
107 return $subject + 1;
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.
116 * @access public
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))) {
125 return false;
127 $this->_focus = $choice - 1;
128 return true;
132 * Sets the focus by name. If already focused and the
133 * target frame also has frames, then the nested frame
134 * will be focused.
135 * @param string $name Chosen frame.
136 * @return boolean True if frame exists.
137 * @access public
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];
147 return true;
149 return false;
153 * Clears the frame focus.
154 * @access public
156 function clearFrameFocus() {
157 $this->_focus = false;
158 $this->_clearNestedFramesFocus();
162 * Clears the frame focus for any nested frames.
163 * @access private
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.
174 * @access public
176 function hasFrames() {
177 return true;
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.
185 * @access public
187 function getFrames() {
188 $report = array();
189 for ($i = 0; $i < count($this->_frames); $i++) {
190 $report[$this->_getPublicNameFromIndex($i)] =
191 $this->_frames[$i]->getFrames();
193 return $report;
197 * Accessor for raw text of either all the pages or
198 * the frame in focus.
199 * @return string Raw unparsed content.
200 * @access public
202 function getRaw() {
203 if (is_integer($this->_focus)) {
204 return $this->_frames[$this->_focus]->getRaw();
206 $raw = '';
207 for ($i = 0; $i < count($this->_frames); $i++) {
208 $raw .= $this->_frames[$i]->getRaw();
210 return $raw;
214 * Accessor for plain text of either all the pages or
215 * the frame in focus.
216 * @return string Plain text content.
217 * @access public
219 function getText() {
220 if (is_integer($this->_focus)) {
221 return $this->_frames[$this->_focus]->getText();
223 $raw = '';
224 for ($i = 0; $i < count($this->_frames); $i++) {
225 $raw .= ' ' . $this->_frames[$i]->getText();
227 return trim($raw);
231 * Accessor for last error.
232 * @return string Error from last response.
233 * @access public
235 function getTransportError() {
236 if (is_integer($this->_focus)) {
237 return $this->_frames[$this->_focus]->getTransportError();
239 return $this->_frameset->getTransportError();
243 * Request method used to fetch this frame.
244 * @return string GET, POST or HEAD.
245 * @access public
247 function getMethod() {
248 if (is_integer($this->_focus)) {
249 return $this->_frames[$this->_focus]->getMethod();
251 return $this->_frameset->getMethod();
255 * Original resource name.
256 * @return SimpleUrl Current url.
257 * @access public
259 function getUrl() {
260 if (is_integer($this->_focus)) {
261 $url = $this->_frames[$this->_focus]->getUrl();
262 $url->setTarget($this->_getPublicNameFromIndex($this->_focus));
263 } else {
264 $url = $this->_frameset->getUrl();
266 return $url;
270 * Original request data.
271 * @return mixed Sent content.
272 * @access public
274 function getRequestData() {
275 if (is_integer($this->_focus)) {
276 return $this->_frames[$this->_focus]->getRequestData();
278 return $this->_frameset->getRequestData();
282 * Accessor for current MIME type.
283 * @return string MIME type as string; e.g. 'text/html'
284 * @access public
286 function getMimeType() {
287 if (is_integer($this->_focus)) {
288 return $this->_frames[$this->_focus]->getMimeType();
290 return $this->_frameset->getMimeType();
294 * Accessor for last response code.
295 * @return integer Last HTTP response code received.
296 * @access public
298 function getResponseCode() {
299 if (is_integer($this->_focus)) {
300 return $this->_frames[$this->_focus]->getResponseCode();
302 return $this->_frameset->getResponseCode();
306 * Accessor for last Authentication type. Only valid
307 * straight after a challenge (401).
308 * @return string Description of challenge type.
309 * @access public
311 function getAuthentication() {
312 if (is_integer($this->_focus)) {
313 return $this->_frames[$this->_focus]->getAuthentication();
315 return $this->_frameset->getAuthentication();
319 * Accessor for last Authentication realm. Only valid
320 * straight after a challenge (401).
321 * @return string Name of security realm.
322 * @access public
324 function getRealm() {
325 if (is_integer($this->_focus)) {
326 return $this->_frames[$this->_focus]->getRealm();
328 return $this->_frameset->getRealm();
332 * Accessor for outgoing header information.
333 * @return string Header block.
334 * @access public
336 function getRequest() {
337 if (is_integer($this->_focus)) {
338 return $this->_frames[$this->_focus]->getRequest();
340 return $this->_frameset->getRequest();
344 * Accessor for raw header information.
345 * @return string Header block.
346 * @access public
348 function getHeaders() {
349 if (is_integer($this->_focus)) {
350 return $this->_frames[$this->_focus]->getHeaders();
352 return $this->_frameset->getHeaders();
356 * Accessor for parsed title.
357 * @return string Title or false if no title is present.
358 * @access public
360 function getTitle() {
361 return $this->_frameset->getTitle();
365 * Accessor for a list of all fixed links.
366 * @return array List of urls with scheme of
367 * http or https and hostname.
368 * @access public
370 function getAbsoluteUrls() {
371 if (is_integer($this->_focus)) {
372 return $this->_frames[$this->_focus]->getAbsoluteUrls();
374 $urls = array();
375 foreach ($this->_frames as $frame) {
376 $urls = array_merge($urls, $frame->getAbsoluteUrls());
378 return array_values(array_unique($urls));
382 * Accessor for a list of all relative links.
383 * @return array List of urls without hostname.
384 * @access public
386 function getRelativeUrls() {
387 if (is_integer($this->_focus)) {
388 return $this->_frames[$this->_focus]->getRelativeUrls();
390 $urls = array();
391 foreach ($this->_frames as $frame) {
392 $urls = array_merge($urls, $frame->getRelativeUrls());
394 return array_values(array_unique($urls));
398 * Accessor for URLs by the link label. Label will match
399 * regardess of whitespace issues and case.
400 * @param string $label Text of link.
401 * @return array List of links with that label.
402 * @access public
404 function getUrlsByLabel($label) {
405 if (is_integer($this->_focus)) {
406 return $this->_tagUrlsWithFrame(
407 $this->_frames[$this->_focus]->getUrlsByLabel($label),
408 $this->_focus);
410 $urls = array();
411 foreach ($this->_frames as $index => $frame) {
412 $urls = array_merge(
413 $urls,
414 $this->_tagUrlsWithFrame(
415 $frame->getUrlsByLabel($label),
416 $index));
418 return $urls;
422 * Accessor for a URL by the id attribute. If in a frameset
423 * then the first link found with that ID attribute is
424 * returned only. Focus on a frame if you want one from
425 * a specific part of the frameset.
426 * @param string $id Id attribute of link.
427 * @return string URL with that id.
428 * @access public
430 function getUrlById($id) {
431 foreach ($this->_frames as $index => $frame) {
432 if ($url = $frame->getUrlById($id)) {
433 if (! $url->gettarget()) {
434 $url->setTarget($this->_getPublicNameFromIndex($index));
436 return $url;
439 return false;
443 * Attaches the intended frame index to a list of URLs.
444 * @param array $urls List of SimpleUrls.
445 * @param string $frame Name of frame or index.
446 * @return array List of tagged URLs.
447 * @access private
449 function _tagUrlsWithFrame($urls, $frame) {
450 $tagged = array();
451 foreach ($urls as $url) {
452 if (! $url->getTarget()) {
453 $url->setTarget($this->_getPublicNameFromIndex($frame));
455 $tagged[] = $url;
457 return $tagged;
461 * Finds a held form by button label. Will only
462 * search correctly built forms.
463 * @param SimpleSelector $selector Button finder.
464 * @return SimpleForm Form object containing
465 * the button.
466 * @access public
468 function &getFormBySubmit($selector) {
469 $form = &$this->_findForm('getFormBySubmit', $selector);
470 return $form;
474 * Finds a held form by image using a selector.
475 * Will only search correctly built forms. The first
476 * form found either within the focused frame, or
477 * across frames, will be the one returned.
478 * @param SimpleSelector $selector Image finder.
479 * @return SimpleForm Form object containing
480 * the image.
481 * @access public
483 function &getFormByImage($selector) {
484 $form = &$this->_findForm('getFormByImage', $selector);
485 return $form;
489 * Finds a held form by the form ID. A way of
490 * identifying a specific form when we have control
491 * of the HTML code. The first form found
492 * either within the focused frame, or across frames,
493 * will be the one returned.
494 * @param string $id Form label.
495 * @return SimpleForm Form object containing the matching ID.
496 * @access public
498 function &getFormById($id) {
499 $form = &$this->_findForm('getFormById', $id);
500 return $form;
504 * General form finder. Will search all the frames or
505 * just the one in focus.
506 * @param string $method Method to use to find in a page.
507 * @param string $attribute Label, name or ID.
508 * @return SimpleForm Form object containing the matching ID.
509 * @access private
511 function &_findForm($method, $attribute) {
512 if (is_integer($this->_focus)) {
513 $form = &$this->_findFormInFrame(
514 $this->_frames[$this->_focus],
515 $this->_focus,
516 $method,
517 $attribute);
518 return $form;
520 for ($i = 0; $i < count($this->_frames); $i++) {
521 $form = &$this->_findFormInFrame(
522 $this->_frames[$i],
524 $method,
525 $attribute);
526 if ($form) {
527 return $form;
530 $null = null;
531 return $null;
535 * Finds a form in a page using a form finding method. Will
536 * also tag the form with the frame name it belongs in.
537 * @param SimplePage $page Page content of frame.
538 * @param integer $index Internal frame representation.
539 * @param string $method Method to use to find in a page.
540 * @param string $attribute Label, name or ID.
541 * @return SimpleForm Form object containing the matching ID.
542 * @access private
544 function &_findFormInFrame(&$page, $index, $method, $attribute) {
545 $form = &$this->_frames[$index]->$method($attribute);
546 if (isset($form)) {
547 $form->setDefaultTarget($this->_getPublicNameFromIndex($index));
549 return $form;
553 * Sets a field on each form in which the field is
554 * available.
555 * @param SimpleSelector $selector Field finder.
556 * @param string $value Value to set field to.
557 * @return boolean True if value is valid.
558 * @access public
560 function setField($selector, $value) {
561 if (is_integer($this->_focus)) {
562 $this->_frames[$this->_focus]->setField($selector, $value);
563 } else {
564 for ($i = 0; $i < count($this->_frames); $i++) {
565 $this->_frames[$i]->setField($selector, $value);
571 * Accessor for a form element value within a page.
572 * @param SimpleSelector $selector Field finder.
573 * @return string/boolean A string if the field is
574 * present, false if unchecked
575 * and null if missing.
576 * @access public
578 function getField($selector) {
579 for ($i = 0; $i < count($this->_frames); $i++) {
580 $value = $this->_frames[$i]->getField($selector);
581 if (isset($value)) {
582 return $value;
585 return null;