fix ignore refs
[mdref/mdref] / mdref / Action.php
1 <?php
2
3 namespace mdref;
4
5 use http\Env\Request;
6 use http\Env\Response;
7 use http\Message\Body;
8
9 /**
10 * Request handler
11 */
12 class Action {
13 /**
14 * The reference
15 * @var \mdref\Reference
16 */
17 private $reference;
18
19 /**
20 * @var \http\Request
21 */
22 private $request;
23
24 /**
25 * @var \http\Response
26 */
27 private $response;
28
29 /**
30 * @var \http\Url
31 */
32 private $baseUrl;
33
34 /**
35 * Initialize the reference
36 */
37 public function __construct(Reference $ref, Request $req, Response $res, BaseUrl $baseUrl) {
38 $this->reference = $ref;
39 $this->request = $req;
40 $this->response = $res;
41 $this->baseUrl = $baseUrl;
42 ob_start($res);
43 }
44
45 function esc($txt) {
46 return htmlspecialchars($txt);
47 }
48
49 /**
50 * Create the view payload
51 * @param \http\Controller $ctl
52 * @return \stdClass
53 */
54 private function createPayload() {
55 $pld = new \stdClass;
56
57 $pld->esc = "htmlspecialchars";
58 $pld->anchor = [$this->reference, "formatAnchor"];
59 $pld->quick = [$this->reference, "formatString"];
60 $pld->file = [$this->reference, "formatFile"];
61
62 $pld->ref = $this->baseUrl->pathinfo(
63 $this->baseUrl->mod($this->request->getRequestUrl()));
64
65 $pld->refs = $this->reference;
66 $pld->baseUrl = $this->baseUrl;
67
68 return $pld;
69 }
70
71 /**
72 * Redirect to canononical url
73 * @param string $cnn
74 */
75 private function serveCanonical($cnn) {
76 $this->response->setHeader("Location", $this->baseUrl->mod(["path" => $cnn]));
77 $this->response->setResponseCode(301);
78 $this->response->send();
79 }
80
81 /**
82 * Serve index.css
83 */
84 private function serveStylesheet() {
85 $this->response->setHeader("Content-Type", "text/css");
86 $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.css", "r")));
87 $this->response->send();
88 }
89
90 /**
91 * Serve index.js
92 */
93 private function serveJavascript() {
94 $this->response->setHeader("Content-Type", "application/javascript");
95 $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.js", "r")));
96 $this->response->send();
97 }
98
99 /**
100 * Server a PHP stub
101 */
102 private function serveStub() {
103 $name = $this->request->getQuery("ref", "s");
104 $repo = $this->reference->getRepoForEntry($name);
105 if (!$repo->hasStub($stub)) {
106 throw new Exception(404, "Stub not found");
107 }
108 $this->response->setHeader("Content-Type", "application/x-php");
109 $this->response->setContentDisposition(["attachment" => ["filename" => "$name.stub.php"]]);
110 $this->response->setBody(new Body(fopen($stub, "r")));
111 $this->response->send();
112 }
113
114 /**
115 * Serve a preset
116 * @param \stdClass $pld
117 * @return true to continue serving the payload
118 * @throws Exception
119 */
120 private function servePreset($pld) {
121 switch ($pld->ref) {
122 case "AUTHORS":
123 case "LICENSE":
124 case "VERSION":
125 $pld->text = file_get_contents(ROOT."/$pld->ref");
126 return true;
127 case "index.css":
128 $this->serveStylesheet();
129 break;
130 case "index.js":
131 $this->serveJavascript();
132 break;
133 case "stub":
134 $this->serveStub();
135 break;
136 default:
137 throw new Exception(404, "$pld->ref not found");
138 }
139 return false;
140 }
141
142 private function serve() {
143 extract((array) func_get_arg(0));
144 include ROOT."/views/layout.phtml";
145 $this->response->send();
146 }
147
148 public function handle() {
149 try {
150
151 $pld = $this->createPayload();
152
153 if (strlen($pld->ref)) {
154 $cnn = null;
155 if (($repo = $this->reference->getRepoForEntry($pld->ref, $cnn))) {
156 if (strlen($cnn)) {
157 /* redirect */
158 return $this->serveCanonical($cnn);
159 } else {
160 /* direct match */
161 $pld->entry = $repo->getEntry($pld->ref);
162 }
163 } elseif (!$this->servePreset($pld)) {
164 return;
165 }
166 }
167
168 } catch (\Exception $e) {
169 $pld->exception = $e;
170 }
171
172 $this->serve($pld);
173 }
174 }