xref: /dokuwiki/_test/core/TestRequest.php (revision 3e2fa388693f117b05e78c833043887bdae5578b)
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
49        // save old environment
50        $server = $_SERVER;
51        $session = $_SESSION;
52        $get = $_GET;
53        $post = $_POST;
54        $request = $_REQUEST;
55        $input = $INPUT;
56
57        // prepare the right URI
58        $this->setUri($uri);
59
60        // import all defined globals into the function scope
61        foreach(array_keys($GLOBALS) as $glb){
62            global $$glb;
63        }
64
65        // fake environment
66        global $default_server_vars;
67        $_SERVER = array_merge($default_server_vars, $this->server);
68        $_SESSION = $this->session;
69        $_GET = $this->get;
70        $_POST = $this->post;
71        $_REQUEST = array_merge($_GET, $_POST);
72
73        // reset output buffer
74        global $output_buffer;
75        $output_buffer = '';
76
77        // now execute dokuwiki and grep the output
78        header_remove();
79        ob_start('ob_start_callback');
80        $INPUT = new Input();
81        include(DOKU_INC.$this->script);
82        ob_end_flush();
83
84        // create the response object
85        $response = new TestResponse(
86            $output_buffer,
87            (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list())   // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli
88        );
89
90        // reset environment
91        $_SERVER = $server;
92        $_SESSION = $session;
93        $_GET = $get;
94        $_POST = $post;
95        $_REQUEST = $request;
96        $INPUT = $input;
97
98        return $response;
99    }
100
101    /**
102     * Set the virtual URI the request works against
103     *
104     * This parses the given URI and sets any contained GET variables
105     * but will not overwrite any previously set ones (eg. set via setGet()).
106     *
107     * It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING']
108     * with all set GET variables.
109     *
110     * @param string $url  end URL to simulate, needs to start with /doku.php currently
111     * @todo make this work with other end points
112     */
113    protected function setUri($uri){
114        if(!preg_match('#^('.join('|',$this->valid_scripts).')#',$uri)){
115            throw new Exception("$uri \n--- only ".join(', ',$this->valid_scripts)." are supported currently");
116        }
117
118        $params = array();
119        list($uri, $query) = explode('?',$uri,2);
120        if($query) parse_str($query, $params);
121
122        $this->script = substr($uri,1);
123        $this->get  = array_merge($params, $this->get);
124        if(count($this->get)){
125            $query = '?'.http_build_query($this->get, '', '&');
126            $query = str_replace(
127                array('%3A', '%5B', '%5D'),
128                array(':', '[', ']'),
129                $query
130            );
131            $uri = $uri.$query;
132        }
133
134        $this->setServer('QUERY_STRING', $query);
135        $this->setServer('REQUEST_URI', $uri);
136    }
137
138    /**
139     * Simulate a POST request with the given variables
140     *
141     * @param array $post  all the POST parameters to use
142     * @param string $url  end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently
143     * @param return TestResponse
144     */
145    public function post($post=array(), $uri='/doku.php') {
146        $this->post = array_merge($this->post, $post);
147        $this->setServer('REQUEST_METHOD', 'POST');
148        return $this->execute($uri);
149    }
150
151    /**
152     * Simulate a GET request with the given variables
153     *
154     * @param array $GET   all the GET parameters to use
155     * @param string $url  end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently
156     * @param return TestResponse
157     */
158    public function get($get=array(), $uri='/doku.php') {
159        $this->get  = array_merge($this->get, $get);
160        $this->setServer('REQUEST_METHOD', 'GET');
161        return $this->execute($uri);
162    }
163
164
165}
166