1f8369d7dSTobias Sarnowski<?php 2f8369d7dSTobias Sarnowski/** 3f8369d7dSTobias Sarnowski * Simulates a full DokuWiki HTTP Request and allows 4f8369d7dSTobias Sarnowski * runtime inspection. 5f8369d7dSTobias Sarnowski */ 6f8369d7dSTobias Sarnowski 7f8369d7dSTobias Sarnowski// output buffering 8f8369d7dSTobias Sarnowski$output_buffer = ''; 9f8369d7dSTobias Sarnowski 10572dc222SLarsDW223$currentTestRequest = null; 11572dc222SLarsDW223 12f8369d7dSTobias Sarnowskifunction ob_start_callback($buffer) { 13f8369d7dSTobias Sarnowski global $output_buffer; 14f8369d7dSTobias Sarnowski $output_buffer .= $buffer; 15f8369d7dSTobias Sarnowski} 16f8369d7dSTobias Sarnowski 17f8369d7dSTobias Sarnowski/** 18f8369d7dSTobias Sarnowski * Helper class to execute a fake request 19f8369d7dSTobias Sarnowski */ 20f8369d7dSTobias Sarnowskiclass TestRequest { 21f8369d7dSTobias Sarnowski 22*1ada9e0aSAndreas Gohr protected $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php', '/lib/exe/ajax.php'); 23*1ada9e0aSAndreas Gohr protected $script; 249894e7afSChristopher Smith 25*1ada9e0aSAndreas Gohr protected $server = array(); 26*1ada9e0aSAndreas Gohr protected $session = array(); 27*1ada9e0aSAndreas Gohr protected $get = array(); 28*1ada9e0aSAndreas Gohr protected $post = array(); 29*1ada9e0aSAndreas Gohr protected $notifications = array(); 30f8369d7dSTobias Sarnowski 31*1ada9e0aSAndreas Gohr /** 32*1ada9e0aSAndreas Gohr * Get a $_SERVER var 33*1ada9e0aSAndreas Gohr * 34*1ada9e0aSAndreas Gohr * @param string $key 35*1ada9e0aSAndreas Gohr * @return mixed 36*1ada9e0aSAndreas Gohr */ 37*1ada9e0aSAndreas Gohr public function getServer($key) { 38*1ada9e0aSAndreas Gohr return $this->server[$key]; 39*1ada9e0aSAndreas Gohr } 40f8369d7dSTobias Sarnowski 41*1ada9e0aSAndreas Gohr /** 42*1ada9e0aSAndreas Gohr * Get a $_SESSION var 43*1ada9e0aSAndreas Gohr * 44*1ada9e0aSAndreas Gohr * @param string $key 45*1ada9e0aSAndreas Gohr * @return mixed 46*1ada9e0aSAndreas Gohr */ 47*1ada9e0aSAndreas Gohr public function getSession($key) { 48*1ada9e0aSAndreas Gohr return $this->session[$key]; 49*1ada9e0aSAndreas Gohr } 50*1ada9e0aSAndreas Gohr 51*1ada9e0aSAndreas Gohr /** 52*1ada9e0aSAndreas Gohr * Get a $_GET var 53*1ada9e0aSAndreas Gohr * 54*1ada9e0aSAndreas Gohr * @param string $key 55*1ada9e0aSAndreas Gohr * @return mixed 56*1ada9e0aSAndreas Gohr */ 57*1ada9e0aSAndreas Gohr public function getGet($key) { 58*1ada9e0aSAndreas Gohr return $this->get[$key]; 59*1ada9e0aSAndreas Gohr } 60*1ada9e0aSAndreas Gohr 61*1ada9e0aSAndreas Gohr /** 62*1ada9e0aSAndreas Gohr * Get a $_POST var 63*1ada9e0aSAndreas Gohr * 64*1ada9e0aSAndreas Gohr * @param string $key 65*1ada9e0aSAndreas Gohr * @return mixed 66*1ada9e0aSAndreas Gohr */ 67*1ada9e0aSAndreas Gohr public function getPost($key) { 68*1ada9e0aSAndreas Gohr return $this->post[$key]; 69*1ada9e0aSAndreas Gohr } 70*1ada9e0aSAndreas Gohr 71*1ada9e0aSAndreas Gohr /** 72*1ada9e0aSAndreas Gohr * Get the script that will execute the request 73*1ada9e0aSAndreas Gohr * 74*1ada9e0aSAndreas Gohr * @return string 75*1ada9e0aSAndreas Gohr */ 76*1ada9e0aSAndreas Gohr public function getScript() { 77*1ada9e0aSAndreas Gohr return $this->script; 78*1ada9e0aSAndreas Gohr } 79*1ada9e0aSAndreas Gohr 80*1ada9e0aSAndreas Gohr /** 81*1ada9e0aSAndreas Gohr * Set a $_SERVER var 82*1ada9e0aSAndreas Gohr * 83*1ada9e0aSAndreas Gohr * @param string $key 84*1ada9e0aSAndreas Gohr * @param mixed $value 85*1ada9e0aSAndreas Gohr */ 86*1ada9e0aSAndreas Gohr public function setServer($key, $value) { 87*1ada9e0aSAndreas Gohr $this->server[$key] = $value; 88*1ada9e0aSAndreas Gohr } 89*1ada9e0aSAndreas Gohr 90*1ada9e0aSAndreas Gohr /** 91*1ada9e0aSAndreas Gohr * Set a $_SESSION var 92*1ada9e0aSAndreas Gohr * 93*1ada9e0aSAndreas Gohr * @param string $key 94*1ada9e0aSAndreas Gohr * @param mixed $value 95*1ada9e0aSAndreas Gohr */ 96*1ada9e0aSAndreas Gohr public function setSession($key, $value) { 97*1ada9e0aSAndreas Gohr $this->session[$key] = $value; 98*1ada9e0aSAndreas Gohr } 99*1ada9e0aSAndreas Gohr 100*1ada9e0aSAndreas Gohr /** 101*1ada9e0aSAndreas Gohr * Set a $_GET var 102*1ada9e0aSAndreas Gohr * 103*1ada9e0aSAndreas Gohr * @param string $key 104*1ada9e0aSAndreas Gohr * @param mixed $value 105*1ada9e0aSAndreas Gohr */ 106*1ada9e0aSAndreas Gohr public function setGet($key, $value) { 107*1ada9e0aSAndreas Gohr $this->get[$key] = $value; 108*1ada9e0aSAndreas Gohr } 109*1ada9e0aSAndreas Gohr 110*1ada9e0aSAndreas Gohr /** 111*1ada9e0aSAndreas Gohr * Set a $_POST var 112*1ada9e0aSAndreas Gohr * 113*1ada9e0aSAndreas Gohr * @param string $key 114*1ada9e0aSAndreas Gohr * @param mixed $value 115*1ada9e0aSAndreas Gohr */ 116*1ada9e0aSAndreas Gohr public function setPost($key, $value) { 117*1ada9e0aSAndreas Gohr $this->post[$key] = $value; 118*1ada9e0aSAndreas Gohr } 119f8369d7dSTobias Sarnowski 120f8369d7dSTobias Sarnowski /** 121f8369d7dSTobias Sarnowski * Executes the request 122f8369d7dSTobias Sarnowski * 123*1ada9e0aSAndreas Gohr * @param string $uri end URL to simulate, needs to be one of the testable scripts 124f8369d7dSTobias Sarnowski * @return TestResponse the resulting output of the request 125f8369d7dSTobias Sarnowski */ 1264d053d04SAndreas Gohr public function execute($uri = '/doku.php') { 127fe717f57Slisps global $INPUT; 128572dc222SLarsDW223 global $currentTestRequest; 129572dc222SLarsDW223 130572dc222SLarsDW223 $currentTestRequest = $this; 131fe717f57Slisps 132f8369d7dSTobias Sarnowski // save old environment 133f8369d7dSTobias Sarnowski $server = $_SERVER; 134f8369d7dSTobias Sarnowski $session = $_SESSION; 135f8369d7dSTobias Sarnowski $get = $_GET; 136f8369d7dSTobias Sarnowski $post = $_POST; 137f8369d7dSTobias Sarnowski $request = $_REQUEST; 138fe717f57Slisps $input = $INPUT; 139f8369d7dSTobias Sarnowski 1404d053d04SAndreas Gohr // prepare the right URI 1414d053d04SAndreas Gohr $this->setUri($uri); 1424d053d04SAndreas Gohr 1430189bd86SAndreas Gohr // import all defined globals into the function scope 1440189bd86SAndreas Gohr foreach(array_keys($GLOBALS) as $glb) { 1450189bd86SAndreas Gohr global $$glb; 1460189bd86SAndreas Gohr } 1470189bd86SAndreas Gohr 148f8369d7dSTobias Sarnowski // fake environment 149f8369d7dSTobias Sarnowski global $default_server_vars; 150f8369d7dSTobias Sarnowski $_SERVER = array_merge($default_server_vars, $this->server); 151f8369d7dSTobias Sarnowski $_SESSION = $this->session; 152f8369d7dSTobias Sarnowski $_GET = $this->get; 153f8369d7dSTobias Sarnowski $_POST = $this->post; 154f8369d7dSTobias Sarnowski $_REQUEST = array_merge($_GET, $_POST); 155f8369d7dSTobias Sarnowski 156f8369d7dSTobias Sarnowski // reset output buffer 157f8369d7dSTobias Sarnowski global $output_buffer; 158f8369d7dSTobias Sarnowski $output_buffer = ''; 159f8369d7dSTobias Sarnowski 160f8369d7dSTobias Sarnowski // now execute dokuwiki and grep the output 161f8369d7dSTobias Sarnowski header_remove(); 162f8369d7dSTobias Sarnowski ob_start('ob_start_callback'); 163fe717f57Slisps $INPUT = new Input(); 1649894e7afSChristopher Smith include(DOKU_INC . $this->script); 165f8369d7dSTobias Sarnowski ob_end_flush(); 166f8369d7dSTobias Sarnowski 167f8369d7dSTobias Sarnowski // create the response object 168f8369d7dSTobias Sarnowski $response = new TestResponse( 169f8369d7dSTobias Sarnowski $output_buffer, 1709894e7afSChristopher Smith (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()) // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli 171f8369d7dSTobias Sarnowski ); 172572dc222SLarsDW223 if($this->notifications != null) { 173572dc222SLarsDW223 $response->setNotifications($this->notifications); 174572dc222SLarsDW223 } 175f8369d7dSTobias Sarnowski 176f8369d7dSTobias Sarnowski // reset environment 177f8369d7dSTobias Sarnowski $_SERVER = $server; 178f8369d7dSTobias Sarnowski $_SESSION = $session; 179f8369d7dSTobias Sarnowski $_GET = $get; 180f8369d7dSTobias Sarnowski $_POST = $post; 181f8369d7dSTobias Sarnowski $_REQUEST = $request; 182fe717f57Slisps $INPUT = $input; 183f8369d7dSTobias Sarnowski 184572dc222SLarsDW223 $currentTestRequest = null; 185572dc222SLarsDW223 186f8369d7dSTobias Sarnowski return $response; 187f8369d7dSTobias Sarnowski } 1889e777ceeSAndreas Gohr 1899e777ceeSAndreas Gohr /** 1909e777ceeSAndreas Gohr * Set the virtual URI the request works against 1919e777ceeSAndreas Gohr * 1929e777ceeSAndreas Gohr * This parses the given URI and sets any contained GET variables 1939e777ceeSAndreas Gohr * but will not overwrite any previously set ones (eg. set via setGet()). 1949e777ceeSAndreas Gohr * 1959e777ceeSAndreas Gohr * It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING'] 1969e777ceeSAndreas Gohr * with all set GET variables. 1979e777ceeSAndreas Gohr * 198*1ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 199*1ada9e0aSAndreas Gohr * @throws Exception when an invalid script is passed 2009e777ceeSAndreas Gohr */ 2014d053d04SAndreas Gohr protected function setUri($uri) { 2029894e7afSChristopher Smith if(!preg_match('#^(' . join('|', $this->valid_scripts) . ')#', $uri)) { 2039894e7afSChristopher Smith throw new Exception("$uri \n--- only " . join(', ', $this->valid_scripts) . " are supported currently"); 2049e777ceeSAndreas Gohr } 2059e777ceeSAndreas Gohr 2069e777ceeSAndreas Gohr $params = array(); 2079e777ceeSAndreas Gohr list($uri, $query) = explode('?', $uri, 2); 2089e777ceeSAndreas Gohr if($query) parse_str($query, $params); 2099e777ceeSAndreas Gohr 2109894e7afSChristopher Smith $this->script = substr($uri, 1); 2119e777ceeSAndreas Gohr $this->get = array_merge($params, $this->get); 2129e777ceeSAndreas Gohr if(count($this->get)) { 2139e777ceeSAndreas Gohr $query = '?' . http_build_query($this->get, '', '&'); 2149e777ceeSAndreas Gohr $query = str_replace( 2159e777ceeSAndreas Gohr array('%3A', '%5B', '%5D'), 2169e777ceeSAndreas Gohr array(':', '[', ']'), 2179e777ceeSAndreas Gohr $query 2189e777ceeSAndreas Gohr ); 2199e777ceeSAndreas Gohr $uri = $uri . $query; 2209e777ceeSAndreas Gohr } 2219e777ceeSAndreas Gohr 2229e777ceeSAndreas Gohr $this->setServer('QUERY_STRING', $query); 2239e777ceeSAndreas Gohr $this->setServer('REQUEST_URI', $uri); 2249e777ceeSAndreas Gohr } 2259e777ceeSAndreas Gohr 2269e777ceeSAndreas Gohr /** 2279e777ceeSAndreas Gohr * Simulate a POST request with the given variables 2289e777ceeSAndreas Gohr * 2299e777ceeSAndreas Gohr * @param array $post all the POST parameters to use 230*1ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 231*1ada9e0aSAndreas Gohr * @return TestResponse 2329e777ceeSAndreas Gohr */ 2339e777ceeSAndreas Gohr public function post($post = array(), $uri = '/doku.php') { 2349e777ceeSAndreas Gohr $this->post = array_merge($this->post, $post); 2359e777ceeSAndreas Gohr $this->setServer('REQUEST_METHOD', 'POST'); 2364d053d04SAndreas Gohr return $this->execute($uri); 2379e777ceeSAndreas Gohr } 2389e777ceeSAndreas Gohr 2399e777ceeSAndreas Gohr /** 2409e777ceeSAndreas Gohr * Simulate a GET request with the given variables 2419e777ceeSAndreas Gohr * 242*1ada9e0aSAndreas Gohr * @param array $get all the GET parameters to use 243*1ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 244*1ada9e0aSAndreas Gohr * @return TestResponse 2459e777ceeSAndreas Gohr */ 2469e777ceeSAndreas Gohr public function get($get = array(), $uri = '/doku.php') { 2479e777ceeSAndreas Gohr $this->get = array_merge($this->get, $get); 2489e777ceeSAndreas Gohr $this->setServer('REQUEST_METHOD', 'GET'); 2494d053d04SAndreas Gohr return $this->execute($uri); 2509e777ceeSAndreas Gohr } 2519e777ceeSAndreas Gohr 252572dc222SLarsDW223 /** 253572dc222SLarsDW223 * Add a notification to later store it in the test respone. 254572dc222SLarsDW223 */ 255572dc222SLarsDW223 public function addNotification(array $new) { 256572dc222SLarsDW223 $this->notifications[] = $new; 257572dc222SLarsDW223 } 258f8369d7dSTobias Sarnowski} 259