3 // Copyright (c) 2011 Blue Static
5 // This program is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or any later version.
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 // You should have received a copy of the GNU General Public License along with
15 // this program. If not, see <http://www.gnu.org/licenses/>.
17 namespace hoplite\http
;
19 require_once HOPLITE_ROOT
. '/http/request.php';
20 require_once HOPLITE_ROOT
. '/http/response.php';
21 require_once HOPLITE_ROOT
. '/http/response_code.php';
24 The RootController is meant to be invoked from the index.php of the
30 private $request = NULL
;
33 private $response = NULL
;
36 private $url_map = NULL
;
38 /*! @var OutputFilter */
39 private $output_filter = NULL
;
41 /*! @var RootControllerDelegate */
42 private $delegate = NULL
;
45 Creates the controller with the request context information, typicallhy
46 from the global scope ($GLOBALS), but can be injected for testing.
47 @param UrlMap The routing map
48 @param OutputFilter The object responsible for decorating output.
49 @param array& PHP globals array
51 public function __construct(array $globals)
53 $this->response
= new Response();
54 $this->request
= new Request();
55 $this->request
->data
= array(
56 '_GET' => &$globals['_GET'],
57 '_POST' => &$globals['_POST'],
58 '_COOKIE' => &$globals['_COOKIE'],
59 '_SERVER' => &$globals['_SERVER']
64 public function request() { return $this->request
; }
65 public function response() { return $this->response
; }
67 /*! Sets the UrlMap. */
68 public function set_url_map(UrlMap
$url_map) { $this->url_map
= $url_map; }
70 /*! Sest the Output Filter. */
71 public function set_output_filter(OutputFilter
$output_filter)
73 $this->output_filter
= $output_filter;
76 /*! Sets the delegate. */
77 public function set_delegate($delegate)
79 $this->delegate
= $delegate;
81 public function delegate()
83 return $this->delegate
->Get();
87 Createst the Request and Response that are used throughout the duration of
92 // The query rewriter module of the webserver rewrites a request from:
93 // http://example.com/webapp/user/view/42
95 // http://example.com/webapp/index.php/user/view/42
96 // ... which then becomes accessible from PATH_INFO.
97 $data = $this->request
->data
['_SERVER'];
98 if (isset($data['PATH_INFO']))
99 $url = $data['PATH_INFO'];
103 $url = substr($url, 1);
105 // Set the final pieces of the request.
106 $this->request
->url
= $url;
107 $this->request
->http_method
= $this->request
->data
['_SERVER']['REQUEST_METHOD'];
109 // Extract any PUT data as POST params.
110 if ($this->request
->http_method
== 'PUT')
111 parse_str(file_get_contents('php://input'), $this->request
->data
['_POST']);
113 // Register self as the active instance.
114 $GLOBALS[__CLASS__
] = $this;
116 $this->delegate
->OnInitialRequest($this->request
, $this->response
);
118 // Dispatch the request to an Action.
119 $this->RouteRequest($this->request
);
121 // When control returns here, all actions have been invoked and it's time
122 // to start the output filter and exit.
127 Prevents any other Actions from executing. This starts the OutputFilter and
130 public function Stop()
132 $this->delegate
->WillStop($this->request
, $this->response
);
133 $this->output_filter
->FilterOutput($this->request
, $this->response
);
138 Sets the response code and stops the controller. Returns void.
140 public function StopWithCode($code)
142 $this->response
->response_code
= $code;
147 Sets the response code to HTTP 302 FOUND and redirects the page to a new
149 @param string The destination location of the redirect.
151 public function StopWithRedirect($location)
153 $this->response
->headers
['Location'] = $location;
154 $this->StopWithCode(ResponseCode
::FOUND
);
159 Wrapper around PHP exit().
161 protected function _Exit()
167 Invoked by Run() and can be invoked by others to evaluate and perform the
168 lookup in the UrlMap. This then calls InvokeAction().
169 @param Request The Request whose URL will be routed
171 public function RouteRequest(Request
$request)
173 $this->delegate
->WillRouteRequest($request, $this->response
);
175 $url_map_value = $this->url_map
->Evaluate($request);
179 $action = $this->url_map
->LookupAction($url_map_value);
182 $this->response
->response_code
= ResponseCode
::NOT_FOUND
;
187 $this->InvokeAction($action);
191 Used to run an Action and drive it through its states.
194 public function InvokeAction(Action
$action)
196 $this->delegate
->WillInvokeAction($action, $this->request
, $this->response
);
198 $action->FilterRequest($this->request
, $this->response
);
199 $action->Invoke($this->request
, $this->response
);
200 $action->FilterResponse($this->request
, $this->response
);
202 $this->delegate
->DidInvokeAction($action, $this->request
, $this->response
);
206 Performs a reverse-lookup in the UrlMap for the pattern/fragment for the
207 name of a given Action class.
208 @param string Class name.
210 public function LookupAction($class)
212 $map = $this->url_map
->map();
213 foreach ($map as $pattern => $action) {
214 if ($action == $class)
220 Given a relative path, return an absolute path from the root controller.
221 @param string The relative path for which a URL will be created
222 @param bool Include the HTTP scheme and host to create an RFC URL if true;
223 if false an absolute path will be returned.
225 public function MakeURL($new_path, $url = FALSE
)
227 // Detect the common paths between the REQUEST_URI and the PATH_INFO. That
228 // common piece will be the path to the root controller.
229 $request_uri = $this->request()->data
['_SERVER']['REQUEST_URI'];
230 $path_info = $this->request()->data
['_SERVER']['PATH_INFO'];
231 if ($path_info === NULL
)
232 $common_uri = substr($request_uri, 0, -1);
234 $common_uri = strstr($request_uri, $path_info, TRUE
);
236 // If just constructing an absolute path, return that now.
238 return $common_uri . $new_path;
240 // Otherwise, build the host part.
242 if (isset($this->request()->data
['_SERVER']['HTTPS']) &&
243 $this->request()->data
['_SERVER']['HTTPS'] == 'on') {
246 $url .= '://' . $this->request()->data
['_SERVER']['HTTP_HOST'];
248 $port = $this->request()->data
['_SERVER']['SERVER_PORT'];
249 if ($port != 80 && $port != 443)
253 return $url . $new_path;
258 Delegate for the root controller. All methods are optional.
260 interface RootControllerDelegate
262 public function OnInitialRequest(Request
$request, Response
$response);
264 public function WillRouteRequest(Request
$request, Response
$response);
266 public function WillInvokeAction(Action
$action, Request
$request, Response
$response);
268 public function DidInvokeAction(Action
$action, Request
$request, Response
$response);
270 public function WillStop(Request
$request, Response
$response);