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