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