1<?php 2/** 3 * Simulates a full DokuWiki HTTP Request and allows 4 * runtime inspection. 5 */ 6 7// output buffering 8$output_buffer = ''; 9 10$currentTestRequest = null; 11 12function ob_start_callback($buffer) { 13 global $output_buffer; 14 $output_buffer .= $buffer; 15} 16 17/** 18 * Helper class to execute a fake request 19 */ 20class TestRequest { 21 22 protected $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php', '/lib/exe/ajax.php'); 23 protected $script; 24 25 protected $server = array(); 26 protected $session = array(); 27 protected $get = array(); 28 protected $post = array(); 29 protected $notifications = array(); 30 31 /** 32 * Get a $_SERVER var 33 * 34 * @param string $key 35 * @return mixed 36 */ 37 public function getServer($key) { 38 return $this->server[$key]; 39 } 40 41 /** 42 * Get a $_SESSION var 43 * 44 * @param string $key 45 * @return mixed 46 */ 47 public function getSession($key) { 48 return $this->session[$key]; 49 } 50 51 /** 52 * Get a $_GET var 53 * 54 * @param string $key 55 * @return mixed 56 */ 57 public function getGet($key) { 58 return $this->get[$key]; 59 } 60 61 /** 62 * Get a $_POST var 63 * 64 * @param string $key 65 * @return mixed 66 */ 67 public function getPost($key) { 68 return $this->post[$key]; 69 } 70 71 /** 72 * Get the script that will execute the request 73 * 74 * @return string 75 */ 76 public function getScript() { 77 return $this->script; 78 } 79 80 /** 81 * Set a $_SERVER var 82 * 83 * @param string $key 84 * @param mixed $value 85 */ 86 public function setServer($key, $value) { 87 $this->server[$key] = $value; 88 } 89 90 /** 91 * Set a $_SESSION var 92 * 93 * @param string $key 94 * @param mixed $value 95 */ 96 public function setSession($key, $value) { 97 $this->session[$key] = $value; 98 } 99 100 /** 101 * Set a $_GET var 102 * 103 * @param string $key 104 * @param mixed $value 105 */ 106 public function setGet($key, $value) { 107 $this->get[$key] = $value; 108 } 109 110 /** 111 * Set a $_POST var 112 * 113 * @param string $key 114 * @param mixed $value 115 */ 116 public function setPost($key, $value) { 117 $this->post[$key] = $value; 118 } 119 120 /** 121 * Executes the request 122 * 123 * @param string $uri end URL to simulate, needs to be one of the testable scripts 124 * @return TestResponse the resulting output of the request 125 */ 126 public function execute($uri = '/doku.php') { 127 global $INPUT; 128 global $currentTestRequest; 129 130 $currentTestRequest = $this; 131 132 // save old environment 133 $server = $_SERVER; 134 $session = $_SESSION; 135 $get = $_GET; 136 $post = $_POST; 137 $request = $_REQUEST; 138 $input = $INPUT; 139 140 // prepare the right URI 141 $this->setUri($uri); 142 143 // import all defined globals into the function scope 144 foreach(array_keys($GLOBALS) as $glb) { 145 global $$glb; 146 } 147 148 // fake environment 149 global $default_server_vars; 150 $_SERVER = array_merge($default_server_vars, $this->server); 151 $_SESSION = $this->session; 152 $_GET = $this->get; 153 $_POST = $this->post; 154 $_REQUEST = array_merge($_GET, $_POST); 155 156 // reset output buffer 157 global $output_buffer; 158 $output_buffer = ''; 159 160 // now execute dokuwiki and grep the output 161 header_remove(); 162 ob_start('ob_start_callback'); 163 $INPUT = new Input(); 164 include(DOKU_INC . $this->script); 165 ob_end_flush(); 166 167 // create the response object 168 $response = new TestResponse( 169 $output_buffer, 170 (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()) // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli 171 ); 172 if($this->notifications != null) { 173 $response->setNotifications($this->notifications); 174 } 175 176 // reset environment 177 $_SERVER = $server; 178 $_SESSION = $session; 179 $_GET = $get; 180 $_POST = $post; 181 $_REQUEST = $request; 182 $INPUT = $input; 183 184 $currentTestRequest = null; 185 186 return $response; 187 } 188 189 /** 190 * Set the virtual URI the request works against 191 * 192 * This parses the given URI and sets any contained GET variables 193 * but will not overwrite any previously set ones (eg. set via setGet()). 194 * 195 * It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'] 196 * with all set GET variables. 197 * 198 * @param string $uri end URL to simulate 199 * @throws Exception when an invalid script is passed 200 */ 201 protected function setUri($uri) { 202 if(!preg_match('#^(' . join('|', $this->valid_scripts) . ')#', $uri)) { 203 throw new Exception("$uri \n--- only " . join(', ', $this->valid_scripts) . " are supported currently"); 204 } 205 206 $params = array(); 207 list($uri, $query) = explode('?', $uri, 2); 208 if($query) parse_str($query, $params); 209 210 $this->script = substr($uri, 1); 211 $this->get = array_merge($params, $this->get); 212 if(count($this->get)) { 213 $query = '?' . http_build_query($this->get, '', '&'); 214 $query = str_replace( 215 array('%3A', '%5B', '%5D'), 216 array(':', '[', ']'), 217 $query 218 ); 219 $uri = $uri . $query; 220 } 221 222 $this->setServer('QUERY_STRING', $query); 223 $this->setServer('REQUEST_URI', $uri); 224 } 225 226 /** 227 * Simulate a POST request with the given variables 228 * 229 * @param array $post all the POST parameters to use 230 * @param string $uri end URL to simulate 231 * @return TestResponse 232 */ 233 public function post($post = array(), $uri = '/doku.php') { 234 $this->post = array_merge($this->post, $post); 235 $this->setServer('REQUEST_METHOD', 'POST'); 236 return $this->execute($uri); 237 } 238 239 /** 240 * Simulate a GET request with the given variables 241 * 242 * @param array $get all the GET parameters to use 243 * @param string $uri end URL to simulate 244 * @return TestResponse 245 */ 246 public function get($get = array(), $uri = '/doku.php') { 247 $this->get = array_merge($this->get, $get); 248 $this->setServer('REQUEST_METHOD', 'GET'); 249 return $this->execute($uri); 250 } 251 252 /** 253 * Add a notification to later store it in the test respone. 254 */ 255 public function addNotification(array $new) { 256 $this->notifications[] = $new; 257 } 258} 259