Source for file page.php

Documentation is available at page.php

  1. <?php
  2. /**
  3.  *  Base include file for SimpleTest
  4.  *  @package    SimpleTest
  5.  *  @subpackage WebTester
  6.  *  @version    $Id: page.php 1672 2008-03-02 04:47:34Z edwardzyang $
  7.  */
  8.  
  9. /**#@+
  10.     *   include other SimpleTest class files
  11.     */
  12. require_once(dirname(__FILE__'/http.php');
  13. require_once(dirname(__FILE__'/parser.php');
  14. require_once(dirname(__FILE__'/tag.php');
  15. require_once(dirname(__FILE__'/form.php');
  16. require_once(dirname(__FILE__'/selector.php');
  17. /**#@-*/
  18.  
  19.  *    Creates tags and widgets given HTML tag
  20.  *    attributes.
  21.  *    @package SimpleTest
  22.  *    @subpackage WebTester
  23.  */
  24.  
  25.     /**
  26.      *    Factory for the tag objects. Creates the
  27.      *    appropriate tag object for the incoming tag name
  28.      *    and attributes.
  29.      *    @param string $name        HTML tag name.
  30.      *    @param hash $attributes    Element attributes.
  31.      *    @return SimpleTag          Tag object.
  32.      *    @access public
  33.      */
  34.     function createTag($name$attributes{
  35.         static $map array(
  36.                 'a' => 'SimpleAnchorTag',
  37.                 'title' => 'SimpleTitleTag',
  38.                 'base' => 'SimpleBaseTag',
  39.                 'button' => 'SimpleButtonTag',
  40.                 'textarea' => 'SimpleTextAreaTag',
  41.                 'option' => 'SimpleOptionTag',
  42.                 'label' => 'SimpleLabelTag',
  43.                 'form' => 'SimpleFormTag',
  44.                 'frame' => 'SimpleFrameTag');
  45.         $attributes $this->_keysToLowerCase($attributes);
  46.         if (array_key_exists($name$map)) {
  47.             $tag_class $map[$name];
  48.             return new $tag_class($attributes);
  49.         elseif ($name == 'select'{
  50.             return $this->_createSelectionTag($attributes);
  51.         elseif ($name == 'input'{
  52.             return $this->_createInputTag($attributes);
  53.         }
  54.         return new SimpleTag($name$attributes);
  55.     }
  56.  
  57.     /**
  58.      *    Factory for selection fields.
  59.      *    @param hash $attributes    Element attributes.
  60.      *    @return SimpleTag          Tag object.
  61.      *    @access protected
  62.      */
  63.     function _createSelectionTag($attributes{
  64.         if (isset($attributes['multiple'])) {
  65.             return new MultipleSelectionTag($attributes);
  66.         }
  67.         return new SimpleSelectionTag($attributes);
  68.     }
  69.  
  70.     /**
  71.      *    Factory for input tags.
  72.      *    @param hash $attributes    Element attributes.
  73.      *    @return SimpleTag          Tag object.
  74.      *    @access protected
  75.      */
  76.     function _createInputTag($attributes{
  77.         if (isset($attributes['type'])) {
  78.             return new SimpleTextTag($attributes);
  79.         }
  80.         $type strtolower(trim($attributes['type']));
  81.         $map array(
  82.                 'submit' => 'SimpleSubmitTag',
  83.                 'image' => 'SimpleImageSubmitTag',
  84.                 'checkbox' => 'SimpleCheckboxTag',
  85.                 'radio' => 'SimpleRadioButtonTag',
  86.                 'text' => 'SimpleTextTag',
  87.                 'hidden' => 'SimpleTextTag',
  88.                 'password' => 'SimpleTextTag',
  89.                 'file' => 'SimpleUploadTag');
  90.         if (array_key_exists($type$map)) {
  91.             $tag_class $map[$type];
  92.             return new $tag_class($attributes);
  93.         }
  94.         return false;
  95.     }
  96.  
  97.     /**
  98.      *    Make the keys lower case for case insensitive look-ups.
  99.      *    @param hash $map   Hash to convert.
  100.      *    @return hash       Unchanged values, but keys lower case.
  101.      *    @access private
  102.      */
  103.     function _keysToLowerCase($map{
  104.         $lower array();
  105.         foreach ($map as $key => $value{
  106.             $lower[strtolower($key)$value;
  107.         }
  108.         return $lower;
  109.     }
  110. }
  111.  
  112. /**
  113.  *    SAX event handler. Maintains a list of
  114.  *    open tags and dispatches them as they close.
  115.  *    @package SimpleTest
  116.  *    @subpackage WebTester
  117.  */
  118.     var $_tags;
  119.     var $_page;
  120.     var $_private_content_tag;
  121.  
  122.     /**
  123.      *    Sets the builder up empty.
  124.      *    @access public
  125.      */
  126.     function SimplePageBuilder({
  127.         $this->SimpleSaxListener();
  128.     }
  129.     
  130.     /**
  131.      *    Frees up any references so as to allow the PHP garbage
  132.      *    collection from unset() to work.
  133.      *    @access public
  134.      */
  135.     function free({
  136.         unset($this->_tags);
  137.         unset($this->_page);
  138.         unset($this->_private_content_tags);
  139.     }
  140.  
  141.     /**
  142.      *    Reads the raw content and send events
  143.      *    into the page to be built.
  144.      *    @param $response SimpleHttpResponse  Fetched response.
  145.      *    @return SimplePage                   Newly parsed page.
  146.      *    @access public
  147.      */
  148.     function &parse($response{
  149.         $this->_tags = array();
  150.         $this->_page = &$this->_createPage($response);
  151.         $parser &$this->_createParser($this);
  152.         $parser->parse($response->getContent());
  153.         $this->_page->acceptPageEnd();
  154.         return $this->_page;
  155.     }
  156.  
  157.     /**
  158.      *    Creates an empty page.
  159.      *    @return SimplePage        New unparsed page.
  160.      *    @access protected
  161.      */
  162.     function &_createPage($response{
  163.         $page &new SimplePage($response);
  164.         return $page;
  165.     }
  166.  
  167.     /**
  168.      *    Creates the parser used with the builder.
  169.      *    @param $listener SimpleSaxListener   Target of parser.
  170.      *    @return SimpleSaxParser              Parser to generate
  171.      *                                          events for the builder.
  172.      *    @access protected
  173.      */
  174.     function &_createParser(&$listener{
  175.         $parser &new SimpleHtmlSaxParser($listener);
  176.         return $parser;
  177.     }
  178.     
  179.     /**
  180.      *    Start of element event. Opens a new tag.
  181.      *    @param string $name         Element name.
  182.      *    @param hash $attributes     Attributes without content
  183.      *                                 are marked as true.
  184.      *    @return boolean             False on parse error.
  185.      *    @access public
  186.      */
  187.     function startElement($name$attributes{
  188.         $factory &new SimpleTagBuilder();
  189.         $tag $factory->createTag($name$attributes);
  190.         if ($tag{
  191.             return true;
  192.         }
  193.         if ($tag->getTagName(== 'label'{
  194.             $this->_page->acceptLabelStart($tag);
  195.             $this->_openTag($tag);
  196.             return true;
  197.         }
  198.         if ($tag->getTagName(== 'form'{
  199.             $this->_page->acceptFormStart($tag);
  200.             return true;
  201.         }
  202.         if ($tag->getTagName(== 'frameset'{
  203.             $this->_page->acceptFramesetStart($tag);
  204.             return true;
  205.         }
  206.         if ($tag->getTagName(== 'frame'{
  207.             $this->_page->acceptFrame($tag);
  208.             return true;
  209.         }
  210.         if ($tag->isPrivateContent(&& isset($this->_private_content_tag)) {
  211.             $this->_private_content_tag = &$tag;
  212.         }
  213.         if ($tag->expectEndTag()) {
  214.             $this->_openTag($tag);
  215.             return true;
  216.         }
  217.         $this->_page->acceptTag($tag);
  218.         return true;
  219.     }
  220.  
  221.     /**
  222.      *    End of element event.
  223.      *    @param string $name        Element name.
  224.      *    @return boolean            False on parse error.
  225.      *    @access public
  226.      */
  227.     function endElement($name{
  228.         if ($name == 'label'{
  229.             $this->_page->acceptLabelEnd();
  230.             return true;
  231.         }
  232.         if ($name == 'form'{
  233.             $this->_page->acceptFormEnd();
  234.             return true;
  235.         }
  236.         if ($name == 'frameset'{
  237.             $this->_page->acceptFramesetEnd();
  238.             return true;
  239.         }
  240.         if ($this->_hasNamedTagOnOpenTagStack($name)) {
  241.             $tag array_pop($this->_tags[$name]);
  242.             if ($tag->isPrivateContent(&& $this->_private_content_tag->getTagName(== $name{
  243.                 unset($this->_private_content_tag);
  244.             }
  245.             $this->_addContentTagToOpenTags($tag);
  246.             $this->_page->acceptTag($tag);
  247.             return true;
  248.         }
  249.         return true;
  250.     }
  251.  
  252.     /**
  253.      *    Test to see if there are any open tags awaiting
  254.      *    closure that match the tag name.
  255.      *    @param string $name        Element name.
  256.      *    @return boolean            True if any are still open.
  257.      *    @access private
  258.      */
  259.     function _hasNamedTagOnOpenTagStack($name{
  260.         return isset($this->_tags[$name]&& (count($this->_tags[$name]0);
  261.     }
  262.  
  263.     /**
  264.      *    Unparsed, but relevant data. The data is added
  265.      *    to every open tag.
  266.      *    @param string $text        May include unparsed tags.
  267.      *    @return boolean            False on parse error.
  268.      *    @access public
  269.      */
  270.     function addContent($text{
  271.         if (isset($this->_private_content_tag)) {
  272.             $this->_private_content_tag->addContent($text);
  273.         else {
  274.             $this->_addContentToAllOpenTags($text);
  275.         }
  276.         return true;
  277.     }
  278.  
  279.     /**
  280.      *    Any content fills all currently open tags unless it
  281.      *    is part of an option tag.
  282.      *    @param string $text        May include unparsed tags.
  283.      *    @access private
  284.      */
  285.     function _addContentToAllOpenTags($text{
  286.         foreach (array_keys($this->_tagsas $name{
  287.             for ($i 0$count count($this->_tags[$name])$i $count$i++{
  288.                 $this->_tags[$name][$i]->addContent($text);
  289.             }
  290.         }
  291.     }
  292.  
  293.     /**
  294.      *    Parsed data in tag form. The parsed tag is added
  295.      *    to every open tag. Used for adding options to select
  296.      *    fields only.
  297.      *    @param SimpleTag $tag        Option tags only.
  298.      *    @access private
  299.      */
  300.     function _addContentTagToOpenTags(&$tag{
  301.         if ($tag->getTagName(!= 'option'{
  302.             return;
  303.         }
  304.         foreach (array_keys($this->_tagsas $name{
  305.             for ($i 0$count count($this->_tags[$name])$i $count$i++{
  306.                 $this->_tags[$name][$i]->addTag($tag);
  307.             }
  308.         }
  309.     }
  310.  
  311.     /**
  312.      *    Opens a tag for receiving content. Multiple tags
  313.      *    will be receiving input at the same time.
  314.      *    @param SimpleTag $tag        New content tag.
  315.      *    @access private
  316.      */
  317.     function _openTag(&$tag{
  318.         $name $tag->getTagName();
  319.         if (in_array($namearray_keys($this->_tags))) {
  320.             $this->_tags[$namearray();
  321.         }
  322.         $this->_tags[$name][&$tag;
  323.     }
  324. }
  325.  
  326. /**
  327.  *    A wrapper for a web page.
  328.  *    @package SimpleTest
  329.  *    @subpackage WebTester
  330.  */
  331. class SimplePage {
  332.     var $_links;
  333.     var $_title;
  334.     var $_last_widget;
  335.     var $_label;
  336.     var $_left_over_labels;
  337.     var $_open_forms;
  338.     var $_complete_forms;
  339.     var $_frameset;
  340.     var $_frames;
  341.     var $_transport_error;
  342.     var $_raw;
  343.     var $_text;
  344.     var $_sent;
  345.     var $_headers;
  346.     var $_method;
  347.     var $_url;
  348.     var $_base = false;
  349.     var $_request_data;
  350.  
  351.     /**
  352.      *    Parses a page ready to access it's contents.
  353.      *    @param SimpleHttpResponse $response     Result of HTTP fetch.
  354.      *    @access public
  355.      */
  356.     function SimplePage($response false{
  357.         $this->_links = array();
  358.         $this->_title = false;
  359.         $this->_left_over_labels = array();
  360.         $this->_open_forms = array();
  361.         $this->_complete_forms = array();
  362.         $this->_frameset = false;
  363.         $this->_frames = array();
  364.         $this->_frameset_nesting_level = 0;
  365.         $this->_text = false;
  366.         if ($response{
  367.             $this->_extractResponse($response);
  368.         else {
  369.             $this->_noResponse();
  370.         }
  371.     }
  372.  
  373.     /**
  374.      *    Extracts all of the response information.
  375.      *    @param SimpleHttpResponse $response    Response being parsed.
  376.      *    @access private
  377.      */
  378.     function _extractResponse($response{
  379.         $this->_transport_error = $response->getError();
  380.         $this->_raw = $response->getContent();
  381.         $this->_sent = $response->getSent();
  382.         $this->_headers = $response->getHeaders();
  383.         $this->_method = $response->getMethod();
  384.         $this->_url = $response->getUrl();
  385.         $this->_request_data = $response->getRequestData();
  386.     }
  387.  
  388.     /**
  389.      *    Sets up a missing response.
  390.      *    @access private
  391.      */
  392.     function _noResponse({
  393.         $this->_transport_error = 'No page fetched yet';
  394.         $this->_raw = false;
  395.         $this->_sent = false;
  396.         $this->_headers = false;
  397.         $this->_method = 'GET';
  398.         $this->_url = false;
  399.         $this->_request_data = false;
  400.     }
  401.  
  402.     /**
  403.      *    Original request as bytes sent down the wire.
  404.      *    @return mixed              Sent content.
  405.      *    @access public
  406.      */
  407.     function getRequest({
  408.         return $this->_sent;
  409.     }
  410.  
  411.     /**
  412.      *    Accessor for raw text of page.
  413.      *    @return string        Raw unparsed content.
  414.      *    @access public
  415.      */
  416.     function getRaw({
  417.         return $this->_raw;
  418.     }
  419.  
  420.     /**
  421.      *    Accessor for plain text of page as a text browser
  422.      *    would see it.
  423.      *    @return string        Plain text of page.
  424.      *    @access public
  425.      */
  426.     function getText({
  427.         if ($this->_text{
  428.             $this->_text = SimpleHtmlSaxParser::normalise($this->_raw);
  429.         }
  430.         return $this->_text;
  431.     }
  432.  
  433.     /**
  434.      *    Accessor for raw headers of page.
  435.      *    @return string       Header block as text.
  436.      *    @access public
  437.      */
  438.     function getHeaders({
  439.         if ($this->_headers{
  440.             return $this->_headers->getRaw();
  441.         }
  442.         return false;
  443.     }
  444.  
  445.     /**
  446.      *    Original request method.
  447.      *    @return string        GET, POST or HEAD.
  448.      *    @access public
  449.      */
  450.     function getMethod({
  451.         return $this->_method;
  452.     }
  453.  
  454.     /**
  455.      *    Original resource name.
  456.      *    @return SimpleUrl        Current url.
  457.      *    @access public
  458.      */
  459.     function getUrl({
  460.         return $this->_url;
  461.     }
  462.  
  463.     /**
  464.      *    Base URL if set via BASE tag page url otherwise
  465.      *    @return SimpleUrl        Base url.
  466.      *    @access public
  467.      */
  468.     function getBaseUrl({
  469.         return $this->_base;
  470.     }
  471.  
  472.     /**
  473.      *    Original request data.
  474.      *    @return mixed              Sent content.
  475.      *    @access public
  476.      */
  477.     function getRequestData({
  478.         return $this->_request_data;
  479.     }
  480.  
  481.     /**
  482.      *    Accessor for last error.
  483.      *    @return string        Error from last response.
  484.      *    @access public
  485.      */
  486.     function getTransportError({
  487.         return $this->_transport_error;
  488.     }
  489.  
  490.     /**
  491.      *    Accessor for current MIME type.
  492.      *    @return string    MIME type as string; e.g. 'text/html'
  493.      *    @access public
  494.      */
  495.     function getMimeType({
  496.         if ($this->_headers{
  497.             return $this->_headers->getMimeType();
  498.         }
  499.         return false;
  500.     }
  501.  
  502.     /**
  503.      *    Accessor for HTTP response code.
  504.      *    @return integer    HTTP response code received.
  505.      *    @access public
  506.      */
  507.     function getResponseCode({
  508.         if ($this->_headers{
  509.             return $this->_headers->getResponseCode();
  510.         }
  511.         return false;
  512.     }
  513.  
  514.     /**
  515.      *    Accessor for last Authentication type. Only valid
  516.      *    straight after a challenge (401).
  517.      *    @return string    Description of challenge type.
  518.      *    @access public
  519.      */
  520.     function getAuthentication({
  521.         if ($this->_headers{
  522.             return $this->_headers->getAuthentication();
  523.         }
  524.         return false;
  525.     }
  526.  
  527.     /**
  528.      *    Accessor for last Authentication realm. Only valid
  529.      *    straight after a challenge (401).
  530.      *    @return string    Name of security realm.
  531.      *    @access public
  532.      */
  533.     function getRealm({
  534.         if ($this->_headers{
  535.             return $this->_headers->getRealm();
  536.         }
  537.         return false;
  538.     }
  539.  
  540.     /**
  541.      *    Accessor for current frame focus. Will be
  542.      *    false as no frames.
  543.      *    @return array    Always empty.
  544.      *    @access public
  545.      */
  546.     function getFrameFocus({
  547.         return array();
  548.     }
  549.  
  550.     /**
  551.      *    Sets the focus by index. The integer index starts from 1.
  552.      *    @param integer $choice    Chosen frame.
  553.      *    @return boolean           Always false.
  554.      *    @access public
  555.      */
  556.     function setFrameFocusByIndex($choice{
  557.         return false;
  558.     }
  559.  
  560.     /**
  561.      *    Sets the focus by name. Always fails for a leaf page.
  562.      *    @param string $name    Chosen frame.
  563.      *    @return boolean        False as no frames.
  564.      *    @access public
  565.      */
  566.     function setFrameFocus($name{
  567.         return false;
  568.     }
  569.  
  570.     /**
  571.      *    Clears the frame focus. Does nothing for a leaf page.
  572.      *    @access public
  573.      */
  574.     function clearFrameFocus({
  575.     }
  576.  
  577.     /**
  578.      *    Adds a tag to the page.
  579.      *    @param SimpleTag $tag        Tag to accept.
  580.      *    @access public
  581.      */
  582.     function acceptTag(&$tag{
  583.         if ($tag->getTagName(== "a"{
  584.             $this->_addLink($tag);
  585.         elseif ($tag->getTagName(== "base"{
  586.             $this->_setBase($tag);
  587.         elseif ($tag->getTagName(== "title"{
  588.             $this->_setTitle($tag);
  589.         elseif ($this->_isFormElement($tag->getTagName())) {
  590.             for ($i 0$i count($this->_open_forms)$i++{
  591.                 $this->_open_forms[$i]->addWidget($tag);
  592.             }
  593.             $this->_last_widget = &$tag;
  594.         }
  595.     }
  596.  
  597.     /**
  598.      *    Opens a label for a described widget.
  599.      *    @param SimpleFormTag $tag      Tag to accept.
  600.      *    @access public
  601.      */
  602.     function acceptLabelStart(&$tag{
  603.         $this->_label = &$tag;
  604.         unset($this->_last_widget);
  605.     }
  606.  
  607.     /**
  608.      *    Closes the most recently opened label.
  609.      *    @access public
  610.      */
  611.     function acceptLabelEnd({
  612.         if (isset($this->_label)) {
  613.             if (isset($this->_last_widget)) {
  614.                 $this->_last_widget->setLabel($this->_label->getText());
  615.                 unset($this->_last_widget);
  616.             else {
  617.                 $this->_left_over_labels[SimpleTestCompatibility::copy($this->_label);
  618.             }
  619.             unset($this->_label);
  620.         }
  621.     }
  622.  
  623.     /**
  624.      *    Tests to see if a tag is a possible form
  625.      *    element.
  626.      *    @param string $name     HTML element name.
  627.      *    @return boolean         True if form element.
  628.      *    @access private
  629.      */
  630.     function _isFormElement($name{
  631.         return in_array($namearray('input''button''textarea''select'));
  632.     }
  633.  
  634.     /**
  635.      *    Opens a form. New widgets go here.
  636.      *    @param SimpleFormTag $tag      Tag to accept.
  637.      *    @access public
  638.      */
  639.     function acceptFormStart(&$tag{
  640.         $this->_open_forms[&new SimpleForm($tag$this);
  641.     }
  642.  
  643.     /**
  644.      *    Closes the most recently opened form.
  645.      *    @access public
  646.      */
  647.     function acceptFormEnd({
  648.         if (count($this->_open_forms)) {
  649.             $this->_complete_forms[array_pop($this->_open_forms);
  650.         }
  651.     }
  652.  
  653.     /**
  654.      *    Opens a frameset. A frameset may contain nested
  655.      *    frameset tags.
  656.      *    @param SimpleFramesetTag $tag      Tag to accept.
  657.      *    @access public
  658.      */
  659.     function acceptFramesetStart(&$tag{
  660.         if ($this->_isLoadingFrames()) {
  661.             $this->_frameset = &$tag;
  662.         }
  663.         $this->_frameset_nesting_level++;
  664.     }
  665.  
  666.     /**
  667.      *    Closes the most recently opened frameset.
  668.      *    @access public
  669.      */
  670.     function acceptFramesetEnd({
  671.         if ($this->_isLoadingFrames()) {
  672.             $this->_frameset_nesting_level--;
  673.         }
  674.     }
  675.  
  676.     /**
  677.      *    Takes a single frame tag and stashes it in
  678.      *    the current frame set.
  679.      *    @param SimpleFrameTag $tag      Tag to accept.
  680.      *    @access public
  681.      */
  682.     function acceptFrame(&$tag{
  683.         if ($this->_isLoadingFrames()) {
  684.             if ($tag->getAttribute('src')) {
  685.                 $this->_frames[&$tag;
  686.             }
  687.         }
  688.     }
  689.  
  690.     /**
  691.      *    Test to see if in the middle of reading
  692.      *    a frameset.
  693.      *    @return boolean        True if inframeset.
  694.      *    @access private
  695.      */
  696.     function _isLoadingFrames({
  697.         if ($this->_frameset{
  698.             return false;
  699.         }
  700.         return ($this->_frameset_nesting_level > 0);
  701.     }
  702.  
  703.     /**
  704.      *    Test to see if link is an absolute one.
  705.      *    @param string $url     Url to test.
  706.      *    @return boolean        True if absolute.
  707.      *    @access protected
  708.      */
  709.     function _linkIsAbsolute($url{
  710.         $parsed new SimpleUrl($url);
  711.         return (boolean)($parsed->getScheme(&& $parsed->getHost());
  712.     }
  713.  
  714.     /**
  715.      *    Adds a link to the page.
  716.      *    @param SimpleAnchorTag $tag      Link to accept.
  717.      *    @access protected
  718.      */
  719.     function _addLink($tag{
  720.         $this->_links[$tag;
  721.     }
  722.  
  723.     /**
  724.      *    Marker for end of complete page. Any work in
  725.      *    progress can now be closed.
  726.      *    @access public
  727.      */
  728.     function acceptPageEnd({
  729.         while (count($this->_open_forms)) {
  730.             $this->_complete_forms[array_pop($this->_open_forms);
  731.         }
  732.         foreach ($this->_left_over_labels as $label{
  733.             for ($i 0$count count($this->_complete_forms)$i $count$i++{
  734.                 $this->_complete_forms[$i]->attachLabelBySelector(
  735.                         new SimpleById($label->getFor()),
  736.                         $label->getText());
  737.             }
  738.         }
  739.     }
  740.  
  741.     /**
  742.      *    Test for the presence of a frameset.
  743.      *    @return boolean        True if frameset.
  744.      *    @access public
  745.      */
  746.     function hasFrames({
  747.         return (boolean)$this->_frameset;
  748.     }
  749.  
  750.     /**
  751.      *    Accessor for frame name and source URL for every frame that
  752.      *    will need to be loaded. Immediate children only.
  753.      *    @return boolean/array     False if no frameset or
  754.      *                               otherwise a hash of frame URLs.
  755.      *                               The key is either a numerical
  756.      *                               base one index or the name attribute.
  757.      *    @access public
  758.      */
  759.     function getFrameset({
  760.         if ($this->_frameset{
  761.             return false;
  762.         }
  763.         $urls array();
  764.         for ($i 0$i count($this->_frames)$i++{
  765.             $name $this->_frames[$i]->getAttribute('name');
  766.             $url new SimpleUrl($this->_frames[$i]->getAttribute('src'));
  767.             $urls[$name $name $i 1$this->expandUrl($url);
  768.         }
  769.         return $urls;
  770.     }
  771.  
  772.     /**
  773.      *    Fetches a list of loaded frames.
  774.      *    @return array/string    Just the URL for a single page.
  775.      *    @access public
  776.      */
  777.     function getFrames({
  778.         $url $this->expandUrl($this->getUrl());
  779.         return $url->asString();
  780.     }
  781.  
  782.     /**
  783.      *    Accessor for a list of all links.
  784.      *    @return array   List of urls with scheme of
  785.      *                     http or https and hostname.
  786.      *    @access public
  787.      */
  788.     function getUrls({
  789.         $all array();
  790.         foreach ($this->_links as $link{
  791.             $url $this->_getUrlFromLink($link);
  792.             $all[$url->asString();
  793.         }
  794.         return $all;
  795.     }
  796.  
  797.     /**
  798.      *    Accessor for URLs by the link label. Label will match
  799.      *    regardess of whitespace issues and case.
  800.      *    @param string $label    Text of link.
  801.      *    @return array           List of links with that label.
  802.      *    @access public
  803.      */
  804.     function getUrlsByLabel($label{
  805.         $matches array();
  806.         foreach ($this->_links as $link{
  807.             if ($link->getText(== $label{
  808.                 $matches[$this->_getUrlFromLink($link);
  809.             }
  810.         }
  811.         return $matches;
  812.     }
  813.  
  814.     /**
  815.      *    Accessor for a URL by the id attribute.
  816.      *    @param string $id       Id attribute of link.
  817.      *    @return SimpleUrl       URL with that id of false if none.
  818.      *    @access public
  819.      */
  820.     function getUrlById($id{
  821.         foreach ($this->_links as $link{
  822.             if ($link->getAttribute('id'=== (string)$id{
  823.                 return $this->_getUrlFromLink($link);
  824.             }
  825.         }
  826.         return false;
  827.     }
  828.  
  829.     /**
  830.      *    Converts a link tag into a target URL.
  831.      *    @param SimpleAnchor $link    Parsed link.
  832.      *    @return SimpleUrl            URL with frame target if any.
  833.      *    @access private
  834.      */
  835.     function _getUrlFromLink($link{
  836.         $url $this->expandUrl($link->getHref());
  837.         if ($link->getAttribute('target')) {
  838.             $url->setTarget($link->getAttribute('target'));
  839.         }
  840.         return $url;
  841.     }
  842.  
  843.     /**
  844.      *    Expands expandomatic URLs into fully qualified
  845.      *    URLs.
  846.      *    @param SimpleUrl $url        Relative URL.
  847.      *    @return SimpleUrl            Absolute URL.
  848.      *    @access public
  849.      */
  850.     function expandUrl($url{
  851.         if (is_object($url)) {
  852.             $url new SimpleUrl($url);
  853.         }
  854.         $location $this->getBaseUrl($this->getBaseUrl(new SimpleUrl();
  855.         return $url->makeAbsolute($location->makeAbsolute($this->getUrl()));
  856.     }
  857.  
  858.     /**
  859.      *    Sets the base url for the page.
  860.      *    @param SimpleTag $tag    Base URL for page.
  861.      *    @access protected
  862.      */
  863.     function _setBase(&$tag{
  864.         $url $tag->getAttribute('href');
  865.         $this->_base = new SimpleUrl($url);
  866.     }
  867.  
  868.     /**
  869.      *    Sets the title tag contents.
  870.      *    @param SimpleTitleTag $tag    Title of page.
  871.      *    @access protected
  872.      */
  873.     function _setTitle(&$tag{
  874.         $this->_title = &$tag;
  875.     }
  876.  
  877.     /**
  878.      *    Accessor for parsed title.
  879.      *    @return string     Title or false if no title is present.
  880.      *    @access public
  881.      */
  882.     function getTitle({
  883.         if ($this->_title{
  884.             return $this->_title->getText();
  885.         }
  886.         return false;
  887.     }
  888.  
  889.     /**
  890.      *    Finds a held form by button label. Will only
  891.      *    search correctly built forms.
  892.      *    @param SimpleSelector $selector       Button finder.
  893.      *    @return SimpleForm                    Form object containing
  894.      *                                           the button.
  895.      *    @access public
  896.      */
  897.     function &getFormBySubmit($selector{
  898.         for ($i 0$i count($this->_complete_forms)$i++{
  899.             if ($this->_complete_forms[$i]->hasSubmit($selector)) {
  900.                 return $this->_complete_forms[$i];
  901.             }
  902.         }
  903.         $null null;
  904.         return $null;
  905.     }
  906.  
  907.     /**
  908.      *    Finds a held form by image using a selector.
  909.      *    Will only search correctly built forms.
  910.      *    @param SimpleSelector $selector  Image finder.
  911.      *    @return SimpleForm               Form object containing
  912.      *                                      the image.
  913.      *    @access public
  914.      */
  915.     function &getFormByImage($selector{
  916.         for ($i 0$i count($this->_complete_forms)$i++{
  917.             if ($this->_complete_forms[$i]->hasImage($selector)) {
  918.                 return $this->_complete_forms[$i];
  919.             }
  920.         }
  921.         $null null;
  922.         return $null;
  923.     }
  924.  
  925.     /**
  926.      *    Finds a held form by the form ID. A way of
  927.      *    identifying a specific form when we have control
  928.      *    of the HTML code.
  929.      *    @param string $id     Form label.
  930.      *    @return SimpleForm    Form object containing the matching ID.
  931.      *    @access public
  932.      */
  933.     function &getFormById($id{
  934.         for ($i 0$i count($this->_complete_forms)$i++{
  935.             if ($this->_complete_forms[$i]->getId(== $id{
  936.                 return $this->_complete_forms[$i];
  937.             }
  938.         }
  939.         $null null;
  940.         return $null;
  941.     }
  942.  
  943.     /**
  944.      *    Sets a field on each form in which the field is
  945.      *    available.
  946.      *    @param SimpleSelector $selector    Field finder.
  947.      *    @param string $value               Value to set field to.
  948.      *    @return boolean                    True if value is valid.
  949.      *    @access public
  950.      */
  951.     function setField($selector$value$position=false{
  952.         $is_set false;
  953.         for ($i 0$i count($this->_complete_forms)$i++{
  954.             if ($this->_complete_forms[$i]->setField($selector$value$position)) {
  955.                 $is_set true;
  956.             }
  957.         }
  958.         return $is_set;
  959.     }
  960.  
  961.     /**
  962.      *    Accessor for a form element value within a page.
  963.      *    @param SimpleSelector $selector    Field finder.
  964.      *    @return string/boolean             A string if the field is
  965.      *                                        present, false if unchecked
  966.      *                                        and null if missing.
  967.      *    @access public
  968.      */
  969.     function getField($selector{
  970.         for ($i 0$i count($this->_complete_forms)$i++{
  971.             $value $this->_complete_forms[$i]->getValue($selector);
  972.             if (isset($value)) {
  973.                 return $value;
  974.             }
  975.         }
  976.         return null;
  977.     }
  978. }
  979. ?>

Documentation generated on Sun, 04 May 2008 09:21:53 -0500 by phpDocumentor 1.3.0