dcd8fcbed025d24f4725c9b9c0976a2c19d8e2ba
[mdref/mdref] / mdref / Action.php
1 <?php
2
3 namespace mdref;
4
5 use http\Controller\Observer;
6
7 /**
8 * Request handler
9 */
10 class Action extends Observer {
11 /**
12 * Reference paths
13 * @var string
14 */
15 protected $refpath;
16
17 /**
18 * The reference
19 * @var \mdref\Reference
20 */
21 private $reference;
22
23 /**
24 * Initialize the reference
25 */
26 protected function init() {
27 $this->reference = new Reference(explode(PATH_SEPARATOR, $this->refpath));
28 }
29
30 /**
31 * Create the view payload
32 * @param \http\Controller $ctl
33 * @return \stdClass
34 */
35 private function createPayload(\http\Controller $ctl) {
36 $pld = new \stdClass;
37
38 try {
39 $pld->quick = function($string) {
40 $md = \MarkdownDocument::createFromString($string);
41 $md->compile(\MarkdownDocument::AUTOLINK);
42 return $md->getHtml();
43 };
44
45 $pld->file = function($file) {
46 $fd = fopen($file, "r");
47 $md = \MarkdownDocument::createFromStream($fd);
48 $md->compile(\MarkdownDocument::AUTOLINK | \MarkdownDocument::TOC);
49 $html = $md->getHtml();
50 fclose($fd);
51 return $html;
52 };
53
54 $pld->ref = implode("/", $this->baseUrl->params(
55 $this->baseUrl->mod($ctl->getRequest()->getRequestUrl())));
56
57 $pld->refs = $this->reference;
58 $pld->baseUrl = $this->baseUrl;
59
60 } catch (\Exception $e) {
61 $pld->exception = $e;
62 }
63
64 return $pld;
65 }
66
67 /**
68 * Redirect to canononical url
69 * @param \http\Controller $ctl
70 * @param string $cnn
71 */
72 private function serveCanonical($ctl, $cnn) {
73 $ctl->detachAll(Observer\View::class);
74 $ctl->getResponse()->setHeader("Location", $this->baseUrl->mod($cnn));
75 $ctl->getResponse()->setResponseCode(301);
76 }
77
78 /**
79 * Serve index.css
80 * @param \http\Controller $ctl
81 */
82 private function serveStylesheet($ctl) {
83 $ctl->detachAll(Observer\View::class);
84 $ctl->getResponse()->setHeader("Content-Type", "text/css");
85 $ctl->getResponse()->setBody(new \http\Message\Body(fopen(ROOT."/public/index.css", "r")));
86 }
87
88 /**
89 * Serve index.js
90 * @param \http\Controller $ctl
91 */
92 private function serveJavascript($ctl) {
93 $ctl->detachAll(Observer\View::class);
94 $ctl->getResponse()->setHeader("Content-Type", "application/javascript");
95 $ctl->getResponse()->setBody(new \http\Message\Body(fopen(ROOT."/public/index.js", "r")));
96 }
97
98 /**
99 * Serve a preset
100 * @param \http\Controller $ctl
101 * @param \stdClass $pld
102 * @throws \http\Controller\Exception
103 */
104 private function servePreset($ctl, $pld) {
105 switch ($pld->ref) {
106 case "AUTHORS":
107 case "LICENSE":
108 case "VERSION":
109 $pld->text = file_get_contents(ROOT."/$pld->ref");
110 break;
111 case "index.css":
112 $this->serveStylesheet($ctl);
113 break;
114 case "index.js":
115 $this->serveJavascript($ctl);
116 break;
117 default:
118 throw new \http\Controller\Exception(404, "$pld->ref not found");
119 }
120 }
121
122 /**
123 * Implements Observer
124 * @param \SplSubject $ctl \http\Controller
125 */
126 public function update(\SplSubject $ctl) {
127 /* @var http\Controller $ctl */
128 $pld = $this->createPayload($ctl);
129 $ctl[Observer\View::class] = function() use($pld) {
130 return $pld;
131 };
132
133 if (!isset($pld->ref) || !strlen($pld->ref)) {
134 /* front page */
135 return;
136 }
137
138 $cnn = null;
139 if (($repo = $this->reference->getRepoForEntry($pld->ref, $cnn))) {
140 if (strlen($cnn)) {
141 /* redirect */
142 $this->serveCanonical($ctl, $cnn);
143 } else {
144 /* direct match */
145 $pld->entry = $repo->getEntry($pld->ref);
146 }
147 } else {
148 $this->servePreset($ctl, $pld);
149 }
150 }
151
152 }