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