X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=mdref%2FAction.php;h=05e007fe37b0ea176dda8d9be8b738c2e273294e;hb=904fc60f05894d6207e9ae85abda8c94283f7d28;hp=d85e300fed5fc36663505d57943372efe4cd0959;hpb=6a97dab17a6ee9a5a87ebb396da78fe87847794d;p=mdref%2Fmdref diff --git a/mdref/Action.php b/mdref/Action.php index d85e300..05e007f 100644 --- a/mdref/Action.php +++ b/mdref/Action.php @@ -2,92 +2,151 @@ namespace mdref; -use http\Controller\Observer; +use http\Env\Request; +use http\Env\Response; /** - * The sole action controller of mdref + * Request handler */ -class Action extends Observer -{ - private function serveReference(\http\Url $url, \stdClass $payload) { - $finder = new Finder($this->baseUrl, REFS); - $path = $finder->find($url); - $payload->listing = new RefListing($path, - $finder->glob($path, "/[:_a-zA-Z]*.md")); - $payload->title = $payload->listing->getSelf()->formatLink(); - $payload->refs = $finder; - if ($path->isFile()) { - $payload->html = new Markdown($path); - $payload->sublisting = new RefListing($path, - $finder->glob($path, "/[_a-z]*.md")); - return true; - } - } +class Action { + /** + * The reference + * @var \mdref\Reference + */ + private $reference; + + /** + * @var \http\Request + */ + private $request; + + /** + * @var \http\Response + */ + private $response; + + /** + * @var \http\Url + */ + private $baseUrl; - private function serveInternal(\http\Url $url, \stdClass $payload) { - $finder = new Finder($this->baseUrl, ROOT); - $path = $finder->find($url, ""); - if ($path->isFile("")) { - $payload->html = $path->toHtml(); - return true; - } + /** + * Initialize the reference + */ + public function __construct(Reference $ref, Request $req, Response $res, BaseUrl $baseUrl) { + $this->reference = $ref; + $this->request = $req; + $this->response = $res; + $this->baseUrl = $baseUrl; + ob_start($res); + } + + function esc($txt) { + return htmlspecialchars($txt); } - private function getType($file) { - static $inf = null; - static $typ = array(".css" => "text/css", ".js" => "applicatin/javascript"); - - $ext = strrchr($file, "."); - if (isset($typ[$ext])) { - return $typ[$ext]; - } + /** + * Create the view payload + * @param \http\Controller $ctl + * @return \stdClass + */ + private function createPayload() { + $pld = new \stdClass; - if (!$inf) { - $inf = new \FINFO(FILEINFO_MIME_TYPE); - } - return $inf->file($file); + $pld->esc = "htmlspecialchars"; + $pld->quick = [$this->reference, "formatString"]; + $pld->file = [$this->reference, "formatFile"]; + + $pld->ref = $this->baseUrl->pathinfo( + $this->baseUrl->mod($this->request->getRequestUrl())); + + $pld->refs = $this->reference; + $pld->baseUrl = $this->baseUrl; + + return $pld; } - private function servePublic(\http\Url $url, \http\Env\Response $res) { - $finder = new Finder($this->baseUrl, ROOT."/public"); - $path = $finder->find($url, ""); - if ($path->isFile("")) { - $res->setHeader("Content-Type", $this->getType($path->getFullPath(""))); - $res->setBody(new \http\Message\Body(fopen($path->getFullPath(""),"r"))); - return true; - } + /** + * Redirect to canononical url + * @param string $cnn + */ + private function serveCanonical($cnn) { + $this->response->setHeader("Location", $this->baseUrl->mod(["path" => $cnn])); + $this->response->setResponseCode(301); + $this->response->send(); } - + /** - * Implements \SplObserver - * @param \SplSubject $ctl + * Serve index.css */ - function update(\SplSubject $ctl) { - /* @var \http\Controller $ctl */ + private function serveStylesheet() { + $this->response->setHeader("Content-Type", "text/css"); + $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.css", "r"))); + $this->response->send(); + } + + /** + * Serve index.js + */ + private function serveJavascript() { + $this->response->setHeader("Content-Type", "application/javascript"); + $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.js", "r"))); + $this->response->send(); + } + + /** + * Serve a preset + * @param \stdClass $pld + * @throws Exception + */ + private function servePreset($pld) { + switch ($pld->ref) { + case "AUTHORS": + case "LICENSE": + case "VERSION": + $pld->text = file_get_contents(ROOT."/$pld->ref"); + break; + case "index.css": + $this->serveStylesheet(); + break; + case "index.js": + $this->serveJavascript(); + break; + default: + throw new Exception(404, "$pld->ref not found"); + } + } + + private function serve() { + extract((array) func_get_arg(0)); + include ROOT."/views/layout.phtml"; + $this->response->send(); + } + + public function handle() { try { - $pld = new \stdClass; - $ctl[Observer\View::class] = function() use($pld) { - return $pld; - }; - - $pld->baseUrl = $this->baseUrl; - $url = $this->baseUrl->mod($ctl->getRequest()->getRequestUrl()); - $pld->permUrl = implode("/", $this->baseUrl->params($url)); - if ($this->serveReference($url, $pld) || $this->serveInternal($url, $pld)) { - return; - } elseif ($this->servePublic($url, $ctl->getResponse())) { - $ctl->detachAll(Observer\View::class); - return; - } - - /* fallthrough */ - if (strcmp($url->path, $this->baseUrl->path)) { - throw new \http\Controller\Exception(404, "Could not find '$url'"); + + $pld = $this->createPayload(); + + if (strlen($pld->ref)) { + $cnn = null; + if (($repo = $this->reference->getRepoForEntry($pld->ref, $cnn))) { + if (strlen($cnn)) { + /* redirect */ + return $this->serveCanonical($cnn); + } else { + /* direct match */ + $pld->entry = $repo->getEntry($pld->ref); + } + } else { + return $this->servePreset($pld); + } } - } catch (\Exception $exception) { - $ctl[Observer\View::class] = function() use($exception) { - return compact("exception"); - }; + + } catch (\Exception $e) { + $pld->exception = $e; } + + $this->serve($pld); } -} +} \ No newline at end of file