--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2016 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+namespace hoplite\http2;
+
+require_once HOPLITE_ROOT . '/http2/middleware.php';
+require_once HOPLITE_ROOT . '/http2/request.php';
+require_once HOPLITE_ROOT . '/http2/response.php';
+
+class DataResponse extends Response {
+ public $data;
+
+ public function __construct($data) {
+ parent::__construct();
+ $this->data = $data;
+ }
+
+ public function generate() {
+ throw new \Exception(__CLASS__ . ' cannot generate a response');
+ }
+}
+
+class JsonResponse extends Response {
+ private $data;
+
+ public function __construct(DataResponse $r) {
+ $this->code = $r->code;
+ $this->data = $r->data;
+ }
+
+ public function generate() {
+ $this->headers['Content-Type'] = 'application/json';
+ parent::generate();
+ print json_encode($this->data);
+ }
+}
+
+class JsonResponseFilter extends Middleware {
+ public function execute(Request $request) {
+ $response = $this->next->execute($request);
+
+ if ($response instanceof DataResponse) {
+ return new JsonResponse($response);
+ }
+
+ return $response;
+ }
+}
--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2016 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+namespace hoplite\http2;
+
+require_once HOPLITE_ROOT . '/http2/pipeline.php';
+require_once HOPLITE_ROOT . '/http2/request.php';
+require_once HOPLITE_ROOT . '/http2/response.php';
+
+abstract class Middleware {
+ protected $pipeline;
+ protected $next;
+
+ public function __construct(Pipeline $pipeline,
+ Middleware $next) {
+ $this->pipeline = $pipeline;
+ $this->next = $next;
+ }
+
+ public abstract /*http\Response*/ function execute(Request $request);
+}
+
+class Sentinel extends Middleware {
+ private $response;
+
+ public function __construct(Response $response) {
+ $this->response = $response;
+ }
+
+ public function execute(Request $request) {
+ return $this->response;
+ }
+}
+
+class ClosureMiddleware extends Middleware {
+ private $closure;
+
+ public function __construct(Pipeline $pipeline,
+ Middleware $next,
+ \Closure $closure) {
+ parent::__construct($pipeline, $next);
+ $this->closure = $closure;
+ }
+
+ public function execute(Request $request) {
+ $closure = $this->closure;
+ return $closure($request, $this->next);
+ }
+}
--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2016 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+namespace hoplite\http2;
+
+require_once HOPLITE_ROOT . '/http2/middleware.php';
+require_once HOPLITE_ROOT . '/http2/request.php';
+require_once HOPLITE_ROOT . '/http2/response.php';
+
+class Pipeline {
+ private $middleware = [];
+
+ public function add($middleware) {
+ /*
+ if (!($middleware instanceof Middleware ||
+ $middleware instanceof \Closure ||
+ is_array($middleware))) {
+ // TODO(php7): TypeError
+ throw new \Exception(__FUNCTION__ . ' requires a Middleware or Closure');
+ }
+ */
+ $this->middleware[] = $middleware;
+ return $this;
+ }
+
+ public function build() {
+ $chain = new Sentinel(new NotFoundResponse());
+ for ($i = count($this->middleware) - 1; $i >= 0; --$i) {
+ $args = $this->middleware[$i];
+ if ($args instanceof \Closure) {
+ $chain = new ClosureMiddleware($this, $chain, $args);
+ } else if (is_array($args)) {
+ $class = array_shift($args);
+ array_unshift($args, $this, $chain);
+ $chain = new $class(...$args);
+ } else {
+ $chain = new $args($this, $chain);
+ }
+ }
+
+ return $chain;
+ }
+
+ public function run(Middleware $chain) {
+ $response = $chain->execute(new Request());
+ $response->generate();
+ }
+
+ public function buildAndRun() {
+ $this->run($this->build());
+ }
+}
+
+class SubPipeline extends Middleware {
+ public function __construct(Pipeline $subpipe) {
+ // Skip calling super since this is a new pipeline and the
+ // next middleware will be selected by building the subpipe.
+ // It would be possible to build the middleware chain here, but
+ // doing it lazily on execution is more efficient, since SubPipeline
+ // should be used to partition applications.
+ $this->subpipe = $subpipe;
+ }
+
+ public function execute(Request $request) {
+ return $this->subpipe->build()->execute($request);
+ }
+}
--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2016 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+namespace hoplite\http2;
+
+/*!
+ A Request represents a HTTP request and holds the data and context associated
+ with it.
+*/
+class Request
+{
+ /*! @var string The request method (upper case). */
+ public $http_method = NULL;
+
+ /*! @var string The URL, relataive to the RootController. */
+ public $url = '';
+
+ /*! @var array HTTP request data. */
+ public $data = [];
+
+ /*! @var array Context data. */
+ public $context = [];
+
+ /*!
+ Constructor. Takes an optional URL.
+ */
+ public function __construct($url='')
+ {
+ $this->url = $url;
+ }
+
+ /*!
+ Wrapper around filter_input() that stores the result in the ::$data field.
+ */
+ public function filter($type, $name, $filter=FILTER_SANITIZE_STRING, $options=NULL)
+ {
+ $rv = filter_input($type, $name, $filter, $options);
+ $this->data[$name] = $rv;
+ return $rv;
+ }
+
+ /*!
+ Wrapper around filter_input() that merges the result in the ::$data field.
+ */
+ public function filterArray($type, $definition, $add_empty=TRUE)
+ {
+ $rv = filter_input_array($type, $definition, $add_empty);
+ $this->data = array_merge($this->data, $rv);
+ return $rv;
+ }
+}
--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2016 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+namespace hoplite\http2;
+
+require_once HOPLITE_ROOT . '/http/response_code.php';
+
+class Response
+{
+ /*! @var integer The HTTP response code to return. */
+ public $code;
+
+ /*! @var array A map of headers to values to be sent with the response. */
+ public $headers = [];
+
+ public function __construct($code=\hoplite\http\ResponseCode::OK) {
+ $this->code = $code;
+ }
+
+ /*! @var string Raw HTTP response body. */
+ public function generate() {
+ http_response_code($this->code);
+ foreach ($this->headers as $header => $value) {
+ header("$header: $value");
+ }
+ }
+}
+
+class NotFoundResponse extends Response {
+ public function __construct() {
+ parent::__construct(\hoplite\http\ResponseCode::NOT_FOUND);
+ }
+
+ public function generate() {
+ parent::generate();
+ print '<h1>404 - Not Found</h1>';
+ }
+}
+
+class TextResponse extends Response {
+ private $text;
+
+ public function __construct($text) {
+ parent::__construct();
+ $this->text = $text;
+ $this->headers['Content-Type'] = 'text/plain';
+ }
+
+ public function generate() {
+ parent::generate();
+ print $this->text;
+ }
+}