Last active
August 30, 2020 14:38
-
-
Save thekid/3bb2b6cd099f58bce85fa8447103a833 to your computer and use it in GitHub Desktop.
Test application for https://github.com/xp-forge/web/pull/65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| use web\frontend\{Frontend, Templates, View}; | |
| use web\session\{InFileSystem, Cookies}; | |
| use web\{Application, Filter, Filters}; | |
| class Uploads extends Application { | |
| /** @return [:var] */ | |
| public function routes() { | |
| // Upload handler | |
| $upload= new class() { | |
| #[@get] | |
| public function show() { | |
| return View::named('form'); | |
| } | |
| #[@post, @$request: request()] | |
| public function handle($request) { | |
| $uploaded= []; | |
| foreach ($request->multipart()->files() as $file) { | |
| $uploaded[]= ['name' => $file->name(), 'size' => strlen($file->bytes())]; | |
| } | |
| return empty($uploaded) | |
| ? View::named('form') | |
| : View::named('uploaded')->with(['files' => $uploaded]) | |
| ; | |
| } | |
| }; | |
| // Simple template engine with inline templates | |
| $templates= new class() implements Templates { | |
| private static $templates= [ | |
| 'login' => ' | |
| <h1>Login for {{request.uri.path}}</h1> | |
| <form method="POST"> | |
| <input type="hidden" name="return" value="{{request.uri.path}}"/> | |
| <label for="user">Username</label><input type="text" name="user"><br/> | |
| <label for="pass">Password</label><input type="password" name="pass"><br/> | |
| <input type="submit" value="Login"> | |
| </form> | |
| ', | |
| 'form' => ' | |
| <h1>Welcome @{{request.values.user}}</h1 | |
| <p>Please upload a file</p> | |
| <form method="POST" enctype="multipart/form-data"> | |
| <input type="hidden" name="token" value="{{request.values.token}}"/> | |
| <label for="file">Select file</label><input type="file" name="upload"/><br/> | |
| <input type="submit" value="Upload"/> | |
| </form> | |
| ', | |
| 'uploaded' => ' | |
| <h1>Thanks, @{{request.values.user}}!</h1 | |
| <p>You have uploaded the file {{files.0.name}}, which is {{files.0.size}} bytes in size</p> | |
| <a href="/">Upload another file</a> | |
| ' | |
| ]; | |
| public function write($name, $context, $out) { | |
| $out->write(preg_replace_callback( | |
| '/\{\{([^}]+)\}\}/', | |
| function($match) use($name, $context) { | |
| $lookup= $context + ['this' => $name]; | |
| foreach (explode('.', $match[1]) as $segment) { | |
| $lookup= is_object($lookup) ? $lookup->{$segment}() : $lookup[$segment] ?? null; | |
| } | |
| return $lookup; | |
| }, | |
| '<!DOCTYPE html><html><head><title>{{this}}</title></head><body>'. | |
| (self::$templates[$name] ?? '(Undefined template "'.$name.'")'). | |
| '</body></html>' | |
| )); | |
| } | |
| }; | |
| // Simple form-based authentication | |
| $auth= new class($templates) implements Filter { | |
| private $sessions, $templates; | |
| public function __construct($templates) { | |
| $this->sessions= (new InFileSystem('.'))->via((new Cookies())->insecure(true)); | |
| $this->templates= $templates; | |
| } | |
| public function filter($request, $response, $invocation) { | |
| if ($session= $this->sessions->locate($request)) { | |
| $request->pass('user', $session->value('user')); | |
| $request->pass('token', $session->value('token')); | |
| return $invocation->proceed($request, $response); | |
| } | |
| // Authenticate, then redirect to get rid of POST method | |
| if ('POST' === $request->method() && 'test:test' === $request->param('user').':'.$request->param('pass')) { | |
| $session= $this->sessions->create(); | |
| $session->register('user', 'test'); | |
| $session->register('token', uniqid()); | |
| $response->answer(303); | |
| $response->header('Location', $request->param('return', '/')); | |
| $session->transmit($response); | |
| return; | |
| } | |
| // Show login form | |
| $response->answer(200); | |
| $response->header('Content-Type', 'text/html; charset=utf-8'); | |
| $out= $response->stream(); | |
| try { | |
| $this->templates->write('login', ['request' => $request], $out); | |
| } finally { | |
| $out->close(); | |
| } | |
| } | |
| }; | |
| return [ | |
| '/favicon.ico' => fn($request, $response) => $response->answer(404), | |
| '/' => new Filters([$auth], new Frontend($upload, $templates)), | |
| ]; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment