summaryrefslogtreecommitdiffhomepage
path: root/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-11-24 04:58:38 +0900
committernsfisis <nsfisis@gmail.com>2025-11-24 04:58:38 +0900
commit67094790d2d9db5c99e7c136f49061a78698e57d (patch)
tree02feb966e74c7c2d1b6a77d8310502aa9758649b /vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025
parenta071111365f9760b2f97fa3f6e12aee9f75dd15d (diff)
downloadnil.ninja-67094790d2d9db5c99e7c136f49061a78698e57d.tar.gz
nil.ninja-67094790d2d9db5c99e7c136f49061a78698e57d.tar.zst
nil.ninja-67094790d2d9db5c99e7c136f49061a78698e57d.zip
Add vhosts/t/phpcon-kagawa-2025/
Diffstat (limited to 'vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025')
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieEatHandler.php66
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieHandler.php92
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/GetHandler.php31
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/HealthHandler.php29
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/NotFoundHandler.php29
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php164
6 files changed, 411 insertions, 0 deletions
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieEatHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieEatHandler.php
new file mode 100644
index 0000000..93e9c3b
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieEatHandler.php
@@ -0,0 +1,66 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class CookieEatHandler implements RequestHandlerInterface
+{
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $cookies = $request->getCookieParams();
+
+ $orders = [];
+ if (isset($cookies['order']) && $cookies['order'] !== '') {
+ $orders = explode(',', $cookies['order']);
+ }
+
+ if (count($orders) > 0) {
+ $orderList = '<ul>';
+ foreach ($orders as $order) {
+ $orderList .= '<li>' . htmlspecialchars($order) . '</li>';
+ }
+ $orderList .= '</ul>';
+ $message = '<p>ごちそうさまでした。</p>';
+ } else {
+ $orderList = '';
+ $message = '<p>注文がありません。</p>';
+ }
+
+ $body = <<<HTML
+<!DOCTYPE html>
+<html lang="ja">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>いただきます</title>
+</head>
+<body>
+ <div class="container">
+ <h1>いただきます</h1>
+ {$orderList}
+ {$message}
+ <a href="/phpcon-kagawa-2025/cookie/">もう一度注文する</a>
+ </div>
+</body>
+</html>
+HTML;
+
+ return $this->responseFactory->createResponse(200)
+ ->withHeader('Content-Type', 'text/html; charset=UTF-8')
+ ->withHeader('Set-Cookie', 'order=; Max-Age=0; path=/')
+ ->withBody($this->streamFactory->createStream($body));
+ }
+}
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieHandler.php
new file mode 100644
index 0000000..0b9f656
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/CookieHandler.php
@@ -0,0 +1,92 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class CookieHandler implements RequestHandlerInterface
+{
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $cookies = $request->getCookieParams();
+
+ $orders = [];
+ if (isset($cookies['order']) && $cookies['order'] !== '') {
+ $orders = explode(',', $cookies['order']);
+ }
+
+ $setCookie = null;
+
+ if ($request->getMethod() === 'POST') {
+ $postData = [];
+ parse_str((string) $request->getBody(), $postData);
+ $newOrder = $postData['udon'] ?? '';
+ if ($newOrder !== '') {
+ $orders[] = $newOrder;
+ $setCookie = 'order=' . urlencode(implode(',', $orders)) . '; path=/';
+ }
+ }
+
+ $orderList = '';
+ if (count($orders) > 0) {
+ $orderList = '<h2>現在の注文</h2><ul>';
+ foreach ($orders as $order) {
+ $orderList .= '<li>' . htmlspecialchars($order) . '</li>';
+ }
+ $orderList .= '</ul>';
+ $orderList .= '<a href="/phpcon-kagawa-2025/cookie/eat/">食べる</a>';
+ } else {
+ $orderList = '<p>まだ注文がありません。</p>';
+ }
+
+ $body = <<<HTML
+<!DOCTYPE html>
+<html lang="ja">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>うどん店</title>
+</head>
+<body>
+ <main>
+ <h1>うどん店</h1>
+ <form method="POST" action="/cookie/">
+ <div>
+ <select name="udon">
+ <option value="かけ">かけ</option>
+ <option value="ぶっかけ">ぶっかけ</option>
+ <option value="釜揚げ">釜揚げ</option>
+ <option value="釜玉">釜玉</option>
+ </select>
+ </div>
+ <button type="submit">注文</button>
+ </form>
+ {$orderList}
+ </main>
+</body>
+</html>
+HTML;
+
+ $response = $this->responseFactory->createResponse(200)
+ ->withHeader('Content-Type', 'text/html; charset=UTF-8')
+ ->withBody($this->streamFactory->createStream($body));
+
+ if ($setCookie !== null) {
+ $response = $response->withHeader('Set-Cookie', $setCookie);
+ }
+
+ return $response;
+ }
+}
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/GetHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/GetHandler.php
new file mode 100644
index 0000000..555ef79
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/GetHandler.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class GetHandler implements RequestHandlerInterface
+{
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ ob_start();
+ phpinfo(INFO_GENERAL | INFO_CREDITS | INFO_LICENSE);
+ $body = ob_get_clean();
+
+ return $this->responseFactory->createResponse(200)
+ ->withHeader('Content-Type', 'text/plain; charset=UTF-8')
+ ->withBody($this->streamFactory->createStream($body));
+ }
+}
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/HealthHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/HealthHandler.php
new file mode 100644
index 0000000..2c2d1b5
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/HealthHandler.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class HealthHandler implements RequestHandlerInterface
+{
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $body = 'OK';
+
+ return $this->responseFactory->createResponse(200)
+ ->withHeader('Content-Type', 'text/plain; charset=UTF-8')
+ ->withBody($this->streamFactory->createStream($body));
+ }
+}
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/NotFoundHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/NotFoundHandler.php
new file mode 100644
index 0000000..0d5b33f
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/NotFoundHandler.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class NotFoundHandler implements RequestHandlerInterface
+{
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $body = '404 Not Found';
+
+ return $this->responseFactory->createResponse(404)
+ ->withHeader('Content-Type', 'text/plain; charset=UTF-8')
+ ->withBody($this->streamFactory->createStream($body));
+ }
+}
diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php
new file mode 100644
index 0000000..2653e3e
--- /dev/null
+++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php
@@ -0,0 +1,164 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Nsfisis\TinyPhpHttpd\PhpConKagawa2025;
+
+use Psr\Http\Message\ResponseFactoryInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\StreamFactoryInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+final readonly class PostHandler implements RequestHandlerInterface
+{
+ /**
+ * @var array<string, string>
+ */
+ private const array ANSWERS = [
+ 'ehime' => 'hiroshima',
+ 'kagawa' => 'okayama',
+ 'tokushima' => 'hyogo',
+ ];
+
+ /**
+ * @var array<string, string>
+ */
+ private const array PREFECTURE_NAMES = [
+ 'okayama' => '岡山',
+ 'hiroshima' => '広島',
+ 'yamaguchi' => '山口',
+ 'hyogo' => '兵庫',
+ 'osaka' => '大阪',
+ ];
+
+ private const string QUIZ_FORM = <<<'HTML'
+<!DOCTYPE html>
+<html lang="ja">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>本州四国連絡橋クイズ</title>
+</head>
+<body>
+ <main>
+ <h1>本州四国連絡橋クイズ</h1>
+ <p>四国の各県と橋でつながっている中国地方の県を選んでください。</p>
+ <form method="POST" action="/post/">
+ <div>
+ <label>愛媛とつながっているのは?</label>
+ <select name="ehime">
+ <option value="">選択してください</option>
+ <option value="okayama">岡山</option>
+ <option value="hiroshima">広島</option>
+ <option value="yamaguchi">山口</option>
+ <option value="hyogo">兵庫</option>
+ <option value="osaka">大阪</option>
+ </select>
+ </div>
+ <div>
+ <label>香川とつながっているのは?</label>
+ <select name="kagawa">
+ <option value="">選択してください</option>
+ <option value="okayama">岡山</option>
+ <option value="hiroshima">広島</option>
+ <option value="yamaguchi">山口</option>
+ <option value="hyogo">兵庫</option>
+ <option value="osaka">大阪</option>
+ </select>
+ </div>
+ <div>
+ <label>徳島とつながっているのは?</label>
+ <select name="tokushima">
+ <option value="">選択してください</option>
+ <option value="okayama">岡山</option>
+ <option value="hiroshima">広島</option>
+ <option value="yamaguchi">山口</option>
+ <option value="hyogo">兵庫</option>
+ <option value="osaka">大阪</option>
+ </select>
+ </div>
+ <button type="submit">回答する</button>
+ </form>
+ </main>
+</body>
+</html>
+HTML;
+
+ public function __construct(
+ private ResponseFactoryInterface $responseFactory,
+ private StreamFactoryInterface $streamFactory,
+ ) {
+ }
+
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ if ($request->getMethod() === 'POST') {
+ $postData = [];
+ parse_str((string) $request->getBody(), $postData);
+
+ $userEhime = $postData['ehime'] ?? '';
+ $userKagawa = $postData['kagawa'] ?? '';
+ $userTokushima = $postData['tokushima'] ?? '';
+
+ $results = [];
+ $score = 0;
+
+ // Ehime
+ $userEhimeName = self::PREFECTURE_NAMES[$userEhime] ?? $userEhime;
+ if ($userEhime === self::ANSWERS['ehime']) {
+ $results[] = '<p>愛媛: ' . htmlspecialchars($userEhimeName) . ' ⭕ 正解!</p>';
+ $score++;
+ } else {
+ $results[] = '<p>愛媛: ' . htmlspecialchars($userEhimeName) . ' ❌ 不正解</p>';
+ }
+
+ // Kagawa
+ $userKagawaName = self::PREFECTURE_NAMES[$userKagawa] ?? $userKagawa;
+ if ($userKagawa === self::ANSWERS['kagawa']) {
+ $results[] = '<p>香川: ' . htmlspecialchars($userKagawaName) . ' ⭕ 正解!</p>';
+ $score++;
+ } else {
+ $results[] = '<p>香川: ' . htmlspecialchars($userKagawaName) . ' ❌ 不正解</p>';
+ }
+
+ // Tokushima
+ $userTokushimaName = self::PREFECTURE_NAMES[$userTokushima] ?? $userTokushima;
+ if ($userTokushima === self::ANSWERS['tokushima']) {
+ $results[] = '<p>徳島: ' . htmlspecialchars($userTokushimaName) . ' ⭕ 正解!</p>';
+ $score++;
+ } else {
+ $results[] = '<p>徳島: ' . htmlspecialchars($userTokushimaName) . ' ❌ 不正解</p>';
+ }
+
+ $resultHtml = implode("\n", $results);
+
+ $body = <<<HTML
+<!DOCTYPE html>
+<html lang="ja">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>クイズ結果</title>
+</head>
+<body>
+ <main>
+ <h1>クイズ結果</h1>
+ <p class="score">スコア: {$score} / 3</p>
+ {$resultHtml}
+ <p>
+ <a href="/phpcon-kagawa-2025/post/">もう一度挑戦する</a>
+ </p>
+ </main>
+</body>
+</html>
+HTML;
+ } else {
+ $body = self::QUIZ_FORM;
+ }
+
+ return $this->responseFactory->createResponse(200)
+ ->withHeader('Content-Type', 'text/html; charset=UTF-8')
+ ->withBody($this->streamFactory->createStream($body));
+ }
+}