MDL-39416 do not try to get detailed perflog info before PAGE int
[moodle.git] / lib / simpletestlib / frames.php
blobd6d8e96fd0c191c6eaf54895b260278040d818e4
1 <?php
2 /**
3 * Base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage WebTester
6 * @version $Id: frames.php 1784 2008-04-26 13:07:14Z pp11 $
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 private $frameset;
26 private $frames;
27 private $focus;
28 private $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 __construct($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 protected 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 protected 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 * Page base URL.
271 * @return SimpleUrl Current url.
272 * @access public
274 function getBaseUrl() {
275 if (is_integer($this->focus)) {
276 $url = $this->frames[$this->focus]->getBaseUrl();
277 } else {
278 $url = $this->frameset->getBaseUrl();
280 return $url;
284 * Expands expandomatic URLs into fully qualified
285 * URLs for the frameset page.
286 * @param SimpleUrl $url Relative URL.
287 * @return SimpleUrl Absolute URL.
288 * @access public
290 function expandUrl($url) {
291 return $this->frameset->expandUrl($url);
295 * Original request data.
296 * @return mixed Sent content.
297 * @access public
299 function getRequestData() {
300 if (is_integer($this->focus)) {
301 return $this->frames[$this->focus]->getRequestData();
303 return $this->frameset->getRequestData();
307 * Accessor for current MIME type.
308 * @return string MIME type as string; e.g. 'text/html'
309 * @access public
311 function getMimeType() {
312 if (is_integer($this->focus)) {
313 return $this->frames[$this->focus]->getMimeType();
315 return $this->frameset->getMimeType();
319 * Accessor for last response code.
320 * @return integer Last HTTP response code received.
321 * @access public
323 function getResponseCode() {
324 if (is_integer($this->focus)) {
325 return $this->frames[$this->focus]->getResponseCode();
327 return $this->frameset->getResponseCode();
331 * Accessor for last Authentication type. Only valid
332 * straight after a challenge (401).
333 * @return string Description of challenge type.
334 * @access public
336 function getAuthentication() {
337 if (is_integer($this->focus)) {
338 return $this->frames[$this->focus]->getAuthentication();
340 return $this->frameset->getAuthentication();
344 * Accessor for last Authentication realm. Only valid
345 * straight after a challenge (401).
346 * @return string Name of security realm.
347 * @access public
349 function getRealm() {
350 if (is_integer($this->focus)) {
351 return $this->frames[$this->focus]->getRealm();
353 return $this->frameset->getRealm();
357 * Accessor for outgoing header information.
358 * @return string Header block.
359 * @access public
361 function getRequest() {
362 if (is_integer($this->focus)) {
363 return $this->frames[$this->focus]->getRequest();
365 return $this->frameset->getRequest();
369 * Accessor for raw header information.
370 * @return string Header block.
371 * @access public
373 function getHeaders() {
374 if (is_integer($this->focus)) {
375 return $this->frames[$this->focus]->getHeaders();
377 return $this->frameset->getHeaders();
381 * Accessor for parsed title.
382 * @return string Title or false if no title is present.
383 * @access public
385 function getTitle() {
386 return $this->frameset->getTitle();
390 * Accessor for a list of all fixed links.
391 * @return array List of urls as strings.
392 * @access public
394 function getUrls() {
395 if (is_integer($this->focus)) {
396 return $this->frames[$this->focus]->getUrls();
398 $urls = array();
399 foreach ($this->frames as $frame) {
400 $urls = array_merge($urls, $frame->getUrls());
402 return array_values(array_unique($urls));
406 * Accessor for URLs by the link label. Label will match
407 * regardess of whitespace issues and case.
408 * @param string $label Text of link.
409 * @return array List of links with that label.
410 * @access public
412 function getUrlsByLabel($label) {
413 if (is_integer($this->focus)) {
414 return $this->tagUrlsWithFrame(
415 $this->frames[$this->focus]->getUrlsByLabel($label),
416 $this->focus);
418 $urls = array();
419 foreach ($this->frames as $index => $frame) {
420 $urls = array_merge(
421 $urls,
422 $this->tagUrlsWithFrame(
423 $frame->getUrlsByLabel($label),
424 $index));
426 return $urls;
430 * Accessor for a URL by the id attribute. If in a frameset
431 * then the first link found with that ID attribute is
432 * returned only. Focus on a frame if you want one from
433 * a specific part of the frameset.
434 * @param string $id Id attribute of link.
435 * @return string URL with that id.
436 * @access public
438 function getUrlById($id) {
439 foreach ($this->frames as $index => $frame) {
440 if ($url = $frame->getUrlById($id)) {
441 if (! $url->gettarget()) {
442 $url->setTarget($this->getPublicNameFromIndex($index));
444 return $url;
447 return false;
451 * Attaches the intended frame index to a list of URLs.
452 * @param array $urls List of SimpleUrls.
453 * @param string $frame Name of frame or index.
454 * @return array List of tagged URLs.
455 * @access private
457 protected function tagUrlsWithFrame($urls, $frame) {
458 $tagged = array();
459 foreach ($urls as $url) {
460 if (! $url->getTarget()) {
461 $url->setTarget($this->getPublicNameFromIndex($frame));
463 $tagged[] = $url;
465 return $tagged;
469 * Finds a held form by button label. Will only
470 * search correctly built forms.
471 * @param SimpleSelector $selector Button finder.
472 * @return SimpleForm Form object containing
473 * the button.
474 * @access public
476 function getFormBySubmit($selector) {
477 return $this->findForm('getFormBySubmit', $selector);
481 * Finds a held form by image using a selector.
482 * Will only search correctly built forms. The first
483 * form found either within the focused frame, or
484 * across frames, will be the one returned.
485 * @param SimpleSelector $selector Image finder.
486 * @return SimpleForm Form object containing
487 * the image.
488 * @access public
490 function getFormByImage($selector) {
491 return $this->findForm('getFormByImage', $selector);
495 * Finds a held form by the form ID. A way of
496 * identifying a specific form when we have control
497 * of the HTML code. The first form found
498 * either within the focused frame, or across frames,
499 * will be the one returned.
500 * @param string $id Form label.
501 * @return SimpleForm Form object containing the matching ID.
502 * @access public
504 function getFormById($id) {
505 return $this->findForm('getFormById', $id);
509 * General form finder. Will search all the frames or
510 * just the one in focus.
511 * @param string $method Method to use to find in a page.
512 * @param string $attribute Label, name or ID.
513 * @return SimpleForm Form object containing the matching ID.
514 * @access private
516 protected function findForm($method, $attribute) {
517 if (is_integer($this->focus)) {
518 return $this->findFormInFrame(
519 $this->frames[$this->focus],
520 $this->focus,
521 $method,
522 $attribute);
524 for ($i = 0; $i < count($this->frames); $i++) {
525 $form = $this->findFormInFrame(
526 $this->frames[$i],
528 $method,
529 $attribute);
530 if ($form) {
531 return $form;
534 $null = null;
535 return $null;
539 * Finds a form in a page using a form finding method. Will
540 * also tag the form with the frame name it belongs in.
541 * @param SimplePage $page Page content of frame.
542 * @param integer $index Internal frame representation.
543 * @param string $method Method to use to find in a page.
544 * @param string $attribute Label, name or ID.
545 * @return SimpleForm Form object containing the matching ID.
546 * @access private
548 protected function findFormInFrame($page, $index, $method, $attribute) {
549 $form = $this->frames[$index]->$method($attribute);
550 if (isset($form)) {
551 $form->setDefaultTarget($this->getPublicNameFromIndex($index));
553 return $form;
557 * Sets a field on each form in which the field is
558 * available.
559 * @param SimpleSelector $selector Field finder.
560 * @param string $value Value to set field to.
561 * @return boolean True if value is valid.
562 * @access public
564 function setField($selector, $value) {
565 if (is_integer($this->focus)) {
566 $this->frames[$this->focus]->setField($selector, $value);
567 } else {
568 for ($i = 0; $i < count($this->frames); $i++) {
569 $this->frames[$i]->setField($selector, $value);
575 * Accessor for a form element value within a page.
576 * @param SimpleSelector $selector Field finder.
577 * @return string/boolean A string if the field is
578 * present, false if unchecked
579 * and null if missing.
580 * @access public
582 function getField($selector) {
583 for ($i = 0; $i < count($this->frames); $i++) {
584 $value = $this->frames[$i]->getField($selector);
585 if (isset($value)) {
586 return $value;
589 return null;