1<?php 2/** 3 * Simulates a full DokuWiki HTTP Request and allows 4 * runtime inspection. 5 */ 6 7// output buffering 8$output_buffer = ''; 9 10function ob_start_callback($buffer) { 11 global $output_buffer; 12 $output_buffer .= $buffer; 13} 14 15 16/** 17 * Helper class to execute a fake request 18 */ 19class TestRequest { 20 21 private $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php'); 22 private $script; 23 24 private $server = array(); 25 private $session = array(); 26 private $get = array(); 27 private $post = array(); 28 29 public function getServer($key) { return $this->server[$key]; } 30 public function getSession($key) { return $this->session[$key]; } 31 public function getGet($key) { return $this->get[$key]; } 32 public function getPost($key) { return $this->post[$key]; } 33 public function getScript() { return $this->script; } 34 35 public function setServer($key, $value) { $this->server[$key] = $value; } 36 public function setSession($key, $value) { $this->session[$key] = $value; } 37 public function setGet($key, $value) { $this->get[$key] = $value; } 38 public function setPost($key, $value) { $this->post[$key] = $value; } 39 40 /** 41 * Executes the request 42 * 43 * @param string $url end URL to simulate, needs to start with /doku.php currently 44 * @return TestResponse the resulting output of the request 45 */ 46 public function execute($uri='/doku.php') { 47 global $INPUT; 48 global $ID; 49 global $INFO; 50 51 // save old environment 52 $server = $_SERVER; 53 $session = $_SESSION; 54 $get = $_GET; 55 $post = $_POST; 56 $request = $_REQUEST; 57 $input = $INPUT; 58 59 // prepare the right URI 60 $this->setUri($uri); 61 62 // import all defined globals into the function scope 63 foreach(array_keys($GLOBALS) as $glb){ 64 global $$glb; 65 } 66 67 // fake environment 68 global $default_server_vars; 69 $_SERVER = array_merge($default_server_vars, $this->server); 70 $_SESSION = $this->session; 71 $_GET = $this->get; 72 $_POST = $this->post; 73 $_REQUEST = array_merge($_GET, $_POST); 74 75 // reset output buffer 76 global $output_buffer; 77 $output_buffer = ''; 78 79 // now execute dokuwiki and grep the output 80 header_remove(); 81 ob_start('ob_start_callback'); 82 $INPUT = new Input(); 83 include(DOKU_INC.$this->script); 84 ob_end_flush(); 85 86 // create the response object 87 $response = new TestResponse( 88 $output_buffer, 89 (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()) // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli 90 ); 91 92 // reset environment 93 $_SERVER = $server; 94 $_SESSION = $session; 95 $_GET = $get; 96 $_POST = $post; 97 $_REQUEST = $request; 98 $INPUT = $input; 99 100 return $response; 101 } 102 103 /** 104 * Set the virtual URI the request works against 105 * 106 * This parses the given URI and sets any contained GET variables 107 * but will not overwrite any previously set ones (eg. set via setGet()). 108 * 109 * It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'] 110 * with all set GET variables. 111 * 112 * @param string $url end URL to simulate, needs to start with /doku.php currently 113 * @todo make this work with other end points 114 */ 115 protected function setUri($uri){ 116 if(!preg_match('#^('.join('|',$this->valid_scripts).')#',$uri)){ 117 throw new Exception("$uri \n--- only ".join(', ',$this->valid_scripts)." are supported currently"); 118 } 119 120 $params = array(); 121 list($uri, $query) = explode('?',$uri,2); 122 if($query) parse_str($query, $params); 123 124 $this->script = substr($uri,1); 125 $this->get = array_merge($params, $this->get); 126 if(count($this->get)){ 127 $query = '?'.http_build_query($this->get, '', '&'); 128 $query = str_replace( 129 array('%3A', '%5B', '%5D'), 130 array(':', '[', ']'), 131 $query 132 ); 133 $uri = $uri.$query; 134 } 135 136 $this->setServer('QUERY_STRING', $query); 137 $this->setServer('REQUEST_URI', $uri); 138 } 139 140 /** 141 * Simulate a POST request with the given variables 142 * 143 * @param array $post all the POST parameters to use 144 * @param string $url end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently 145 * @param return TestResponse 146 */ 147 public function post($post=array(), $uri='/doku.php') { 148 $this->post = array_merge($this->post, $post); 149 $this->setServer('REQUEST_METHOD', 'POST'); 150 return $this->execute($uri); 151 } 152 153 /** 154 * Simulate a GET request with the given variables 155 * 156 * @param array $GET all the GET parameters to use 157 * @param string $url end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently 158 * @param return TestResponse 159 */ 160 public function get($get=array(), $uri='/doku.php') { 161 $this->get = array_merge($this->get, $get); 162 $this->setServer('REQUEST_METHOD', 'GET'); 163 return $this->execute($uri); 164 } 165 166 167} 168