| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
16c99894c7 | 名前空間の参照ちょっと修正 | 1 year ago |
|
|
d467d82a3e | DAO について修正 | 1 year ago |
|
|
2ade56a952 | Dao\Thread :: find 追加 | 1 year ago |
|
|
dd3a9027d5 | DAO 修正 | 1 year ago |
|
|
1ae5df5420 | ファイル構成変更 | 1 year ago |
|
|
445d6da9ef | ちDAOょっと呼出 | 1 year ago |
|
|
5a0cefbfbb | リファクタリング | 1 year ago |
|
|
837b3aaab5 | DAO にメソッド追加 | 1 year ago |
|
|
34859e55b3 | スレッドの削除 DAO 追加 | 1 year ago |
|
|
efa4ceedf8 | DAO 追加 | 1 year ago |
|
|
4b89165f8e | DTO 追加 | 1 year ago |
|
|
dca71147b4 | 移行用 SQL 追加 | 1 year ago |
| @@ -1,4 +1,5 @@ | |||||
| /images | /images | ||||
| /drafts | /drafts | ||||
| /database.php | /database.php | ||||
| /db.sqlite3 | |||||
| /www/images | |||||
| @@ -0,0 +1,99 @@ | |||||
| <?php | |||||
| namespace Dao; | |||||
| class | |||||
| Response | |||||
| { | |||||
| public static function | |||||
| fetch_all ( | |||||
| \SQLite3 $db, | |||||
| int $thread_id) | |||||
| : array | |||||
| { | |||||
| $sql = " | |||||
| SELECT | |||||
| thread_id, | |||||
| response_id, | |||||
| name, | |||||
| message, | |||||
| date, | |||||
| image, | |||||
| held, | |||||
| deleted, | |||||
| pass, | |||||
| good, | |||||
| bad | |||||
| FROM | |||||
| responses | |||||
| WHERE | |||||
| id = $thread_id"; | |||||
| $result = $db -> query ($sql); | |||||
| $responses = []; | |||||
| while (($row = $result -> fetchArray (SQLITE_ASSOC)) !== false) | |||||
| { | |||||
| $response = new Dto\Response; | |||||
| $response -> thread_id = $row['thread_id']; | |||||
| $response -> response_id = $row['response_id']; | |||||
| $response -> name = $row['name']; | |||||
| $response -> message = $row['message']; | |||||
| $response -> date = $row['date']; | |||||
| $response -> image = $row['image']; | |||||
| $response -> held = $row['held']; | |||||
| $response -> deleted = $row['deleted']; | |||||
| $response -> pass = $row['pass']; | |||||
| $response -> good = $row['good']; | |||||
| $response -> bad = $row['bad']; | |||||
| $responses[] = $response; | |||||
| } | |||||
| return $responses; | |||||
| } | |||||
| public static function | |||||
| like ( | |||||
| \SQLite3 $db, | |||||
| int $thread_id, | |||||
| int $response_id) | |||||
| : void | |||||
| { | |||||
| $sql = " | |||||
| UPDATE | |||||
| responses | |||||
| SET | |||||
| good = good + 1 | |||||
| WHERE | |||||
| (thread_id = $thread_id) | |||||
| AND (response_id = $response_id)"; | |||||
| $db -> query ($sql); | |||||
| } | |||||
| public static function | |||||
| dislike ( | |||||
| \SQLite3 $db, | |||||
| int $thread_id, | |||||
| int $response_id) | |||||
| : void | |||||
| { | |||||
| $sql = " | |||||
| UPDATE | |||||
| responses | |||||
| SET | |||||
| bad = bad + 1 | |||||
| WHERE | |||||
| (thread_id = $thread_id) | |||||
| AND (response_id = $response_id)"; | |||||
| $db -> query ($sql); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,124 @@ | |||||
| <?php | |||||
| namespace Dao; | |||||
| class | |||||
| Thread | |||||
| { | |||||
| public static function | |||||
| fetch_all ( | |||||
| \SQLite3 $db) | |||||
| : array | |||||
| { | |||||
| $sql = " | |||||
| SELECT | |||||
| t.id, | |||||
| t.title, | |||||
| t.explain, | |||||
| MAX(r.date) AS latest | |||||
| FROM | |||||
| threads AS t | |||||
| LEFT OUTER JOIN | |||||
| responses AS r | |||||
| ON | |||||
| r.thread_id = t.id | |||||
| WHERE | |||||
| t.id <> 1 | |||||
| -- AND t.deleted = 0 | |||||
| GROUP BY | |||||
| t.id | |||||
| ORDER BY | |||||
| latest DESC"; | |||||
| $result = $db -> query ($sql); | |||||
| $threads = []; | |||||
| while (($row = $result -> fetchArray (SQLITE3_ASSOC)) !== false) | |||||
| { | |||||
| $thread = new Dto\Thread; | |||||
| $thread -> id = $row['id']; | |||||
| $therad -> title = $row['title']; | |||||
| $thread -> explain = $row['explain']; | |||||
| $thread -> latest = $row['latest']; | |||||
| $threads[] = $thread; | |||||
| } | |||||
| return $therads; | |||||
| } | |||||
| public static function | |||||
| find ( | |||||
| \SQLite3 $db, | |||||
| int $id) | |||||
| : ?\Dto\Thread | |||||
| { | |||||
| $sql = " | |||||
| SELECT | |||||
| t.id, | |||||
| t.title, | |||||
| t.explain, | |||||
| MAX(r.date) AS latest | |||||
| FROM | |||||
| threads AS t | |||||
| LEFT OUTER JOIN | |||||
| responses AS r | |||||
| ON | |||||
| r.thread_id = t.id | |||||
| WHERE | |||||
| t.id = $id | |||||
| GROUP BY | |||||
| t.id | |||||
| ORDER BY | |||||
| latest DESC"; | |||||
| $result = $db -> query ($sql); | |||||
| if ($row === false) | |||||
| return null; | |||||
| $row = $result -> fetchArray (SQLITE3_ASSOC); | |||||
| if ($row === false) | |||||
| return null; | |||||
| $thread = new \Dto\Thread; | |||||
| $thread -> id = $row['id']; | |||||
| $thread -> title = $row['title']; | |||||
| $thread -> explain = $row['explain']; | |||||
| $thread -> length = $row['length']; | |||||
| return $thread; | |||||
| } | |||||
| public static function | |||||
| create_thread ( | |||||
| \SQLite3 $db, | |||||
| string $title, | |||||
| string $explain) | |||||
| : void | |||||
| { | |||||
| ; | |||||
| } | |||||
| public static function | |||||
| delete_thread ( | |||||
| \SQLite3 $db, | |||||
| int $id) | |||||
| : void | |||||
| { | |||||
| $db -> query (" | |||||
| DELETE FROM | |||||
| threads | |||||
| WHERE | |||||
| id = $id"); | |||||
| } | |||||
| } | |||||
| @@ -1,12 +0,0 @@ | |||||
| <?php | |||||
| function | |||||
| set_mysql ($db) | |||||
| { | |||||
| $url = 'localhost'; | |||||
| $user = 'root'; | |||||
| $pass = ''; | |||||
| return new mysqli ($url, $user, $pass, $db); | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| <?php | |||||
| namespace Dto; | |||||
| class | |||||
| Response | |||||
| { | |||||
| public int $thread_id; | |||||
| public int $response_id; | |||||
| public string $name; | |||||
| public ?string $message; | |||||
| public DateTime $date; | |||||
| public string $image; | |||||
| public bool $held; | |||||
| public bool $deleted; | |||||
| public ?string $pass; | |||||
| public int $good; | |||||
| public int $bad; | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace Dto; | |||||
| class | |||||
| Thread | |||||
| { | |||||
| public int $id; | |||||
| public string $title; | |||||
| public ?string $explain; | |||||
| public ?DateTime $latest; | |||||
| public bool $deleted; | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| <?php | |||||
| require_once __DIR__ . '/daos/response.php'; | |||||
| require_once __DIR__ . '/daos/thread.php'; | |||||
| require_once __DIR__ . '/dtos/response.php'; | |||||
| require_once __DIR__ . '/dtos/thread.php'; | |||||
| @@ -1,60 +0,0 @@ | |||||
| <?php | |||||
| require_once "${_SERVER['DOCUMENT_ROOT']}/database.php"; | |||||
| if (isset ($_GET['page'])) | |||||
| $page = $_GET['page']; | |||||
| else | |||||
| $page = 0; | |||||
| if (isset ($_GET['thread'])) | |||||
| $thread = $_GET['thread']; | |||||
| else | |||||
| $thread = -1; | |||||
| if (isset ($_GET['sort'])) | |||||
| { | |||||
| $sort = $_GET['sort']; | |||||
| if (!(in_array ($sort, array ('td', 'eg', 'ta', 'eb')))) | |||||
| $sort = 'td'; | |||||
| } | |||||
| else | |||||
| $sort = 'td'; | |||||
| // 画像のディレクトリを開く. | |||||
| $dir = './images/'; | |||||
| $handle = opendir ($dir); | |||||
| // MySQL 宣言 | |||||
| $mysqli = set_mysql ('miteruzo_bbs'); | |||||
| $mysqli -> set_charset ('utf8'); | |||||
| if ($result = $mysqli -> query ("SELECT * FROM threads WHERE id = $thread")) | |||||
| { | |||||
| $row = $result -> fetch_assoc (); | |||||
| $title = $row['title']; | |||||
| $explain = $row['explain']; | |||||
| $result -> close (); | |||||
| } | |||||
| if (isset ($_GET['id']) | |||||
| && isset ($_GET['evaluate']) | |||||
| && (($_GET['evaluate'] == 'good') || ($_GET['evaluate'] == 'bad'))) | |||||
| { | |||||
| $mysqli -> query (" | |||||
| UPDATE | |||||
| responses | |||||
| SET | |||||
| {$_GET['evaluate']} = {$_GET['evaluate']} + 1 | |||||
| WHERE | |||||
| (thread_id = $thread) AND (response_id = {$_GET['id']})"); | |||||
| header ("Location: ./?thread=$thread&sort=$sort"); | |||||
| } | |||||
| require_once './forms/index.frm.php'; | |||||
| @@ -1,10 +0,0 @@ | |||||
| <?php | |||||
| require_once './db_connection.php'; | |||||
| $files = glob ('./migrations/*.sql'); | |||||
| foreach ($files as $file) | |||||
| $__db_connection -> query (file_get_contents ($file)); | |||||
| @@ -1,2 +0,0 @@ | |||||
| CREATE TABLE `miteruzo_bbs`.`threads` ( `id` INT NOT NULL AUTO_INCREMENT , `title` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL , `explain` MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL , `latest` DATETIME NOT NULL , `length` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`)) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci; | |||||
| @@ -1,2 +0,0 @@ | |||||
| CREATE TABLE `miteruzo_bbs`.`responses` ( `thread_id` INT NOT NULL , `response_id` INT NOT NULL , `name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '名なしさん' , `message` MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL , `date` DATETIME NOT NULL , `image` VARCHAR(31) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL , `held` TINYINT NOT NULL DEFAULT '0' , `deleted` TINYINT NOT NULL DEFAULT '0' , `pass` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL , `good` INT NOT NULL DEFAULT '0' , `bad` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`thread_id`, `response_id`)) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci; | |||||
| @@ -0,0 +1 @@ | |||||
| CREATE TABLE `threads` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT , `title` TEXT NOT NULL, `explain` TEXT NOT NULL , `latest` TEXT NOT NULL , `length` INTEGER NOT NULL DEFAULT 0) ; | |||||
| @@ -0,0 +1,2 @@ | |||||
| CREATE TABLE `responses` ( `thread_id` INTEGER , `response_id` INTEGER , `name` TEXT NOT NULL DEFAULT '名なしさん' , `message` TEXT NOT NULL , `date` TEXT NOT NULL , `image` TEXT NOT NULL , `held` INTEGER NOT NULL DEFAULT 0 , `deleted` INTEGER NOT NULL DEFAULT 0 , `pass` TEXT NULL , `good` INTEGER NOT NULL DEFAULT 0, `bad` INTEGER NOT NULL DEFAULT 0 , PRIMARY KEY(thread_id, response_id )); | |||||
| @@ -1,169 +0,0 @@ | |||||
| const music = new Audio ('./assets/music.mp3'); // BGM | |||||
| let playing = false; // 再生フラグ | |||||
| let nowPlay = true; // 再生すべきかどぅか | |||||
| document.getElementById ('sort').addEventListener ('change', sortChange); | |||||
| /* | |||||
| * BGM を再生しよぅとする. | |||||
| * | |||||
| * 戻り値は,なし. | |||||
| */ | |||||
| async function | |||||
| PlayMusic () | |||||
| { | |||||
| // 再生中でなぃ場合 | |||||
| if (playing === false) | |||||
| { | |||||
| // BGM を再生しよぅとする. | |||||
| try | |||||
| { | |||||
| await music.play (); | |||||
| music.loop = true; | |||||
| playing = true; | |||||
| nowPlay = true; | |||||
| // オン/オフ・ボタン | |||||
| document.getElementById ('mute').innerHTML = 'BGM がうるさい人用'; | |||||
| } | |||||
| catch (err) | |||||
| { | |||||
| playing = false; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* | |||||
| * BGM の消音切替 | |||||
| * | |||||
| * 戻り値は,なし. | |||||
| */ | |||||
| function | |||||
| PauseMusic () | |||||
| { | |||||
| // 切替 | |||||
| if (nowPlay && playing) // 再生中の場合 | |||||
| { | |||||
| music.muted = true; | |||||
| document.getElementById ('mute').innerHTML = 'やっぱり BGM が恋しい人用'; | |||||
| nowPlay = false; | |||||
| } | |||||
| else // 消音中の場合 | |||||
| { | |||||
| music.muted = false; | |||||
| document.getElementById ('mute').innerHTML = 'BGM がうるさい人用'; | |||||
| nowPlay = true; | |||||
| } | |||||
| } | |||||
| // 1000 ms ごとに BGM 再生試行 | |||||
| window.setInterval (function | |||||
| () | |||||
| { | |||||
| PlayMusic (); | |||||
| }, | |||||
| 1000); | |||||
| // 画面クリックで BGM 再生試行 | |||||
| document.addEventListener ('click', function | |||||
| () | |||||
| { | |||||
| PlayMusic (); | |||||
| }); | |||||
| // 画面タッチで BGM 再生試行 | |||||
| document.addEventListener ('touchstart', function | |||||
| () | |||||
| { | |||||
| PlayMusic (); | |||||
| }); | |||||
| const body = document.getElementsByTagName ('body')[0]; // body 要素 | |||||
| const cv = document.getElementById ('work'); // 作業用 Canvas | |||||
| const g = cv.getContext ('2d'); // 作業用 Canvas のコンテクスト | |||||
| const list = ['magenta', 'lime', 'cyan', 'yellow', 'orange', 'pink', 'aliceblue', | |||||
| 'antiquewhite', 'aqua', 'aquamarine', 'bisque', 'lightgreen', 'linen', | |||||
| 'lightsalmon', 'darkorange', 'palegreen']; | |||||
| // 色リスト | |||||
| let nowColour = Math.floor (Math.random () * list.length); | |||||
| // 前の色番号 | |||||
| let nextColour = Math.floor (Math.random () * list.length); | |||||
| // 次の色番号 | |||||
| let [tempR, tempG, tempB] = getRGB (list[nowColour]); | |||||
| // 現在の RGB 値 | |||||
| // 3000 ms ごとに次の色指定 | |||||
| window.setInterval (function | |||||
| () | |||||
| { | |||||
| nowColour = nextColour; | |||||
| nextColour = Math.floor (Math.random () * list.length); | |||||
| }, | |||||
| 3000); | |||||
| // 20 ms ごとに,ぢょぢょに,色変更 | |||||
| window.setInterval (function | |||||
| () | |||||
| { | |||||
| let [nowR, nowG, nowB] = getRGB (list[nowColour]); | |||||
| let [nextR, nextG, nextB] = getRGB (list[nextColour]); | |||||
| body.style.backgroundColor = `rgb(${tempR}, ${tempG}, ${tempB})`; | |||||
| tempR += (nextR - nowR) / 150; | |||||
| tempG += (nextG - nowG) / 150; | |||||
| tempB += (nextB - nowB) / 150; | |||||
| }, | |||||
| 20); | |||||
| /* | |||||
| * カラ・コゥド c を RGB 値に変換する. | |||||
| * | |||||
| * 戻り値は,RGB 値排列. | |||||
| */ | |||||
| function | |||||
| getRGB (c) | |||||
| { | |||||
| g.fillStyle = c; | |||||
| g.fillRect (0, 0, 1, 1); | |||||
| const img = g.getImageData (0, 0, 1, 1); | |||||
| const px = img.data; | |||||
| const rgb = [px[0], px[1], px[2]]; | |||||
| return rgb; | |||||
| } | |||||
| function | |||||
| sortChange (evt) | |||||
| { | |||||
| const searchParams = new URLSearchParams (window.location.search); | |||||
| switch (evt.currentTarget.value) | |||||
| { | |||||
| default: | |||||
| window.location.href = `./?thread=${searchParams.get ('thread')}&sort=td`; | |||||
| break; | |||||
| case 'evaluate-good': | |||||
| window.location.href = `./?thread=${searchParams.get ('thread')}&sort=eg`; | |||||
| break; | |||||
| case 'time-asc': | |||||
| window.location.href = `./?thread=${searchParams.get ('thread')}&sort=ta`; | |||||
| break; | |||||
| case 'evaluate-bad': | |||||
| window.location.href = `./?thread=${searchParams.get ('thread')}&sort=eb`; | |||||
| break; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,56 @@ | |||||
| <?php | |||||
| require_once __DIR__ . '/../import.php'; | |||||
| use \Dto; | |||||
| $db = new SQLite3 ('../db.sqlite3'); | |||||
| if (isset ($_GET['page'])) | |||||
| $page = $_GET['page']; | |||||
| else | |||||
| $page = 0; | |||||
| if (isset ($_GET['thread'])) | |||||
| $thread = $_GET['thread']; | |||||
| else | |||||
| $thread = -1; | |||||
| if (isset ($_GET['sort'])) | |||||
| { | |||||
| $sort = $_GET['sort']; | |||||
| if (!(in_array ($sort, array ('td', 'eg', 'ta', 'eb')))) | |||||
| $sort = 'td'; | |||||
| } | |||||
| else | |||||
| $sort = 'td'; | |||||
| // 画像のディレクトリを開く. | |||||
| $dir = './images/'; | |||||
| $handle = opendir ($dir); | |||||
| if ($row = \Dao\Thread :: find ($db, $thread)) | |||||
| { | |||||
| $title = $row -> title; | |||||
| $explain = $row -> explain; | |||||
| } | |||||
| if (isset ($_GET['id'])) | |||||
| { | |||||
| if (($_GET['evaluate'] ?? '') === 'good') | |||||
| { | |||||
| \Dao\Response :: like ($db, (int) $_GET['id']); | |||||
| header ("Location: ./?thread=$thread&sort=$sort"); | |||||
| } | |||||
| if (($_GET['evaluate'] ?? '') === 'bad') | |||||
| { | |||||
| \Dao\Response :: dislike ($db, (int) $_GET['id']); | |||||
| header ("Location: ./?thread=$thread&sort=$sort"); | |||||
| } | |||||
| } | |||||
| require_once './forms/index.frm.php'; | |||||