PageRenderTime 74ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/inc/simpletest/browser.php

https://github.com/chregu/fluxcms
PHP | 1025 lines | 420 code | 77 blank | 528 comment | 49 complexity | 8739d5034869ce2a767127018c2aca8d MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Base include file for SimpleTest
  4. * @package SimpleTest
  5. * @subpackage WebTester
  6. * @version $Id: browser.php,v 1.160 2005/09/09 01:27:37 lastcraft Exp $
  7. */
  8. /**#@+
  9. * include other SimpleTest class files
  10. */
  11. require_once(dirname(__FILE__) . '/simpletest.php');
  12. require_once(dirname(__FILE__) . '/http.php');
  13. require_once(dirname(__FILE__) . '/encoding.php');
  14. require_once(dirname(__FILE__) . '/page.php');
  15. require_once(dirname(__FILE__) . '/selector.php');
  16. require_once(dirname(__FILE__) . '/frames.php');
  17. require_once(dirname(__FILE__) . '/user_agent.php');
  18. /**#@-*/
  19. if (!defined('DEFAULT_MAX_NESTED_FRAMES')) {
  20. define('DEFAULT_MAX_NESTED_FRAMES', 3);
  21. }
  22. /**
  23. * Browser history list.
  24. * @package SimpleTest
  25. * @subpackage WebTester
  26. */
  27. class SimpleBrowserHistory {
  28. var $_sequence;
  29. var $_position;
  30. /**
  31. * Starts empty.
  32. * @access public
  33. */
  34. function SimpleBrowserHistory() {
  35. $this->_sequence = array();
  36. $this->_position = -1;
  37. }
  38. /**
  39. * Test for no entries yet.
  40. * @return boolean True if empty.
  41. * @access private
  42. */
  43. function _isEmpty() {
  44. return ($this->_position == -1);
  45. }
  46. /**
  47. * Test for being at the beginning.
  48. * @return boolean True if first.
  49. * @access private
  50. */
  51. function _atBeginning() {
  52. return ($this->_position == 0) && ! $this->_isEmpty();
  53. }
  54. /**
  55. * Test for being at the last entry.
  56. * @return boolean True if last.
  57. * @access private
  58. */
  59. function _atEnd() {
  60. return ($this->_position + 1 >= count($this->_sequence)) && ! $this->_isEmpty();
  61. }
  62. /**
  63. * Adds a successfully fetched page to the history.
  64. * @param SimpleUrl $url URL of fetch.
  65. * @param SimpleEncoding $parameters Any post data with the fetch.
  66. * @access public
  67. */
  68. function recordEntry($url, $parameters) {
  69. $this->_dropFuture();
  70. array_push(
  71. $this->_sequence,
  72. array('url' => $url, 'parameters' => $parameters));
  73. $this->_position++;
  74. }
  75. /**
  76. * Last fully qualified URL for current history
  77. * position.
  78. * @return SimpleUrl URL for this position.
  79. * @access public
  80. */
  81. function getUrl() {
  82. if ($this->_isEmpty()) {
  83. return false;
  84. }
  85. return $this->_sequence[$this->_position]['url'];
  86. }
  87. /**
  88. * Parameters of last fetch from current history
  89. * position.
  90. * @return SimpleFormEncoding Post parameters.
  91. * @access public
  92. */
  93. function getParameters() {
  94. if ($this->_isEmpty()) {
  95. return false;
  96. }
  97. return $this->_sequence[$this->_position]['parameters'];
  98. }
  99. /**
  100. * Step back one place in the history. Stops at
  101. * the first page.
  102. * @return boolean True if any previous entries.
  103. * @access public
  104. */
  105. function back() {
  106. if ($this->_isEmpty() || $this->_atBeginning()) {
  107. return false;
  108. }
  109. $this->_position--;
  110. return true;
  111. }
  112. /**
  113. * Step forward one place. If already at the
  114. * latest entry then nothing will happen.
  115. * @return boolean True if any future entries.
  116. * @access public
  117. */
  118. function forward() {
  119. if ($this->_isEmpty() || $this->_atEnd()) {
  120. return false;
  121. }
  122. $this->_position++;
  123. return true;
  124. }
  125. /**
  126. * Ditches all future entries beyond the current
  127. * point.
  128. * @access private
  129. */
  130. function _dropFuture() {
  131. if ($this->_isEmpty()) {
  132. return;
  133. }
  134. while (! $this->_atEnd()) {
  135. array_pop($this->_sequence);
  136. }
  137. }
  138. }
  139. /**
  140. * Simulated web browser. This is an aggregate of
  141. * the user agent, the HTML parsing, request history
  142. * and the last header set.
  143. * @package SimpleTest
  144. * @subpackage WebTester
  145. */
  146. class SimpleBrowser {
  147. var $_user_agent;
  148. var $_page;
  149. var $_history;
  150. var $_ignore_frames;
  151. var $_maximum_nested_frames;
  152. /**
  153. * Starts with a fresh browser with no
  154. * cookie or any other state information. The
  155. * exception is that a default proxy will be
  156. * set up if specified in the options.
  157. * @access public
  158. */
  159. function SimpleBrowser() {
  160. $this->_user_agent = &$this->_createUserAgent();
  161. $this->_user_agent->useProxy(
  162. SimpleTest::getDefaultProxy(),
  163. SimpleTest::getDefaultProxyUsername(),
  164. SimpleTest::getDefaultProxyPassword());
  165. $this->_page = &new SimplePage();
  166. $this->_history = &$this->_createHistory();
  167. $this->_ignore_frames = false;
  168. $this->_maximum_nested_frames = DEFAULT_MAX_NESTED_FRAMES;
  169. }
  170. /**
  171. * Creates the underlying user agent.
  172. * @return SimpleFetcher Content fetcher.
  173. * @access protected
  174. */
  175. function &_createUserAgent() {
  176. $user_agent = &new SimpleUserAgent();
  177. return $user_agent;
  178. }
  179. /**
  180. * Creates a new empty history list.
  181. * @return SimpleBrowserHistory New list.
  182. * @access protected
  183. */
  184. function &_createHistory() {
  185. $history = &new SimpleBrowserHistory();
  186. return $history;
  187. }
  188. /**
  189. * Disables frames support. Frames will not be fetched
  190. * and the frameset page will be used instead.
  191. * @access public
  192. */
  193. function ignoreFrames() {
  194. $this->_ignore_frames = true;
  195. }
  196. /**
  197. * Enables frames support. Frames will be fetched from
  198. * now on.
  199. * @access public
  200. */
  201. function useFrames() {
  202. $this->_ignore_frames = false;
  203. }
  204. /**
  205. * Parses the raw content into a page. Will load further
  206. * frame pages unless frames are disabled.
  207. * @param SimpleHttpResponse $response Response from fetch.
  208. * @param integer $depth Nested frameset depth.
  209. * @return SimplePage Parsed HTML.
  210. * @access protected
  211. */
  212. function &_parse($response, $depth = 0) {
  213. $builder = &new SimplePageBuilder();
  214. $page = &$builder->parse($response);
  215. if ($this->_ignore_frames || ! $page->hasFrames() || ($depth > $this->_maximum_nested_frames)) {
  216. return $page;
  217. }
  218. $frameset = &new SimpleFrameset($page);
  219. foreach ($page->getFrameset() as $key => $url) {
  220. $frame = &$this->_fetch($url, new SimpleGetEncoding(), $depth + 1);
  221. $frameset->addFrame($frame, $key);
  222. }
  223. return $frameset;
  224. }
  225. /**
  226. * Fetches a page.
  227. * @param string/SimpleUrl $url Target to fetch.
  228. * @param SimpleEncoding $encoding GET/POST parameters.
  229. * @param integer $depth Nested frameset depth protection.
  230. * @return SimplePage Parsed page.
  231. * @access private
  232. */
  233. function &_fetch($url, $encoding, $depth = 0) {
  234. $response = &$this->_user_agent->fetchResponse($url, $encoding);
  235. if ($response->isError()) {
  236. $page = &new SimplePage($response);
  237. } else {
  238. $page = &$this->_parse($response, $depth);
  239. }
  240. return $page;
  241. }
  242. /**
  243. * Fetches a page or a single frame if that is the current
  244. * focus.
  245. * @param SimpleUrl $url Target to fetch.
  246. * @param SimpleEncoding $parameters GET/POST parameters.
  247. * @return string Raw content of page.
  248. * @access private
  249. */
  250. function _load($url, $parameters) {
  251. $frame = $url->getTarget();
  252. if (! $frame || ! $this->_page->hasFrames() || (strtolower($frame) == '_top')) {
  253. return $this->_loadPage($url, $parameters);
  254. }
  255. return $this->_loadFrame(array($frame), $url, $parameters);
  256. }
  257. /**
  258. * Fetches a page and makes it the current page/frame.
  259. * @param string/SimpleUrl $url Target to fetch as string.
  260. * @param SimplePostEncoding $parameters POST parameters.
  261. * @return string Raw content of page.
  262. * @access private
  263. */
  264. function _loadPage($url, $parameters) {
  265. $this->_page = &$this->_fetch($url, $parameters);
  266. $this->_history->recordEntry(
  267. $this->_page->getUrl(),
  268. $this->_page->getRequestData());
  269. return $this->_page->getRaw();
  270. }
  271. /**
  272. * Fetches a frame into the existing frameset replacing the
  273. * original.
  274. * @param array $frames List of names to drill down.
  275. * @param string/SimpleUrl $url Target to fetch as string.
  276. * @param SimpleFormEncoding $parameters POST parameters.
  277. * @return string Raw content of page.
  278. * @access private
  279. */
  280. function _loadFrame($frames, $url, $parameters) {
  281. $page = &$this->_fetch($url, $parameters);
  282. $this->_page->setFrame($frames, $page);
  283. }
  284. /**
  285. * Removes expired and temporary cookies as if
  286. * the browser was closed and re-opened.
  287. * @param string/integer $date Time when session restarted.
  288. * If omitted then all persistent
  289. * cookies are kept.
  290. * @access public
  291. */
  292. function restart($date = false) {
  293. $this->_user_agent->restart($date);
  294. }
  295. /**
  296. * Adds a header to every fetch.
  297. * @param string $header Header line to add to every
  298. * request until cleared.
  299. * @access public
  300. */
  301. function addHeader($header) {
  302. $this->_user_agent->addHeader($header);
  303. }
  304. /**
  305. * Ages the cookies by the specified time.
  306. * @param integer $interval Amount in seconds.
  307. * @access public
  308. */
  309. function ageCookies($interval) {
  310. $this->_user_agent->ageCookies($interval);
  311. }
  312. /**
  313. * Sets an additional cookie. If a cookie has
  314. * the same name and path it is replaced.
  315. * @param string $name Cookie key.
  316. * @param string $value Value of cookie.
  317. * @param string $host Host upon which the cookie is valid.
  318. * @param string $path Cookie path if not host wide.
  319. * @param string $expiry Expiry date.
  320. * @access public
  321. */
  322. function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
  323. $this->_user_agent->setCookie($name, $value, $host, $path, $expiry);
  324. }
  325. /**
  326. * Reads the most specific cookie value from the
  327. * browser cookies.
  328. * @param string $host Host to search.
  329. * @param string $path Applicable path.
  330. * @param string $name Name of cookie to read.
  331. * @return string False if not present, else the
  332. * value as a string.
  333. * @access public
  334. */
  335. function getCookieValue($host, $path, $name) {
  336. return $this->_user_agent->getCookieValue($host, $path, $name);
  337. }
  338. /**
  339. * Reads the current cookies for the current URL.
  340. * @param string $name Key of cookie to find.
  341. * @return string Null if there is no current URL, false
  342. * if the cookie is not set.
  343. * @access public
  344. */
  345. function getCurrentCookieValue($name) {
  346. return $this->_user_agent->getBaseCookieValue($name, $this->_page->getUrl());
  347. }
  348. /**
  349. * Sets the maximum number of redirects before
  350. * a page will be loaded anyway.
  351. * @param integer $max Most hops allowed.
  352. * @access public
  353. */
  354. function setMaximumRedirects($max) {
  355. $this->_user_agent->setMaximumRedirects($max);
  356. }
  357. /**
  358. * Sets the maximum number of nesting of framed pages
  359. * within a framed page to prevent loops.
  360. * @param integer $max Highest depth allowed.
  361. * @access public
  362. */
  363. function setMaximumNestedFrames($max) {
  364. $this->_maximum_nested_frames = $max;
  365. }
  366. /**
  367. * Sets the socket timeout for opening a connection.
  368. * @param integer $timeout Maximum time in seconds.
  369. * @access public
  370. */
  371. function setConnectionTimeout($timeout) {
  372. $this->_user_agent->setConnectionTimeout($timeout);
  373. }
  374. /**
  375. * Sets proxy to use on all requests for when
  376. * testing from behind a firewall. Set URL
  377. * to false to disable.
  378. * @param string $proxy Proxy URL.
  379. * @param string $username Proxy username for authentication.
  380. * @param string $password Proxy password for authentication.
  381. * @access public
  382. */
  383. function useProxy($proxy, $username = false, $password = false) {
  384. $this->_user_agent->useProxy($proxy, $username, $password);
  385. }
  386. /**
  387. * Fetches the page content with a HEAD request.
  388. * Will affect cookies, but will not change the base URL.
  389. * @param string/SimpleUrl $url Target to fetch as string.
  390. * @param hash/SimpleHeadEncoding $parameters Additional parameters for
  391. * HEAD request.
  392. * @return boolean True if successful.
  393. * @access public
  394. */
  395. function head($url, $parameters = false) {
  396. if (! is_object($url)) {
  397. $url = new SimpleUrl($url);
  398. }
  399. if ($this->getUrl()) {
  400. $url = $url->makeAbsolute($this->getUrl());
  401. }
  402. $response = &$this->_user_agent->fetchResponse($url, new SimpleHeadEncoding($parameters));
  403. return ! $response->isError();
  404. }
  405. /**
  406. * Fetches the page content with a simple GET request.
  407. * @param string/SimpleUrl $url Target to fetch.
  408. * @param hash/SimpleFormEncoding $parameters Additional parameters for
  409. * GET request.
  410. * @return string Content of page or false.
  411. * @access public
  412. */
  413. function get($url, $parameters = false) {
  414. if (! is_object($url)) {
  415. $url = new SimpleUrl($url);
  416. }
  417. if ($this->getUrl()) {
  418. $url = $url->makeAbsolute($this->getUrl());
  419. }
  420. return $this->_load($url, new SimpleGetEncoding($parameters));
  421. }
  422. /**
  423. * Fetches the page content with a POST request.
  424. * @param string/SimpleUrl $url Target to fetch as string.
  425. * @param hash/SimpleFormEncoding $parameters POST parameters.
  426. * @return string Content of page.
  427. * @access public
  428. */
  429. function post($url, $parameters = false) {
  430. if (! is_object($url)) {
  431. $url = new SimpleUrl($url);
  432. }
  433. if ($this->getUrl()) {
  434. $url = $url->makeAbsolute($this->getUrl());
  435. }
  436. return $this->_load($url, new SimplePostEncoding($parameters));
  437. }
  438. /**
  439. * Equivalent to hitting the retry button on the
  440. * browser. Will attempt to repeat the page fetch. If
  441. * there is no history to repeat it will give false.
  442. * @return string/boolean Content if fetch succeeded
  443. * else false.
  444. * @access public
  445. */
  446. function retry() {
  447. $frames = $this->_page->getFrameFocus();
  448. if (count($frames) > 0) {
  449. $this->_loadFrame(
  450. $frames,
  451. $this->_page->getUrl(),
  452. $this->_page->getRequestData());
  453. return $this->_page->getRaw();
  454. }
  455. if ($url = $this->_history->getUrl()) {
  456. $this->_page = &$this->_fetch($url, $this->_history->getParameters());
  457. return $this->_page->getRaw();
  458. }
  459. return false;
  460. }
  461. /**
  462. * Equivalent to hitting the back button on the
  463. * browser. The browser history is unchanged on
  464. * failure. The page content is refetched as there
  465. * is no concept of content caching in SimpleTest.
  466. * @return boolean True if history entry and
  467. * fetch succeeded
  468. * @access public
  469. */
  470. function back() {
  471. if (! $this->_history->back()) {
  472. return false;
  473. }
  474. $content = $this->retry();
  475. if (! $content) {
  476. $this->_history->forward();
  477. }
  478. return $content;
  479. }
  480. /**
  481. * Equivalent to hitting the forward button on the
  482. * browser. The browser history is unchanged on
  483. * failure. The page content is refetched as there
  484. * is no concept of content caching in SimpleTest.
  485. * @return boolean True if history entry and
  486. * fetch succeeded
  487. * @access public
  488. */
  489. function forward() {
  490. if (! $this->_history->forward()) {
  491. return false;
  492. }
  493. $content = $this->retry();
  494. if (! $content) {
  495. $this->_history->back();
  496. }
  497. return $content;
  498. }
  499. /**
  500. * Retries a request after setting the authentication
  501. * for the current realm.
  502. * @param string $username Username for realm.
  503. * @param string $password Password for realm.
  504. * @return boolean True if successful fetch. Note
  505. * that authentication may still have
  506. * failed.
  507. * @access public
  508. */
  509. function authenticate($username, $password) {
  510. if (! $this->_page->getRealm()) {
  511. return false;
  512. }
  513. $url = $this->_page->getUrl();
  514. if (! $url) {
  515. return false;
  516. }
  517. $this->_user_agent->setIdentity(
  518. $url->getHost(),
  519. $this->_page->getRealm(),
  520. $username,
  521. $password);
  522. return $this->retry();
  523. }
  524. /**
  525. * Accessor for a breakdown of the frameset.
  526. * @return array Hash tree of frames by name
  527. * or index if no name.
  528. * @access public
  529. */
  530. function getFrames() {
  531. return $this->_page->getFrames();
  532. }
  533. /**
  534. * Accessor for current frame focus. Will be
  535. * false if no frame has focus.
  536. * @return integer/string/boolean Label if any, otherwise
  537. * the position in the frameset
  538. * or false if none.
  539. * @access public
  540. */
  541. function getFrameFocus() {
  542. return $this->_page->getFrameFocus();
  543. }
  544. /**
  545. * Sets the focus by index. The integer index starts from 1.
  546. * @param integer $choice Chosen frame.
  547. * @return boolean True if frame exists.
  548. * @access public
  549. */
  550. function setFrameFocusByIndex($choice) {
  551. return $this->_page->setFrameFocusByIndex($choice);
  552. }
  553. /**
  554. * Sets the focus by name.
  555. * @param string $name Chosen frame.
  556. * @return boolean True if frame exists.
  557. * @access public
  558. */
  559. function setFrameFocus($name) {
  560. return $this->_page->setFrameFocus($name);
  561. }
  562. /**
  563. * Clears the frame focus. All frames will be searched
  564. * for content.
  565. * @access public
  566. */
  567. function clearFrameFocus() {
  568. return $this->_page->clearFrameFocus();
  569. }
  570. /**
  571. * Accessor for last error.
  572. * @return string Error from last response.
  573. * @access public
  574. */
  575. function getTransportError() {
  576. return $this->_page->getTransportError();
  577. }
  578. /**
  579. * Accessor for current MIME type.
  580. * @return string MIME type as string; e.g. 'text/html'
  581. * @access public
  582. */
  583. function getMimeType() {
  584. return $this->_page->getMimeType();
  585. }
  586. /**
  587. * Accessor for last response code.
  588. * @return integer Last HTTP response code received.
  589. * @access public
  590. */
  591. function getResponseCode() {
  592. return $this->_page->getResponseCode();
  593. }
  594. /**
  595. * Accessor for last Authentication type. Only valid
  596. * straight after a challenge (401).
  597. * @return string Description of challenge type.
  598. * @access public
  599. */
  600. function getAuthentication() {
  601. return $this->_page->getAuthentication();
  602. }
  603. /**
  604. * Accessor for last Authentication realm. Only valid
  605. * straight after a challenge (401).
  606. * @return string Name of security realm.
  607. * @access public
  608. */
  609. function getRealm() {
  610. return $this->_page->getRealm();
  611. }
  612. /**
  613. * Accessor for current URL of page or frame if
  614. * focused.
  615. * @return string Location of current page or frame as
  616. * a string.
  617. */
  618. function getUrl() {
  619. $url = $this->_page->getUrl();
  620. return $url ? $url->asString() : false;
  621. }
  622. /**
  623. * Accessor for raw bytes sent down the wire.
  624. * @return string Original text sent.
  625. * @access public
  626. */
  627. function getRequest() {
  628. return $this->_page->getRequest();
  629. }
  630. /**
  631. * Accessor for raw header information.
  632. * @return string Header block.
  633. * @access public
  634. */
  635. function getHeaders() {
  636. return $this->_page->getHeaders();
  637. }
  638. /**
  639. * Accessor for raw page information.
  640. * @return string Original text content of web page.
  641. * @access public
  642. */
  643. function getContent() {
  644. return $this->_page->getRaw();
  645. }
  646. /**
  647. * Accessor for plain text version of the page.
  648. * @return string Normalised text representation.
  649. * @access public
  650. */
  651. function getContentAsText() {
  652. return $this->_page->getText();
  653. }
  654. /**
  655. * Accessor for parsed title.
  656. * @return string Title or false if no title is present.
  657. * @access public
  658. */
  659. function getTitle() {
  660. return $this->_page->getTitle();
  661. }
  662. /**
  663. * Accessor for a list of all fixed links in current page.
  664. * @return array List of urls with scheme of
  665. * http or https and hostname.
  666. * @access public
  667. */
  668. function getAbsoluteUrls() {
  669. return $this->_page->getAbsoluteUrls();
  670. }
  671. /**
  672. * Accessor for a list of all relative links.
  673. * @return array List of urls without hostname.
  674. * @access public
  675. */
  676. function getRelativeUrls() {
  677. return $this->_page->getRelativeUrls();
  678. }
  679. /**
  680. * Sets all form fields with that name.
  681. * @param string $label Name or label of field in forms.
  682. * @param string $value New value of field.
  683. * @return boolean True if field exists, otherwise false.
  684. * @access public
  685. */
  686. function setField($label, $value) {
  687. return $this->_page->setField(new SimpleByLabelOrName($label), $value);
  688. }
  689. /**
  690. * Sets all form fields with that name. Will use label if
  691. * one is available (not yet implemented).
  692. * @param string $name Name of field in forms.
  693. * @param string $value New value of field.
  694. * @return boolean True if field exists, otherwise false.
  695. * @access public
  696. */
  697. function setFieldByName($name, $value) {
  698. return $this->_page->setField(new SimpleByName($name), $value);
  699. }
  700. /**
  701. * Sets all form fields with that id attribute.
  702. * @param string/integer $id Id of field in forms.
  703. * @param string $value New value of field.
  704. * @return boolean True if field exists, otherwise false.
  705. * @access public
  706. */
  707. function setFieldById($id, $value) {
  708. return $this->_page->setField(new SimpleById($id), $value);
  709. }
  710. /**
  711. * Accessor for a form element value within the page.
  712. * Finds the first match.
  713. * @param string $label Field label.
  714. * @return string/boolean A value if the field is
  715. * present, false if unchecked
  716. * and null if missing.
  717. * @access public
  718. */
  719. function getField($label) {
  720. return $this->_page->getField(new SimpleByLabelOrName($label));
  721. }
  722. /**
  723. * Accessor for a form element value within the page.
  724. * Finds the first match.
  725. * @param string $name Field name.
  726. * @return string/boolean A string if the field is
  727. * present, false if unchecked
  728. * and null if missing.
  729. * @access public
  730. */
  731. function getFieldByName($name) {
  732. return $this->_page->getField(new SimpleByName($name));
  733. }
  734. /**
  735. * Accessor for a form element value within the page.
  736. * @param string/integer $id Id of field in forms.
  737. * @return string/boolean A string if the field is
  738. * present, false if unchecked
  739. * and null if missing.
  740. * @access public
  741. */
  742. function getFieldById($id) {
  743. return $this->_page->getField(new SimpleById($id));
  744. }
  745. /**
  746. * Clicks the submit button by label. The owning
  747. * form will be submitted by this.
  748. * @param string $label Button label. An unlabeled
  749. * button can be triggered by 'Submit'.
  750. * @param hash $additional Additional form data.
  751. * @return string/boolean Page on success.
  752. * @access public
  753. */
  754. function clickSubmit($label = 'Submit', $additional = false) {
  755. if (! ($form = &$this->_page->getFormBySubmit(new SimpleByLabel($label)))) {
  756. return false;
  757. }
  758. $success = $this->_load(
  759. $form->getAction(),
  760. $form->submitButton(new SimpleByLabel($label), $additional));
  761. return ($success ? $this->getContent() : $success);
  762. }
  763. /**
  764. * Clicks the submit button by name attribute. The owning
  765. * form will be submitted by this.
  766. * @param string $name Button name.
  767. * @param hash $additional Additional form data.
  768. * @return string/boolean Page on success.
  769. * @access public
  770. */
  771. function clickSubmitByName($name, $additional = false) {
  772. if (! ($form = &$this->_page->getFormBySubmit(new SimpleByName($name)))) {
  773. return false;
  774. }
  775. $success = $this->_load(
  776. $form->getAction(),
  777. $form->submitButton(new SimpleByName($name), $additional));
  778. return ($success ? $this->getContent() : $success);
  779. }
  780. /**
  781. * Clicks the submit button by ID attribute of the button
  782. * itself. The owning form will be submitted by this.
  783. * @param string $id Button ID.
  784. * @param hash $additional Additional form data.
  785. * @return string/boolean Page on success.
  786. * @access public
  787. */
  788. function clickSubmitById($id, $additional = false) {
  789. if (! ($form = &$this->_page->getFormBySubmit(new SimpleById($id)))) {
  790. return false;
  791. }
  792. $success = $this->_load(
  793. $form->getAction(),
  794. $form->submitButton(new SimpleById($id), $additional));
  795. return ($success ? $this->getContent() : $success);
  796. }
  797. /**
  798. * Clicks the submit image by some kind of label. Usually
  799. * the alt tag or the nearest equivalent. The owning
  800. * form will be submitted by this. Clicking outside of
  801. * the boundary of the coordinates will result in
  802. * a failure.
  803. * @param string $label ID attribute of button.
  804. * @param integer $x X-coordinate of imaginary click.
  805. * @param integer $y Y-coordinate of imaginary click.
  806. * @param hash $additional Additional form data.
  807. * @return string/boolean Page on success.
  808. * @access public
  809. */
  810. function clickImage($label, $x = 1, $y = 1, $additional = false) {
  811. if (! ($form = &$this->_page->getFormByImage(new SimpleByLabel($label)))) {
  812. return false;
  813. }
  814. $success = $this->_load(
  815. $form->getAction(),
  816. $form->submitImage(new SimpleByLabel($label), $x, $y, $additional));
  817. return ($success ? $this->getContent() : $success);
  818. }
  819. /**
  820. * Clicks the submit image by the name. Usually
  821. * the alt tag or the nearest equivalent. The owning
  822. * form will be submitted by this. Clicking outside of
  823. * the boundary of the coordinates will result in
  824. * a failure.
  825. * @param string $name Name attribute of button.
  826. * @param integer $x X-coordinate of imaginary click.
  827. * @param integer $y Y-coordinate of imaginary click.
  828. * @param hash $additional Additional form data.
  829. * @return string/boolean Page on success.
  830. * @access public
  831. */
  832. function clickImageByName($name, $x = 1, $y = 1, $additional = false) {
  833. if (! ($form = &$this->_page->getFormByImage(new SimpleByName($name)))) {
  834. return false;
  835. }
  836. $success = $this->_load(
  837. $form->getAction(),
  838. $form->submitImage(new SimpleByName($name), $x, $y, $additional));
  839. return ($success ? $this->getContent() : $success);
  840. }
  841. /**
  842. * Clicks the submit image by ID attribute. The owning
  843. * form will be submitted by this. Clicking outside of
  844. * the boundary of the coordinates will result in
  845. * a failure.
  846. * @param integer/string $id ID attribute of button.
  847. * @param integer $x X-coordinate of imaginary click.
  848. * @param integer $y Y-coordinate of imaginary click.
  849. * @param hash $additional Additional form data.
  850. * @return string/boolean Page on success.
  851. * @access public
  852. */
  853. function clickImageById($id, $x = 1, $y = 1, $additional = false) {
  854. if (! ($form = &$this->_page->getFormByImage(new SimpleById($id)))) {
  855. return false;
  856. }
  857. $success = $this->_load(
  858. $form->getAction(),
  859. $form->submitImage(new SimpleById($id), $x, $y, $additional));
  860. return ($success ? $this->getContent() : $success);
  861. }
  862. /**
  863. * Submits a form by the ID.
  864. * @param string $id The form ID. No submit button value
  865. * will be sent.
  866. * @return string/boolean Page on success.
  867. * @access public
  868. */
  869. function submitFormById($id) {
  870. if (! ($form = &$this->_page->getFormById($id))) {
  871. return false;
  872. }
  873. $success = $this->_load(
  874. $form->getAction(),
  875. $form->submit());
  876. return ($success ? $this->getContent() : $success);
  877. }
  878. /**
  879. * Follows a link by label. Will click the first link
  880. * found with this link text by default, or a later
  881. * one if an index is given. The match ignores case and
  882. * white space issues.
  883. * @param string $label Text between the anchor tags.
  884. * @param integer $index Link position counting from zero.
  885. * @return string/boolean Page on success.
  886. * @access public
  887. */
  888. function clickLink($label, $index = 0) {
  889. $urls = $this->_page->getUrlsByLabel($label);
  890. if (count($urls) == 0) {
  891. return false;
  892. }
  893. if (count($urls) < $index + 1) {
  894. return false;
  895. }
  896. $this->_load($urls[$index], new SimpleGetEncoding());
  897. return $this->getContent();
  898. }
  899. /**
  900. * Tests to see if a link is present by label.
  901. * @param string $label Text of value attribute.
  902. * @return boolean True if link present.
  903. * @access public
  904. */
  905. function isLink($label) {
  906. return (count($this->_page->getUrlsByLabel($label)) > 0);
  907. }
  908. /**
  909. * Follows a link by id attribute.
  910. * @param string $id ID attribute value.
  911. * @return string/boolean Page on success.
  912. * @access public
  913. */
  914. function clickLinkById($id) {
  915. if (! ($url = $this->_page->getUrlById($id))) {
  916. return false;
  917. }
  918. $this->_load($url, new SimpleGetEncoding());
  919. return $this->getContent();
  920. }
  921. /**
  922. * Tests to see if a link is present by ID attribute.
  923. * @param string $id Text of id attribute.
  924. * @return boolean True if link present.
  925. * @access public
  926. */
  927. function isLinkById($id) {
  928. return (boolean)$this->_page->getUrlById($id);
  929. }
  930. /**
  931. * Clicks a visible text item. Will first try buttons,
  932. * then links and then images.
  933. * @param string $label Visible text or alt text.
  934. * @return string/boolean Raw page or false.
  935. * @access public
  936. */
  937. function click($label) {
  938. $raw = $this->clickSubmit($label);
  939. if (! $raw) {
  940. $raw = $this->clickLink($label);
  941. }
  942. if (! $raw) {
  943. $raw = $this->clickImage($label);
  944. }
  945. return $raw;
  946. }
  947. }
  948. ?>