1f8369d7dSTobias Sarnowski<?php 2f8369d7dSTobias Sarnowski/** 3f8369d7dSTobias Sarnowski * Simulates a full DokuWiki HTTP Request and allows 4f8369d7dSTobias Sarnowski * runtime inspection. 5f8369d7dSTobias Sarnowski */ 6f8369d7dSTobias Sarnowski 7572dc222SLarsDW223$currentTestRequest = null; 8572dc222SLarsDW223 9f8369d7dSTobias Sarnowski 10f8369d7dSTobias Sarnowski/** 11f8369d7dSTobias Sarnowski * Helper class to execute a fake request 12f8369d7dSTobias Sarnowski */ 13f8369d7dSTobias Sarnowskiclass TestRequest { 14f8369d7dSTobias Sarnowski 151ada9e0aSAndreas Gohr protected $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php', '/lib/exe/ajax.php'); 161ada9e0aSAndreas Gohr protected $script; 179894e7afSChristopher Smith 181ada9e0aSAndreas Gohr protected $server = array(); 191ada9e0aSAndreas Gohr protected $session = array(); 201ada9e0aSAndreas Gohr protected $get = array(); 211ada9e0aSAndreas Gohr protected $post = array(); 221ada9e0aSAndreas Gohr protected $notifications = array(); 23f8369d7dSTobias Sarnowski 24*444d58a8SAndreas Gohr /** @var string stores the output buffer, even when it's flushed */ 25*444d58a8SAndreas Gohr protected $output_buffer = ''; 26*444d58a8SAndreas Gohr 27*444d58a8SAndreas Gohr /** @var null|TestRequest the currently running request */ 28*444d58a8SAndreas Gohr static protected $running = null; 29*444d58a8SAndreas Gohr 301ada9e0aSAndreas Gohr /** 311ada9e0aSAndreas Gohr * Get a $_SERVER var 321ada9e0aSAndreas Gohr * 331ada9e0aSAndreas Gohr * @param string $key 341ada9e0aSAndreas Gohr * @return mixed 351ada9e0aSAndreas Gohr */ 361ada9e0aSAndreas Gohr public function getServer($key) { 371ada9e0aSAndreas Gohr return $this->server[$key]; 381ada9e0aSAndreas Gohr } 39f8369d7dSTobias Sarnowski 401ada9e0aSAndreas Gohr /** 411ada9e0aSAndreas Gohr * Get a $_SESSION var 421ada9e0aSAndreas Gohr * 431ada9e0aSAndreas Gohr * @param string $key 441ada9e0aSAndreas Gohr * @return mixed 451ada9e0aSAndreas Gohr */ 461ada9e0aSAndreas Gohr public function getSession($key) { 471ada9e0aSAndreas Gohr return $this->session[$key]; 481ada9e0aSAndreas Gohr } 491ada9e0aSAndreas Gohr 501ada9e0aSAndreas Gohr /** 511ada9e0aSAndreas Gohr * Get a $_GET var 521ada9e0aSAndreas Gohr * 531ada9e0aSAndreas Gohr * @param string $key 541ada9e0aSAndreas Gohr * @return mixed 551ada9e0aSAndreas Gohr */ 561ada9e0aSAndreas Gohr public function getGet($key) { 571ada9e0aSAndreas Gohr return $this->get[$key]; 581ada9e0aSAndreas Gohr } 591ada9e0aSAndreas Gohr 601ada9e0aSAndreas Gohr /** 611ada9e0aSAndreas Gohr * Get a $_POST var 621ada9e0aSAndreas Gohr * 631ada9e0aSAndreas Gohr * @param string $key 641ada9e0aSAndreas Gohr * @return mixed 651ada9e0aSAndreas Gohr */ 661ada9e0aSAndreas Gohr public function getPost($key) { 671ada9e0aSAndreas Gohr return $this->post[$key]; 681ada9e0aSAndreas Gohr } 691ada9e0aSAndreas Gohr 701ada9e0aSAndreas Gohr /** 711ada9e0aSAndreas Gohr * Get the script that will execute the request 721ada9e0aSAndreas Gohr * 731ada9e0aSAndreas Gohr * @return string 741ada9e0aSAndreas Gohr */ 751ada9e0aSAndreas Gohr public function getScript() { 761ada9e0aSAndreas Gohr return $this->script; 771ada9e0aSAndreas Gohr } 781ada9e0aSAndreas Gohr 791ada9e0aSAndreas Gohr /** 801ada9e0aSAndreas Gohr * Set a $_SERVER var 811ada9e0aSAndreas Gohr * 821ada9e0aSAndreas Gohr * @param string $key 831ada9e0aSAndreas Gohr * @param mixed $value 841ada9e0aSAndreas Gohr */ 851ada9e0aSAndreas Gohr public function setServer($key, $value) { 861ada9e0aSAndreas Gohr $this->server[$key] = $value; 871ada9e0aSAndreas Gohr } 881ada9e0aSAndreas Gohr 891ada9e0aSAndreas Gohr /** 901ada9e0aSAndreas Gohr * Set a $_SESSION var 911ada9e0aSAndreas Gohr * 921ada9e0aSAndreas Gohr * @param string $key 931ada9e0aSAndreas Gohr * @param mixed $value 941ada9e0aSAndreas Gohr */ 951ada9e0aSAndreas Gohr public function setSession($key, $value) { 961ada9e0aSAndreas Gohr $this->session[$key] = $value; 971ada9e0aSAndreas Gohr } 981ada9e0aSAndreas Gohr 991ada9e0aSAndreas Gohr /** 1001ada9e0aSAndreas Gohr * Set a $_GET var 1011ada9e0aSAndreas Gohr * 1021ada9e0aSAndreas Gohr * @param string $key 1031ada9e0aSAndreas Gohr * @param mixed $value 1041ada9e0aSAndreas Gohr */ 1051ada9e0aSAndreas Gohr public function setGet($key, $value) { 1061ada9e0aSAndreas Gohr $this->get[$key] = $value; 1071ada9e0aSAndreas Gohr } 1081ada9e0aSAndreas Gohr 1091ada9e0aSAndreas Gohr /** 1101ada9e0aSAndreas Gohr * Set a $_POST var 1111ada9e0aSAndreas Gohr * 1121ada9e0aSAndreas Gohr * @param string $key 1131ada9e0aSAndreas Gohr * @param mixed $value 1141ada9e0aSAndreas Gohr */ 1151ada9e0aSAndreas Gohr public function setPost($key, $value) { 1161ada9e0aSAndreas Gohr $this->post[$key] = $value; 1171ada9e0aSAndreas Gohr } 118f8369d7dSTobias Sarnowski 119f8369d7dSTobias Sarnowski /** 120f8369d7dSTobias Sarnowski * Executes the request 121f8369d7dSTobias Sarnowski * 1221ada9e0aSAndreas Gohr * @param string $uri end URL to simulate, needs to be one of the testable scripts 123f8369d7dSTobias Sarnowski * @return TestResponse the resulting output of the request 124f8369d7dSTobias Sarnowski */ 1254d053d04SAndreas Gohr public function execute($uri = '/doku.php') { 126fe717f57Slisps global $INPUT; 127572dc222SLarsDW223 global $currentTestRequest; 128572dc222SLarsDW223 129572dc222SLarsDW223 $currentTestRequest = $this; 130fe717f57Slisps 131f8369d7dSTobias Sarnowski // save old environment 132f8369d7dSTobias Sarnowski $server = $_SERVER; 133f8369d7dSTobias Sarnowski $session = $_SESSION; 134f8369d7dSTobias Sarnowski $get = $_GET; 135f8369d7dSTobias Sarnowski $post = $_POST; 136f8369d7dSTobias Sarnowski $request = $_REQUEST; 137fe717f57Slisps $input = $INPUT; 138f8369d7dSTobias Sarnowski 1394d053d04SAndreas Gohr // prepare the right URI 1404d053d04SAndreas Gohr $this->setUri($uri); 1414d053d04SAndreas Gohr 1420189bd86SAndreas Gohr // import all defined globals into the function scope 1430189bd86SAndreas Gohr foreach(array_keys($GLOBALS) as $glb) { 1440189bd86SAndreas Gohr global $$glb; 1450189bd86SAndreas Gohr } 1460189bd86SAndreas Gohr 147f8369d7dSTobias Sarnowski // fake environment 148f8369d7dSTobias Sarnowski global $default_server_vars; 149f8369d7dSTobias Sarnowski $_SERVER = array_merge($default_server_vars, $this->server); 150f8369d7dSTobias Sarnowski $_SESSION = $this->session; 151f8369d7dSTobias Sarnowski $_GET = $this->get; 152f8369d7dSTobias Sarnowski $_POST = $this->post; 153f8369d7dSTobias Sarnowski $_REQUEST = array_merge($_GET, $_POST); 154f8369d7dSTobias Sarnowski 155f8369d7dSTobias Sarnowski // reset output buffer 156*444d58a8SAndreas Gohr $this->output_buffer = ''; 157f8369d7dSTobias Sarnowski 158f8369d7dSTobias Sarnowski // now execute dokuwiki and grep the output 159*444d58a8SAndreas Gohr self::$running = $this; 160f8369d7dSTobias Sarnowski header_remove(); 161*444d58a8SAndreas Gohr ob_start(array($this, 'ob_start_callback')); 162fe717f57Slisps $INPUT = new Input(); 1639894e7afSChristopher Smith include(DOKU_INC . $this->script); 164f8369d7dSTobias Sarnowski ob_end_flush(); 165*444d58a8SAndreas Gohr self::$running = null; 166f8369d7dSTobias Sarnowski 167f8369d7dSTobias Sarnowski // create the response object 168f8369d7dSTobias Sarnowski $response = new TestResponse( 169*444d58a8SAndreas Gohr $this->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 * 1981ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 1991ada9e0aSAndreas 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 2301ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 2311ada9e0aSAndreas 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 * 2421ada9e0aSAndreas Gohr * @param array $get all the GET parameters to use 2431ada9e0aSAndreas Gohr * @param string $uri end URL to simulate 2441ada9e0aSAndreas 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 /** 253*444d58a8SAndreas Gohr * Callback for ob_start 254*444d58a8SAndreas Gohr * 255*444d58a8SAndreas Gohr * This continues to fill our own buffer, even when some part 256*444d58a8SAndreas Gohr * of the code askes for flushing the buffers 257*444d58a8SAndreas Gohr * 258*444d58a8SAndreas Gohr * @param string $buffer 259*444d58a8SAndreas Gohr */ 260*444d58a8SAndreas Gohr public function ob_start_callback($buffer) { 261*444d58a8SAndreas Gohr $this->output_buffer .= $buffer; 262*444d58a8SAndreas Gohr } 263*444d58a8SAndreas Gohr 264*444d58a8SAndreas Gohr /** 265572dc222SLarsDW223 * Add a notification to later store it in the test respone. 266572dc222SLarsDW223 */ 267572dc222SLarsDW223 public function addNotification(array $new) { 268572dc222SLarsDW223 $this->notifications[] = $new; 269572dc222SLarsDW223 } 270f8369d7dSTobias Sarnowski} 271