diff --git a/assets/misuzu.css/news/feeds.css b/assets/misuzu.css/news/feeds.css index bf0cda2..0ee8584 100644 --- a/assets/misuzu.css/news/feeds.css +++ b/assets/misuzu.css/news/feeds.css @@ -1,6 +1,6 @@ .news__feeds { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr; grid-gap: 2px; padding: 2px; } diff --git a/composer.json b/composer.json index fe0c0d0..ac5956e 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,13 @@ { "require": { - "flashwave/index": "^0.2408.40014", - "flashwave/sasae": "^1.1", - "flashwave/syokuhou": "^1.2", + "flashwave/index": "^0.2410", + "flashwave/aiwass": "^1.1", "erusev/parsedown": "~1.6", "chillerlan/php-qrcode": "^4.3", "symfony/mailer": "^6.0", "matomo/device-detector": "^6.1", "sentry/sdk": "^4.0", - "nesbot/carbon": "^3.7", - "flashwave/aiwass": "^1.0" + "nesbot/carbon": "^3.7" }, "autoload": { "classmap": [ diff --git a/composer.lock b/composer.lock index a95687c..7cb8ba6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c8edfa21e13dedc126a6351b7d367559", + "content-hash": "526f12235a073ac908e932627e1a16fa", "packages": [ { "name": "carbonphp/carbon-doctrine-types", @@ -418,15 +418,15 @@ }, { "name": "flashwave/aiwass", - "version": "v1.0.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://patchii.net/flashii/aiwass.git", - "reference": "de27da54b603f0fdc06dab89341908e73ea7a880" + "reference": "cf6653ed4676d549b543eeba2b9db517c1feb356" }, "require": { "ext-msgpack": ">=2.2", - "flashwave/index": "^0.2408.40014", + "flashwave/index": "^0.2410", "php": ">=8.3" }, "require-dev": { @@ -453,27 +453,32 @@ ], "description": "Shared HTTP RPC client/server library.", "homepage": "https://railgun.sh/aiwass", - "time": "2024-08-16T15:59:19+00:00" + "time": "2024-10-05T00:04:26+00:00" }, { "name": "flashwave/index", - "version": "v0.2408.611934", + "version": "v0.2410.42339", "source": { "type": "git", "url": "https://patchii.net/flash/index.git", - "reference": "2217c8c3de8e4ec8d7f9ec0f37078dbc2183d14e" + "reference": "d3e4d0985a1189d15fb8ed9eb105830c9dc38c4d" }, "require": { "ext-mbstring": "*", - "php": ">=8.3" + "php": ">=8.3", + "twig/html-extra": "^3.13", + "twig/twig": "^3.14" }, "require-dev": { "phpstan/phpstan": "^1.11", "phpunit/phpunit": "^11.2" }, "suggest": { - "ext-mysqli": "Support for the Index\\Data\\MariaDB namespace (both mysqlnd and libmysql are supported).", - "ext-sqlite3": "Support for the Index\\Data\\SQLite namespace." + "ext-memcache": "Support for the Index\\Cache\\Memcached namespace (only if you can't use ext-memcached for some reason).", + "ext-memcached": "Support for the Index\\Cache\\Memcached namespace (you should use this instead of ext-memcache).", + "ext-mysqli": "Support for the Index\\Db\\MariaDb namespace (both mysqlnd and libmysql are supported).", + "ext-redis": "Support for the Index\\Cache\\Valkey namespace.", + "ext-sqlite3": "Support for the Index\\Db\\Sqlite namespace." }, "type": "library", "autoload": { @@ -495,85 +500,7 @@ ], "description": "Composer package for the common library for my projects.", "homepage": "https://railgun.sh/index", - "time": "2024-09-30T17:34:51+00:00" - }, - { - "name": "flashwave/sasae", - "version": "v1.1.1", - "source": { - "type": "git", - "url": "https://patchii.net/flash/sasae.git", - "reference": "897a28e56926ad465bf0daf587caf3d92a311383" - }, - "require": { - "flashwave/index": "^0.2408.40014", - "php": ">=8.3", - "twig/html-extra": "^3.12", - "twig/twig": "^3.12" - }, - "require-dev": { - "phpstan/phpstan": "^1.11", - "phpunit/phpunit": "^11.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Sasae\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "bsd-3-clause-clear" - ], - "authors": [ - { - "name": "flashwave", - "email": "packagist@flash.moe", - "homepage": "https://flash.moe", - "role": "mom" - } - ], - "description": "A wrapper for Twig with added common functionality.", - "homepage": "https://railgun.sh/sasae", - "time": "2024-09-01T20:38:47+00:00" - }, - { - "name": "flashwave/syokuhou", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://patchii.net/flash/syokuhou.git", - "reference": "129a46c0d917382f9bc195cce278be51984eb87d" - }, - "require": { - "flashwave/index": "^0.2408.40014", - "php": ">=8.3" - }, - "require-dev": { - "phpstan/phpstan": "^1.11", - "phpunit/phpunit": "^11.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Syokuhou\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "bsd-3-clause-clear" - ], - "authors": [ - { - "name": "flashwave", - "email": "packagist@flash.moe", - "homepage": "https://flash.moe", - "role": "mom" - } - ], - "description": "Configuration library for PHP.", - "homepage": "https://railgun.sh/syokuhou", - "time": "2024-08-04T01:07:23+00:00" + "time": "2024-10-04T23:39:32+00:00" }, { "name": "guzzlehttp/psr7", diff --git a/database/2023_01_07_023235_initial_structure_ndx.php b/database/2023_01_07_023235_initial_structure_ndx.php index 7210679..3826061 100644 --- a/database/2023_01_07_023235_initial_structure_ndx.php +++ b/database/2023_01_07_023235_initial_structure_ndx.php @@ -1,11 +1,11 @@ execute(' CREATE TABLE msz_forum_topics_redirects ( topic_id INT(10) UNSIGNED NOT NULL, diff --git a/database/2023_07_21_121854_update_user_agent_storage.php b/database/2023_07_21_121854_update_user_agent_storage.php index 2f8e299..de993a4 100644 --- a/database/2023_07_21_121854_update_user_agent_storage.php +++ b/database/2023_07_21_121854_update_user_agent_storage.php @@ -1,10 +1,10 @@ execute(' ALTER TABLE msz_login_attempts diff --git a/database/2023_07_24_201010_add_moderator_notes_table.php b/database/2023_07_24_201010_add_moderator_notes_table.php index 140aaea..5d80532 100644 --- a/database/2023_07_24_201010_add_moderator_notes_table.php +++ b/database/2023_07_24_201010_add_moderator_notes_table.php @@ -1,9 +1,9 @@ execute(' CREATE TABLE msz_users_modnotes ( note_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, diff --git a/database/2023_07_26_175936_add_new_bans_table.php b/database/2023_07_26_175936_add_new_bans_table.php index 39175a6..4b802bd 100644 --- a/database/2023_07_26_175936_add_new_bans_table.php +++ b/database/2023_07_26_175936_add_new_bans_table.php @@ -1,9 +1,9 @@ execute(' CREATE TABLE msz_users_bans ( ban_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, diff --git a/database/2023_07_26_210150_redo_warnings_table.php b/database/2023_07_26_210150_redo_warnings_table.php index 7ad629f..f3017e9 100644 --- a/database/2023_07_26_210150_redo_warnings_table.php +++ b/database/2023_07_26_210150_redo_warnings_table.php @@ -1,9 +1,9 @@ execute(' CREATE TABLE msz_users_warnings ( warn_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, diff --git a/database/2023_07_27_130516_pluralise_users_for_role_relations.php b/database/2023_07_27_130516_pluralise_users_for_role_relations.php index 8b50af4..cdd0c10 100644 --- a/database/2023_07_27_130516_pluralise_users_for_role_relations.php +++ b/database/2023_07_27_130516_pluralise_users_for_role_relations.php @@ -1,9 +1,9 @@ execute('RENAME TABLE msz_user_roles TO msz_users_roles'); } } diff --git a/database/2023_07_28_212101_create_counters_table.php b/database/2023_07_28_212101_create_counters_table.php index 2b436f1..668e594 100644 --- a/database/2023_07_28_212101_create_counters_table.php +++ b/database/2023_07_28_212101_create_counters_table.php @@ -1,9 +1,9 @@ execute(' CREATE TABLE msz_counters ( counter_name VARBINARY(64) NOT NULL, diff --git a/database/2023_08_03_114403_update_collations_in_various_tables.php b/database/2023_08_03_114403_update_collations_in_various_tables.php index 30a7f2e..6e0fff1 100644 --- a/database/2023_08_03_114403_update_collations_in_various_tables.php +++ b/database/2023_08_03_114403_update_collations_in_various_tables.php @@ -1,9 +1,9 @@ execute(' ALTER TABLE msz_audit_log CHANGE COLUMN log_action log_action VARCHAR(50) NOT NULL COLLATE "ascii_general_ci" AFTER user_id, diff --git a/database/2023_08_30_213930_new_permissions_system.php b/database/2023_08_30_213930_new_permissions_system.php index 3cff692..9d1b22b 100644 --- a/database/2023_08_30_213930_new_permissions_system.php +++ b/database/2023_08_30_213930_new_permissions_system.php @@ -1,9 +1,9 @@ execute('DELETE FROM msz_config WHERE config_name = "perms.needsRecalc"'); diff --git a/database/2024_01_30_233734_create_messages_table.php b/database/2024_01_30_233734_create_messages_table.php index d46d4d9..b127243 100644 --- a/database/2024_01_30_233734_create_messages_table.php +++ b/database/2024_01_30_233734_create_messages_table.php @@ -1,9 +1,9 @@ execute(' CREATE TABLE msz_messages ( msg_id BINARY(8) NOT NULL, diff --git a/database/2024_06_02_194809_base_sixty_four_encode_pms_in_db.php b/database/2024_06_02_194809_base_sixty_four_encode_pms_in_db.php index 7d130c9..fb74b35 100644 --- a/database/2024_06_02_194809_base_sixty_four_encode_pms_in_db.php +++ b/database/2024_06_02_194809_base_sixty_four_encode_pms_in_db.php @@ -1,9 +1,9 @@ execute('UPDATE msz_messages SET msg_title = TO_BASE64(msg_title), msg_body = TO_BASE64(msg_body)'); $conn->execute(' ALTER TABLE `msz_messages` diff --git a/database/2024_09_16_205613_add_role_id_string.php b/database/2024_09_16_205613_add_role_id_string.php index 9353f70..143fdbc 100644 --- a/database/2024_09_16_205613_add_role_id_string.php +++ b/database/2024_09_16_205613_add_role_id_string.php @@ -1,9 +1,9 @@ execute(<<hasValues('sentry:dsn')) (function($cfg) { diff --git a/package-lock.json b/package-lock.json index 2223cd1..60909eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -417,9 +417,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "funding": [ { "type": "opencollective", @@ -703,9 +703,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "version": "1.5.32", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", + "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", "license": "ISC" }, "node_modules/entities": { diff --git a/public-legacy/auth/login.php b/public-legacy/auth/login.php index 48d8a22..3308370 100644 --- a/public-legacy/auth/login.php +++ b/public-legacy/auth/login.php @@ -4,7 +4,7 @@ namespace Misuzu; use Exception; use Misuzu\Auth\AuthTokenCookie; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $authInfo = $msz->getAuthInfo(); if($authInfo->isLoggedIn()) { Tools::redirect($urls->format('index')); diff --git a/public-legacy/auth/logout.php b/public-legacy/auth/logout.php index 195f714..1f9eb73 100644 --- a/public-legacy/auth/logout.php +++ b/public-legacy/auth/logout.php @@ -24,4 +24,4 @@ if($authInfo->isLoggedIn()) { AuthTokenCookie::apply($tokenPacker->pack($tokenInfo)); } -Tools::redirect($msz->getURLs()->format('index'));; +Tools::redirect($msz->getUrls()->format('index'));; diff --git a/public-legacy/auth/password.php b/public-legacy/auth/password.php index 444b2db..5f699ec 100644 --- a/public-legacy/auth/password.php +++ b/public-legacy/auth/password.php @@ -4,7 +4,7 @@ namespace Misuzu; use RuntimeException; use Misuzu\Users\User; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $authInfo = $msz->getAuthInfo(); if($authInfo->isLoggedIn()) { Tools::redirect($urls->format('settings-account')); diff --git a/public-legacy/auth/register.php b/public-legacy/auth/register.php index 85b95ca..59e6b7a 100644 --- a/public-legacy/auth/register.php +++ b/public-legacy/auth/register.php @@ -4,7 +4,7 @@ namespace Misuzu; use RuntimeException; use Misuzu\Users\User; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $authInfo = $msz->getAuthInfo(); if($authInfo->isLoggedIn()) { Tools::redirect($urls->format('index')); diff --git a/public-legacy/auth/revert.php b/public-legacy/auth/revert.php index 5d97a0d..e215be7 100644 --- a/public-legacy/auth/revert.php +++ b/public-legacy/auth/revert.php @@ -3,7 +3,7 @@ namespace Misuzu; use Misuzu\Auth\AuthTokenCookie; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); if(CSRF::validateRequest()) { $tokenInfo = $msz->getAuthInfo()->getTokenInfo(); diff --git a/public-legacy/auth/twofactor.php b/public-legacy/auth/twofactor.php index 56bcc0a..d3e08e3 100644 --- a/public-legacy/auth/twofactor.php +++ b/public-legacy/auth/twofactor.php @@ -5,7 +5,7 @@ use RuntimeException; use Misuzu\TOTPGenerator; use Misuzu\Auth\AuthTokenCookie; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $authInfo = $msz->getAuthInfo(); if($authInfo->isLoggedIn()) { Tools::redirect($urls->format('index')); diff --git a/public-legacy/comments.php b/public-legacy/comments.php index 7781f60..d254a61 100644 --- a/public-legacy/comments.php +++ b/public-legacy/comments.php @@ -4,7 +4,7 @@ namespace Misuzu; use RuntimeException; $usersCtx = $msz->getUsersContext(); -$redirect = filter_input(INPUT_GET, 'return') ?? $_SERVER['HTTP_REFERER'] ?? $msz->getURLs()->format('index'); +$redirect = filter_input(INPUT_GET, 'return') ?? $_SERVER['HTTP_REFERER'] ?? $msz->getUrls()->format('index'); if(!Tools::isLocalURL($redirect)) Template::displayInfo('Possible request forgery detected.', 403); diff --git a/public-legacy/forum/index.php b/public-legacy/forum/index.php index 5ae28c2..fec71b6 100644 --- a/public-legacy/forum/index.php +++ b/public-legacy/forum/index.php @@ -32,14 +32,14 @@ if($mode === 'mark') { $forumCategories->updateUserReadCategory($userInfo, $categoryInfo); } - Tools::redirect($msz->getURLs()->format($categoryId ? 'forum-category' : 'forum-index', ['forum' => $categoryId])); + Tools::redirect($msz->getUrls()->format($categoryId ? 'forum-category' : 'forum-index', ['forum' => $categoryId])); return; } Template::render('confirm', [ 'title' => 'Mark forum as read', 'message' => 'Are you sure you want to mark ' . ($categoryId < 1 ? 'the entire' : 'this') . ' forum as read?', - 'return' => $msz->getURLs()->format($categoryId ? 'forum-category' : 'forum-index', ['forum' => $categoryId]), + 'return' => $msz->getUrls()->format($categoryId ? 'forum-category' : 'forum-index', ['forum' => $categoryId]), 'params' => [ 'forum' => $categoryId, ] diff --git a/public-legacy/forum/leaderboard.php b/public-legacy/forum/leaderboard.php index b4a0337..19ee061 100644 --- a/public-legacy/forum/leaderboard.php +++ b/public-legacy/forum/leaderboard.php @@ -94,7 +94,7 @@ MD; $markdown .= sprintf("| %s | [%s](%s%s) | %s |\r\n", $ranking->position, $ranking->user?->getName() ?? 'Deleted User', $msz->getSiteInfo()->getURL(), - $msz->getURLs()->format('user-profile', ['user' => $ranking->userId]), + $msz->getUrls()->format('user-profile', ['user' => $ranking->userId]), number_format($ranking->postsCount)); } diff --git a/public-legacy/forum/post.php b/public-legacy/forum/post.php index 7ef0b34..31f4501 100644 --- a/public-legacy/forum/post.php +++ b/public-legacy/forum/post.php @@ -3,7 +3,7 @@ namespace Misuzu; use RuntimeException; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $forumCtx = $msz->getForumContext(); $forumPosts = $forumCtx->getPosts(); $usersCtx = $msz->getUsersContext(); diff --git a/public-legacy/forum/posting.php b/public-legacy/forum/posting.php index 2cf7b3f..173ac71 100644 --- a/public-legacy/forum/posting.php +++ b/public-legacy/forum/posting.php @@ -258,7 +258,7 @@ if(!empty($_POST)) { if(empty($notices)) { // does this ternary ever return forum-topic? - $redirect = $msz->getURLs()->format(empty($topicInfo) ? 'forum-topic' : 'forum-post', [ + $redirect = $msz->getUrls()->format(empty($topicInfo) ? 'forum-topic' : 'forum-post', [ 'topic' => $topicId ?? 0, 'post' => $postId ?? 0, ]); diff --git a/public-legacy/forum/topic.php b/public-legacy/forum/topic.php index ad204fd..81fb52a 100644 --- a/public-legacy/forum/topic.php +++ b/public-legacy/forum/topic.php @@ -4,7 +4,7 @@ namespace Misuzu; use stdClass; use RuntimeException; -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $forumCtx = $msz->getForumContext(); $forumCategories = $forumCtx->getCategories(); $forumTopics = $forumCtx->getTopics(); diff --git a/public-legacy/manage/changelog/change.php b/public-legacy/manage/changelog/change.php index 981b295..b3ac9b4 100644 --- a/public-legacy/manage/changelog/change.php +++ b/public-legacy/manage/changelog/change.php @@ -15,7 +15,7 @@ $changeActions = []; foreach(Changelog::ACTIONS as $action) $changeActions[$action] = Changelog::actionText($action); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $changelog = $msz->getChangelog(); $changeId = (string)filter_input(INPUT_GET, 'c', FILTER_SANITIZE_NUMBER_INT); $changeInfo = null; diff --git a/public-legacy/manage/changelog/tag.php b/public-legacy/manage/changelog/tag.php index 1e4ae07..9983604 100644 --- a/public-legacy/manage/changelog/tag.php +++ b/public-legacy/manage/changelog/tag.php @@ -6,7 +6,7 @@ use RuntimeException; if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_CL_TAGS_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $changelog = $msz->getChangelog(); $tagId = (string)filter_input(INPUT_GET, 't', FILTER_SANITIZE_NUMBER_INT); $loadTagInfo = fn() => $changelog->getTag($tagId); diff --git a/public-legacy/manage/forum/redirs.php b/public-legacy/manage/forum/redirs.php index 06c8a38..91735e4 100644 --- a/public-legacy/manage/forum/redirs.php +++ b/public-legacy/manage/forum/redirs.php @@ -5,7 +5,7 @@ $authInfo = $msz->getAuthInfo(); if(!$authInfo->getPerms('global')->check(Perm::G_FORUM_TOPIC_REDIRS_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $forumCtx = $msz->getForumContext(); $forumTopicRedirects = $forumCtx->getTopicRedirects(); diff --git a/public-legacy/manage/general/emoticon.php b/public-legacy/manage/general/emoticon.php index 823a7e3..fb8faa4 100644 --- a/public-legacy/manage/general/emoticon.php +++ b/public-legacy/manage/general/emoticon.php @@ -97,7 +97,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { [$emoteInfo->getId()] ); - Tools::redirect($msz->getURLs()->format('manage-general-emoticon', ['emote' => $emoteInfo->getId()])); + Tools::redirect($msz->getUrls()->format('manage-general-emoticon', ['emote' => $emoteInfo->getId()])); return; } diff --git a/public-legacy/manage/general/emoticons.php b/public-legacy/manage/general/emoticons.php index 66ad09e..a17488d 100644 --- a/public-legacy/manage/general/emoticons.php +++ b/public-legacy/manage/general/emoticons.php @@ -37,7 +37,7 @@ if(CSRF::validateRequest() && !empty($_GET['emote'])) { } } - Tools::redirect($msz->getURLs()->format('manage-general-emoticons')); + Tools::redirect($msz->getUrls()->format('manage-general-emoticons')); return; } diff --git a/public-legacy/manage/general/setting-delete.php b/public-legacy/manage/general/setting-delete.php index 872c92f..4f5c818 100644 --- a/public-legacy/manage/general/setting-delete.php +++ b/public-legacy/manage/general/setting-delete.php @@ -13,7 +13,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { $valueName = $valueInfo->getName(); $msz->createAuditLog('CONFIG_DELETE', [$valueName]); $cfg->removeValues($valueName); - Tools::redirect($msz->getURLs()->format('manage-general-settings')); + Tools::redirect($msz->getUrls()->format('manage-general-settings')); return; } diff --git a/public-legacy/manage/general/setting.php b/public-legacy/manage/general/setting.php index e03e08e..617a058 100644 --- a/public-legacy/manage/general/setting.php +++ b/public-legacy/manage/general/setting.php @@ -1,7 +1,7 @@ getAuthInfo()->getPerms('global')->check(Perm::G_CONFIG_MANAGE)) Template::throwError(403); @@ -73,7 +73,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { $msz->createAuditLog($isNew ? 'CONFIG_CREATE' : 'CONFIG_UPDATE', [$sName]); $applyFunc($sName, $sValue); - Tools::redirect($msz->getURLs()->format('manage-general-settings')); + Tools::redirect($msz->getUrls()->format('manage-general-settings')); return; } diff --git a/public-legacy/manage/news/category.php b/public-legacy/manage/news/category.php index 6cb7077..978a2e5 100644 --- a/public-legacy/manage/news/category.php +++ b/public-legacy/manage/news/category.php @@ -6,7 +6,7 @@ use RuntimeException; if(!$msz->getAuthInfo()->getPerms('global')->check(Perm::G_NEWS_CATEGORIES_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $news = $msz->getNews(); $categoryId = (string)filter_input(INPUT_GET, 'c', FILTER_SANITIZE_NUMBER_INT); $loadCategoryInfo = fn() => $news->getCategory(categoryId: $categoryId); diff --git a/public-legacy/manage/news/post.php b/public-legacy/manage/news/post.php index faeef96..66bc809 100644 --- a/public-legacy/manage/news/post.php +++ b/public-legacy/manage/news/post.php @@ -7,7 +7,7 @@ $authInfo = $msz->getAuthInfo(); if(!$authInfo->getPerms('global')->check(Perm::G_NEWS_POSTS_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $news = $msz->getNews(); $postId = (string)filter_input(INPUT_GET, 'p', FILTER_SANITIZE_NUMBER_INT); $loadPostInfo = fn() => $news->getPost($postId); diff --git a/public-legacy/manage/users/ban.php b/public-legacy/manage/users/ban.php index b537e0e..0680f71 100644 --- a/public-legacy/manage/users/ban.php +++ b/public-legacy/manage/users/ban.php @@ -9,7 +9,7 @@ $authInfo = $msz->getAuthInfo(); if(!$authInfo->getPerms('user')->check(Perm::U_BANS_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $usersCtx = $msz->getUsersContext(); $bans = $usersCtx->getBans(); diff --git a/public-legacy/manage/users/note.php b/public-legacy/manage/users/note.php index a69e1dc..e49d2c6 100644 --- a/public-legacy/manage/users/note.php +++ b/public-legacy/manage/users/note.php @@ -13,7 +13,7 @@ $hasUserId = filter_has_var(INPUT_GET, 'u'); if((!$hasNoteId && !$hasUserId) || ($hasNoteId && $hasUserId)) Template::throwError(400); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $usersCtx = $msz->getUsersContext(); $modNotes = $usersCtx->getModNotes(); diff --git a/public-legacy/manage/users/role.php b/public-legacy/manage/users/role.php index 721ff9b..d1ce6d9 100644 --- a/public-legacy/manage/users/role.php +++ b/public-legacy/manage/users/role.php @@ -168,7 +168,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { $msz->getConfig()->setBoolean('perms.needsRecalc', true); } - Tools::redirect($msz->getURLs()->format('manage-role', ['role' => $roleInfo->getId()])); + Tools::redirect($msz->getUrls()->format('manage-role', ['role' => $roleInfo->getId()])); return; } diff --git a/public-legacy/manage/users/user.php b/public-legacy/manage/users/user.php index 7574ee0..40f18d9 100644 --- a/public-legacy/manage/users/user.php +++ b/public-legacy/manage/users/user.php @@ -12,7 +12,7 @@ $viewerPerms = $authInfo->getPerms('user'); if(!$authInfo->isLoggedIn()) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $usersCtx = $msz->getUsersContext(); $users = $usersCtx->getUsers(); $roles = $usersCtx->getRoles(); diff --git a/public-legacy/manage/users/warning.php b/public-legacy/manage/users/warning.php index 7fc19e7..68f3506 100644 --- a/public-legacy/manage/users/warning.php +++ b/public-legacy/manage/users/warning.php @@ -7,7 +7,7 @@ $authInfo = $msz->getAuthInfo(); if(!$authInfo->getPerms('user')->check(Perm::U_WARNINGS_MANAGE)) Template::throwError(403); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $usersCtx = $msz->getUsersContext(); $users = $usersCtx->getUsers(); $warns = $usersCtx->getWarnings(); diff --git a/public-legacy/profile.php b/public-legacy/profile.php index ae1f444..8d9a2b9 100644 --- a/public-legacy/profile.php +++ b/public-legacy/profile.php @@ -14,7 +14,7 @@ $userId = !empty($_GET['u']) && is_string($_GET['u']) ? trim($_GET['u']) : 0; $profileMode = !empty($_GET['m']) && is_string($_GET['m']) ? (string)$_GET['m'] : ''; $isEditing = !empty($_GET['edit']) && is_string($_GET['edit']) ? (bool)$_GET['edit'] : !empty($_POST) && is_array($_POST); -$urls = $msz->getURLs(); +$urls = $msz->getUrls(); $usersCtx = $msz->getUsersContext(); $users = $usersCtx->getUsers(); $forumCtx = $msz->getForumContext(); diff --git a/public-legacy/settings/data.php b/public-legacy/settings/data.php index 9d115fb..e4002fa 100644 --- a/public-legacy/settings/data.php +++ b/public-legacy/settings/data.php @@ -3,7 +3,6 @@ namespace Misuzu; use ZipArchive; use Index\XString; -use Index\IO\FileStream; use Misuzu\Users\UserInfo; $authInfo = $msz->getAuthInfo(); @@ -42,7 +41,7 @@ function db_to_zip(ZipArchive $archive, UserInfo $userInfo, string $baseName, ar } $tmpName = sys_get_temp_dir() . DIRECTORY_SEPARATOR . sprintf('msz-user-data-%s-%s-%s.tmp', $userId, $baseName, XString::random(8)); - $tmpStream = FileStream::newWrite($tmpName); + $tmpHandle = fopen($tmpName, 'wb'); try { $stmt = $dbConn->prepare(sprintf('SELECT %s FROM msz_%s WHERE %s = ?', implode(', ', $fields), $baseName, $userIdField)); @@ -85,12 +84,12 @@ function db_to_zip(ZipArchive $archive, UserInfo $userInfo, string $baseName, ar $row[$fieldInfo['name']] = $fieldValue; } - $tmpStream->write(json_encode($row, JSON_INVALID_UTF8_SUBSTITUTE)); - $tmpStream->write("\n"); + fwrite($tmpHandle, json_encode($row, JSON_INVALID_UTF8_SUBSTITUTE)); + fwrite($tmpHandle, "\n"); } } finally { - $tmpStream->flush(); - $tmpStream->close(); + fflush($tmpHandle); + fclose($tmpHandle); } $archive->addFile($tmpName, $baseName . '.jsonl'); diff --git a/public-legacy/settings/sessions.php b/public-legacy/settings/sessions.php index cc5be10..ab36678 100644 --- a/public-legacy/settings/sessions.php +++ b/public-legacy/settings/sessions.php @@ -37,7 +37,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) { } if($activeSessionKilled) { - Tools::redirect($msz->getURLs()->format('index')); + Tools::redirect($msz->getUrls()->format('index')); return; } else break; } diff --git a/public/index.php b/public/index.php index fb2c82b..29a91f0 100644 --- a/public/index.php +++ b/public/index.php @@ -2,10 +2,7 @@ namespace Misuzu; use RuntimeException; -use Misuzu\Auth\AuthTokenBuilder; -use Misuzu\Auth\AuthTokenCookie; -use Misuzu\Auth\AuthTokenInfo; -use Sasae\SasaeEnvironment; +use Misuzu\Auth\{AuthTokenBuilder,AuthTokenCookie,AuthTokenInfo}; require_once __DIR__ . '/../misuzu.php'; diff --git a/src/AuditLog/AuditLog.php b/src/AuditLog/AuditLog.php index 3eefb9a..0b82baf 100644 --- a/src/AuditLog/AuditLog.php +++ b/src/AuditLog/AuditLog.php @@ -2,9 +2,7 @@ namespace Misuzu\AuditLog; use InvalidArgumentException; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; -use Index\Data\IDbResult; +use Index\Db\{DbConnection,DbStatementCache}; use Index\Net\IPAddress; use Misuzu\Pagination; use Misuzu\Users\UserInfo; @@ -12,7 +10,7 @@ use Misuzu\Users\UserInfo; class AuditLog { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/AuditLog/AuditLogInfo.php b/src/AuditLog/AuditLogInfo.php index 41f0e74..1689d72 100644 --- a/src/AuditLog/AuditLogInfo.php +++ b/src/AuditLog/AuditLogInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\AuditLog; use ValueError; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class AuditLogInfo { @@ -16,7 +16,7 @@ class AuditLogInfo { private string $country, ) {} - public static function fromResult(IDbResult $result): AuditLogInfo { + public static function fromResult(DbResult $result): AuditLogInfo { return new AuditLogInfo( userId: $result->getStringOrNull(0), action: $result->getString(1), diff --git a/src/Auth/AuthContext.php b/src/Auth/AuthContext.php index c245eed..450f00d 100644 --- a/src/Auth/AuthContext.php +++ b/src/Auth/AuthContext.php @@ -1,8 +1,8 @@ config = $config; $this->sessions = new Sessions($dbConn); $this->loginAttempts = new LoginAttempts($dbConn); diff --git a/src/Auth/AuthRpcActions.php b/src/Auth/AuthRpcActions.php index 84c1110..8296c0c 100644 --- a/src/Auth/AuthRpcActions.php +++ b/src/Auth/AuthRpcActions.php @@ -4,11 +4,11 @@ namespace Misuzu\Auth; use RuntimeException; use Misuzu\Users\{UsersContext,UserInfo}; use Aiwass\Server\{RpcActionHandler,RpcProcedure}; -use Syokuhou\IConfig; +use Index\Config\Config; final class AuthRpcActions extends RpcActionHandler { public function __construct( - private IConfig $impersonateConfig, + private Config $impersonateConfig, private UsersContext $usersCtx, private AuthContext $authCtx ) {} diff --git a/src/Auth/AuthTokenPacker.php b/src/Auth/AuthTokenPacker.php index e356288..fd9a346 100644 --- a/src/Auth/AuthTokenPacker.php +++ b/src/Auth/AuthTokenPacker.php @@ -3,7 +3,6 @@ namespace Misuzu\Auth; use RuntimeException; use Index\UriBase64; -use Index\IO\MemoryStream; class AuthTokenPacker { private const EPOCH_V2 = 1682985600; @@ -64,32 +63,40 @@ class AuthTokenPacker { $unpackTime = unpack('Nts', $timestamp); if($unpackTime === false) - throw new RuntimeException('$token does not contain a valid timestamp.'); + return AuthTokenInfo::empty(); $timestamp = $unpackTime['ts'] + self::EPOCH_V2; - $stream = MemoryStream::fromString($data); - $stream->seek(0); + $handle = fopen('php://memory', 'rb+'); + if($handle === false) + return AuthTokenInfo::empty(); - for(;;) { - $length = $stream->readChar(); - if($length === null) - break; + try { + fwrite($handle, $data); + fseek($handle, 0); - $length = ord($length); - if($length < 1) - break; + for(;;) { + $length = fgetc($handle); + if($length === false) + break; - $name = $stream->read($length); - $value = null; - $length = $stream->readChar(); - if($length !== null) { $length = ord($length); - if($length > 0) - $value = $stream->read($length); - } + if($length < 1) + break; - $builder->setProperty($name, $value); + $name = fread($handle, $length); + $value = null; + $length = fgetc($handle); + if($length !== false) { + $length = ord($length); + if($length > 0) + $value = fread($handle, $length); + } + + $builder->setProperty($name, $value); + } + } finally { + fclose($handle); } } else return AuthTokenInfo::empty(); diff --git a/src/Auth/LoginAttemptInfo.php b/src/Auth/LoginAttemptInfo.php index 21888e7..302ab31 100644 --- a/src/Auth/LoginAttemptInfo.php +++ b/src/Auth/LoginAttemptInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Auth; use Misuzu\ClientInfo; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class LoginAttemptInfo { @@ -17,7 +17,7 @@ class LoginAttemptInfo { private string $clientInfo, ) {} - public static function fromResult(IDbResult $result): LoginAttemptInfo { + public static function fromResult(DbResult $result): LoginAttemptInfo { return new LoginAttemptInfo( userId: $result->getStringOrNull(0), success: $result->getBoolean(1), diff --git a/src/Auth/LoginAttempts.php b/src/Auth/LoginAttempts.php index 6ebda9c..2eb7d9b 100644 --- a/src/Auth/LoginAttempts.php +++ b/src/Auth/LoginAttempts.php @@ -1,8 +1,7 @@ cache = new DbStatementCache($dbConn); } diff --git a/src/Auth/RecoveryTokenInfo.php b/src/Auth/RecoveryTokenInfo.php index 70b0e92..ce48a47 100644 --- a/src/Auth/RecoveryTokenInfo.php +++ b/src/Auth/RecoveryTokenInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Auth; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class RecoveryTokenInfo { @@ -13,7 +13,7 @@ class RecoveryTokenInfo { private int $created; private ?string $code; - public function __construct(IDbResult $result) { + public function __construct(DbResult $result) { $this->userId = (string)$result->getInteger(0); $this->remoteAddr = $result->getString(1); $this->created = $result->getInteger(2); diff --git a/src/Auth/RecoveryTokens.php b/src/Auth/RecoveryTokens.php index 72a255d..c2970b5 100644 --- a/src/Auth/RecoveryTokens.php +++ b/src/Auth/RecoveryTokens.php @@ -4,8 +4,7 @@ namespace Misuzu\Auth; use InvalidArgumentException; use RuntimeException; use Index\Base32; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache}; use Index\Net\IPAddress; use Misuzu\ClientInfo; use Misuzu\Pagination; @@ -14,7 +13,7 @@ use Misuzu\Users\UserInfo; class RecoveryTokens { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Auth/SessionInfo.php b/src/Auth/SessionInfo.php index 13e1ff1..e049977 100644 --- a/src/Auth/SessionInfo.php +++ b/src/Auth/SessionInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Auth; use Misuzu\ClientInfo; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class SessionInfo { @@ -22,7 +22,7 @@ class SessionInfo { private ?int $lastActive, ) {} - public static function fromResult(IDbResult $result): SessionInfo { + public static function fromResult(DbResult $result): SessionInfo { return new SessionInfo( id: $result->getString(0), userId: $result->getString(1), diff --git a/src/Auth/Sessions.php b/src/Auth/Sessions.php index 42c35e3..a65d434 100644 --- a/src/Auth/Sessions.php +++ b/src/Auth/Sessions.php @@ -4,19 +4,17 @@ namespace Misuzu\Auth; use InvalidArgumentException; use RuntimeException; use Index\XString; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Index\Net\IPAddress; use Misuzu\ClientInfo; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class Sessions { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Auth/TwoFactorAuthSessions.php b/src/Auth/TwoFactorAuthSessions.php index afafd7c..ca0d33d 100644 --- a/src/Auth/TwoFactorAuthSessions.php +++ b/src/Auth/TwoFactorAuthSessions.php @@ -2,14 +2,13 @@ namespace Misuzu\Auth; use Index\XString; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache}; use Misuzu\Users\UserInfo; class TwoFactorAuthSessions { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/CSRF.php b/src/CSRF.php index d4e065f..ffaab08 100644 --- a/src/CSRF.php +++ b/src/CSRF.php @@ -1,19 +1,19 @@ getString(0), userId: $result->getStringOrNull(1), diff --git a/src/Changelog/ChangeTagInfo.php b/src/Changelog/ChangeTagInfo.php index 3ad14a0..0ad2c7a 100644 --- a/src/Changelog/ChangeTagInfo.php +++ b/src/Changelog/ChangeTagInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Changelog; use Stringable; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ChangeTagInfo implements Stringable { private string $id; @@ -13,7 +13,7 @@ class ChangeTagInfo implements Stringable { private int $archived; private int $changes; - public function __construct(IDbResult $result) { + public function __construct(DbResult $result) { $this->id = (string)$result->getInteger(0); $this->name = $result->getString(1); $this->description = $result->getString(2); diff --git a/src/Changelog/Changelog.php b/src/Changelog/Changelog.php index f663415..f9edfad 100644 --- a/src/Changelog/Changelog.php +++ b/src/Changelog/Changelog.php @@ -4,10 +4,7 @@ namespace Misuzu\Changelog; use InvalidArgumentException; use RuntimeException; use DateTimeInterface; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; -use Index\Data\IDbResult; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; @@ -15,12 +12,12 @@ class Changelog { // not a strict list but useful to have public const ACTIONS = ['add', 'remove', 'update', 'fix', 'import', 'revert']; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; private array $tags = []; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Changelog/ChangelogRoutes.php b/src/Changelog/ChangelogRoutes.php index 0cdd9f0..18c23d6 100644 --- a/src/Changelog/ChangelogRoutes.php +++ b/src/Changelog/ChangelogRoutes.php @@ -3,18 +3,20 @@ namespace Misuzu\Changelog; use ErrorException; use RuntimeException; -use Index\Http\Routing\{HttpGet,RouteHandler}; +use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait}; +use Index\Syndication\FeedBuilder; +use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait}; use Misuzu\{Pagination,SiteInfo,Template}; use Misuzu\Auth\AuthInfo; use Misuzu\Comments\{Comments,CommentsEx}; -use Misuzu\Feeds\{Feed,FeedItem,AtomFeedSerializer,RssFeedSerializer}; -use Misuzu\URLs\{URLInfo,URLRegistry}; use Misuzu\Users\UsersContext; -final class ChangelogRoutes extends RouteHandler { +final class ChangelogRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; + public function __construct( private SiteInfo $siteInfo, - private URLRegistry $urls, + private UrlRegistry $urls, private Changelog $changelog, private UsersContext $usersCtx, private AuthInfo $authInfo, @@ -27,7 +29,7 @@ final class ChangelogRoutes extends RouteHandler { } #[HttpGet('/changelog')] - #[URLInfo('changelog-index', '/changelog', ['date' => '', 'user' => '', 'tags' => '', 'p' => ''])] + #[UrlFormat('changelog-index', '/changelog', ['date' => '', 'user' => '', 'tags' => '', 'p' => ''])] public function getIndex($response, $request) { $filterDate = (string)$request->getParam('date'); $filterUser = (string)$request->getParam('user', FILTER_SANITIZE_NUMBER_INT); @@ -96,8 +98,8 @@ final class ChangelogRoutes extends RouteHandler { } #[HttpGet('/changelog/change/([0-9]+)')] - #[URLInfo('changelog-change', '/changelog/change/')] - #[URLInfo('changelog-change-comments', '/changelog/change/', fragment: 'comments')] + #[UrlFormat('changelog-change', '/changelog/change/')] + #[UrlFormat('changelog-change-comments', '/changelog/change/', fragment: 'comments')] public function getChange($response, $request, string $changeId) { try { $changeInfo = $this->changelog->getChange($changeId); @@ -117,44 +119,29 @@ final class ChangelogRoutes extends RouteHandler { ]); } - private function createFeed(string $feedMode): Feed { + #[HttpGet('/changelog.(xml|rss|atom)')] + #[UrlFormat('changelog-feed', '/changelog.xml')] + public function getFeed($response) { + $response->setContentType('application/rss+xml; charset=utf-8'); + $siteName = $this->siteInfo->getName(); + $siteUrl = $this->siteInfo->getURL(); $changes = $this->changelog->getChanges(pagination: new Pagination(10)); - $feed = (new Feed) - ->setTitle($siteName . ' » Changelog') - ->setDescription('Live feed of changes to ' . $siteName . '.') - ->setContentUrl($this->siteInfo->getURL() . $this->urls->format('changelog-index')) - ->setFeedUrl($this->siteInfo->getURL() . $this->urls->format("changelog-feed-{$feedMode}")); + $feed = new FeedBuilder; + $feed->setTitle(sprintf('%s » Changelog', $siteName)); + $feed->setDescription(sprintf('Live feed of changes to %s.', $siteName)); + $feed->setContentUrl($siteUrl . $this->urls->format('changelog-index')); + $feed->setFeedUrl($siteUrl . $this->urls->format('changelog-feed')); - foreach($changes as $change) { - $changeUrl = $this->siteInfo->getURL() . $this->urls->format('changelog-change', ['change' => $change->getId()]); - $commentsUrl = $this->siteInfo->getURL() . $this->urls->format('changelog-change-comments', ['change' => $change->getId()]); + foreach($changes as $change) + $feed->createEntry(function($item) use ($change, $siteUrl) { + $item->setTitle(sprintf('%s: %s', $change->getActionText(), $change->getSummary())); + $item->setCreatedAt($change->getCreatedTime()); + $item->setContentUrl($siteUrl . $this->urls->format('changelog-change', ['change' => $change->getId()])); + $item->setCommentsUrl($siteUrl . $this->urls->format('changelog-change-comments', ['change' => $change->getId()])); + }); - $feedItem = (new FeedItem) - ->setTitle($change->getActionText() . ': ' . $change->getSummary()) - ->setCreationDate($change->getCreatedTime()) - ->setUniqueId($changeUrl) - ->setContentUrl($changeUrl) - ->setCommentsUrl($commentsUrl); - - $feed->addItem($feedItem); - } - - return $feed; - } - - #[HttpGet('/changelog.rss')] - #[URLInfo('changelog-feed-rss', '/changelog.rss')] - public function getFeedRSS($response) { - $response->setContentType('application/rss+xml; charset=utf-8'); - return (new RssFeedSerializer)->serializeFeed($this->createFeed('rss')); - } - - #[HttpGet('/changelog.atom')] - #[URLInfo('changelog-feed-atom', '/changelog.atom')] - public function getFeedAtom($response) { - $response->setContentType('application/atom+xml; charset=utf-8'); - return (new AtomFeedSerializer)->serializeFeed($this->createFeed('atom')); + return $feed->toXmlString(); } } diff --git a/src/Comments/Comments.php b/src/Comments/Comments.php index 6e091e7..df0e14e 100644 --- a/src/Comments/Comments.php +++ b/src/Comments/Comments.php @@ -3,17 +3,15 @@ namespace Misuzu\Comments; use InvalidArgumentException; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; -use Index\Data\IDbResult; +use Index\Db\{DbConnection,DbStatementCache}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class Comments { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Comments/CommentsCategoryInfo.php b/src/Comments/CommentsCategoryInfo.php index afd2df7..1c29ba0 100644 --- a/src/Comments/CommentsCategoryInfo.php +++ b/src/Comments/CommentsCategoryInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Comments; use Misuzu\Users\UserInfo; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class CommentsCategoryInfo { public function __construct( @@ -15,7 +15,7 @@ class CommentsCategoryInfo { private int $comments, ) {} - public static function fromResult(IDbResult $result): CommentsCategoryInfo { + public static function fromResult(DbResult $result): CommentsCategoryInfo { return new CommentsCategoryInfo( id: $result->getString(0), name: $result->getString(1), diff --git a/src/Comments/CommentsPostInfo.php b/src/Comments/CommentsPostInfo.php index c3e811a..997a1a1 100644 --- a/src/Comments/CommentsPostInfo.php +++ b/src/Comments/CommentsPostInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Comments; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class CommentsPostInfo { public function __construct( diff --git a/src/Comments/CommentsPostVoteInfo.php b/src/Comments/CommentsPostVoteInfo.php index 4a48a45..250d2c5 100644 --- a/src/Comments/CommentsPostVoteInfo.php +++ b/src/Comments/CommentsPostVoteInfo.php @@ -1,14 +1,14 @@ commentId = (string)$result->getInteger(0); $this->userId = (string)$result->getInteger(1); $this->weight = $result->getInteger(2); diff --git a/src/Counters/CounterInfo.php b/src/Counters/CounterInfo.php index 66967b6..980c782 100644 --- a/src/Counters/CounterInfo.php +++ b/src/Counters/CounterInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Counters; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class CounterInfo { public function __construct( @@ -11,7 +11,7 @@ class CounterInfo { private int $updated, ) {} - public static function fromResult(IDbResult $result): CounterInfo { + public static function fromResult(DbResult $result): CounterInfo { return new CounterInfo( name: $result->getString(0), value: $result->getInteger(1), diff --git a/src/Counters/Counters.php b/src/Counters/Counters.php index 858551b..fb3d65a 100644 --- a/src/Counters/Counters.php +++ b/src/Counters/Counters.php @@ -2,9 +2,7 @@ namespace Misuzu\Counters; use InvalidArgumentException; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; // insert increment and decrement calls in places someday @@ -12,7 +10,7 @@ use Misuzu\Pagination; class Counters { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Emoticons/EmoteInfo.php b/src/Emoticons/EmoteInfo.php index 576aa2b..0e8a003 100644 --- a/src/Emoticons/EmoteInfo.php +++ b/src/Emoticons/EmoteInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Emoticons; use Stringable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class EmoteInfo implements Stringable { public function __construct( @@ -12,7 +12,7 @@ class EmoteInfo implements Stringable { private string $url, ) {} - public static function fromResult(IDbResult $result): EmoteInfo { + public static function fromResult(DbResult $result): EmoteInfo { return new EmoteInfo( id: $result->getString(0), order: $result->getInteger(1), diff --git a/src/Emoticons/EmoteStringInfo.php b/src/Emoticons/EmoteStringInfo.php index 42b002a..f1f8b35 100644 --- a/src/Emoticons/EmoteStringInfo.php +++ b/src/Emoticons/EmoteStringInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Emoticons; use Stringable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class EmoteStringInfo implements Stringable { public function __construct( @@ -11,7 +11,7 @@ class EmoteStringInfo implements Stringable { private string $string, ) {} - public static function fromResult(IDbResult $result): EmoteStringInfo { + public static function fromResult(DbResult $result): EmoteStringInfo { return new EmoteStringInfo( emoteId: $result->getString(0), order: $result->getInteger(1), diff --git a/src/Emoticons/Emotes.php b/src/Emoticons/Emotes.php index 766fb17..26f5df9 100644 --- a/src/Emoticons/Emotes.php +++ b/src/Emoticons/Emotes.php @@ -3,8 +3,7 @@ namespace Misuzu\Emoticons; use InvalidArgumentException; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache}; class Emotes { private const EMOTE_ORDER = [ @@ -13,10 +12,10 @@ class Emotes { 'rank' => 'emote_hierarchy', ]; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Feeds/AtomFeedSerializer.php b/src/Feeds/AtomFeedSerializer.php deleted file mode 100644 index 2905293..0000000 --- a/src/Feeds/AtomFeedSerializer.php +++ /dev/null @@ -1,117 +0,0 @@ -appendChild($document->createElement('feed')); - if($atom instanceof DOMElement) - $atom->setAttribute('xmlns', 'http://www.w3.org/2005/Atom'); - - $atom->appendChild( - $document->createElement( - 'id', - $feed->hasContentUrl() - ? $this->cleanString($feed->getContentUrl()) - : time() - ) - ); - - return $atom; - } - - protected function createTitle(DOMDocument $document, string $title): DOMNode { - return $document->createElement('title', $this->cleanString($title)); - } - - protected function createDescription(DOMDocument $document, string $description): ?DOMNode { - return $document->createElement('subtitle', $this->cleanString($description)); - } - - protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode { - return $document->createElement('updated', $this->formatTime($lastUpdate)); - } - - protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode { - $link = $document->createElement('link'); - $link->setAttribute('href', $this->cleanString($contentUrl)); - return $link; - } - - protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode { - $link = $document->createElement('link'); - $link->setAttribute('href', $this->cleanString($feedUrl)); - $link->setAttribute('ref', 'self'); - return $link; - } - - protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode { - $elem = $document->createElement('entry'); - - $elem->appendChild( - $document->createElement( - 'id', - $feedItem->hasContentUrl() - ? $this->cleanString($feedItem->getContentUrl()) - : time() - ) - ); - - return $elem; - } - - protected function createItemTitle(DOMDocument $document, string $title): DOMNode { - return $document->createElement('title', $this->cleanString($title)); - } - - protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode { - return $document->createElement('summary', $this->cleanString($summary)); - } - - protected function createItemContent(DOMDocument $document, string $content): ?DOMNode { - $elem = $document->createElement('content', $this->cleanString($content)); - $elem->setAttribute('type', 'html'); - return $elem; - } - - protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode { - return $document->createElement('updated', $this->formatTime($creationDate)); - } - - protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode { - return null; - } - - protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode { - $elem = $document->createElement('link'); - $elem->setAttribute('href', $this->cleanString($contentUrl)); - $elem->setAttribute('type', 'text/html'); - return $elem; - } - - protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode { - return null; - } - - protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode { - if(empty($authorName) && empty($authorUrl)) - return null; - - $elem = $document->createElement('author'); - - if(!empty($authorName)) - $elem->appendChild($document->createElement('name', $this->cleanString($authorName))); - - if(!empty($authorUrl)) - $elem->appendChild($document->createElement('uri', $this->cleanString($authorUrl))); - - return $elem; - } -} diff --git a/src/Feeds/Feed.php b/src/Feeds/Feed.php deleted file mode 100644 index ad59392..0000000 --- a/src/Feeds/Feed.php +++ /dev/null @@ -1,74 +0,0 @@ -title; - } - public function setTitle(string $title): self { - $this->title = $title; - return $this; - } - - public function getDescription(): string { - return $this->description ?? ''; - } - public function hasDescription(): bool { - return isset($this->description); - } - public function setDescription(?string $description): self { - $this->description = $description; - return $this; - } - - public function getLastUpdate(): int { - return $this->lastUpdate ?? 0; - } - public function hasLastUpdate(): bool { - return isset($this->lastUpdate); - } - public function setLastUpdate(?int $lastUpdate): self { - $this->lastUpdate = $lastUpdate; - return $this; - } - - public function getContentUrl(): string { - return $this->contentUrl ?? ''; - } - public function hasContentUrl(): bool { - return isset($this->contentUrl); - } - public function setContentUrl(?string $contentUrl): self { - $this->contentUrl = $contentUrl; - return $this; - } - - public function getFeedUrl(): string { - return $this->feedUrl ?? ''; - } - public function hasFeedUrl(): bool { - return isset($this->feedUrl); - } - public function setFeedUrl(?string $feedUrl): self { - $this->feedUrl = $feedUrl; - return $this; - } - - public function getItems(): array { - return $this->feedItems; - } - public function hasItems(): bool { - return count($this->feedItems) > 0; - } - public function addItem(FeedItem $item): self { - $this->feedItems[] = $item; - return $this; - } -} diff --git a/src/Feeds/FeedItem.php b/src/Feeds/FeedItem.php deleted file mode 100644 index 34d8e6d..0000000 --- a/src/Feeds/FeedItem.php +++ /dev/null @@ -1,110 +0,0 @@ -title; - } - public function setTitle(string $title): self { - $this->title = $title; - return $this; - } - - public function getSummary(): string { - return $this->summary ?? ''; - } - public function hasSummary(): bool { - return isset($this->summary); - } - public function setSummary(?string $summary): self { - $this->summary = $summary; - return $this; - } - - public function getContent(): string { - return $this->content ?? ''; - } - public function hasContent(): bool { - return isset($this->content); - } - public function setContent(?string $content): self { - $this->content = $content; - return $this; - } - - public function getCreationDate(): int { - return $this->creationDate; - } - public function hasCreationDate(): bool { - return isset($this->creationDate); - } - public function setCreationDate(?int $creationDate): self { - $this->creationDate = $creationDate; - return $this; - } - - public function getUniqueId(): string { - return $this->uniqueId ?? ''; - } - public function hasUniqueId(): bool { - return isset($this->uniqueId); - } - public function setUniqueId(?string $uniqueId): self { - $this->uniqueId = $uniqueId; - return $this; - } - - public function getContentUrl(): string { - return $this->contentUrl ?? ''; - } - public function hasContentUrl(): bool { - return isset($this->contentUrl); - } - public function setContentUrl(?string $contentUrl): self { - $this->contentUrl = $contentUrl; - return $this; - } - - public function getCommentsUrl(): string { - return $this->commentsUrl ?? ''; - } - public function hasCommentsUrl(): bool { - return isset($this->commentsUrl); - } - public function setCommentsUrl(?string $commentsUrl): self { - $this->commentsUrl = $commentsUrl; - return $this; - } - - public function getAuthorName(): string { - return $this->authorName ?? ''; - } - public function hasAuthorName(): bool { - return isset($this->authorName); - } - public function setAuthorName(?string $authorName): self { - $this->authorName = $authorName; - return $this; - } - - public function getAuthorUrl(): string { - return $this->authorUrl ?? ''; - } - public function hasAuthorUrl(): bool { - return isset($this->authorUrl); - } - public function setAuthorUrl(?string $authorUrl): self { - $this->authorUrl = $authorUrl; - return $this; - } -} diff --git a/src/Feeds/FeedSerializer.php b/src/Feeds/FeedSerializer.php deleted file mode 100644 index 6595b76..0000000 --- a/src/Feeds/FeedSerializer.php +++ /dev/null @@ -1,6 +0,0 @@ -appendChild($document->createElement('rss')); - if($rss instanceof DOMElement) { - $rss->setAttribute('version', '2.0'); - $rss->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom'); - } - - $channel = $rss->appendChild($document->createElement('channel')); - $channel->appendChild($document->createElement('ttl', '900')); - return $channel; - } - - protected function createTitle(DOMDocument $document, string $title): DOMNode { - return $document->createElement('title', $this->cleanString($title)); - } - - protected function createDescription(DOMDocument $document, string $description): ?DOMNode { - return $document->createElement('description', $this->cleanString($description)); - } - - protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode { - return $document->createElement('pubDate', $this->formatTime($lastUpdate)); - } - - protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode { - return $document->createElement('link', $this->cleanString($contentUrl)); - } - - protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode { - $link = $document->createElement('atom:link'); - $link->setAttribute('href', $this->cleanString($feedUrl)); - $link->setAttribute('ref', 'self'); - return $link; - } - - protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode { - return $document->createElement('item'); - } - - protected function createItemTitle(DOMDocument $document, string $title): DOMNode { - return $document->createElement('title', $this->cleanString($title)); - } - - protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode { - return $document->createElement('description', $this->cleanString($summary)); - } - - protected function createItemContent(DOMDocument $document, string $content): ?DOMNode { - return null; - } - - protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode { - return $document->createElement('pubDate', $this->formatTime($creationDate)); - } - - protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode { - $elem = $document->createElement('guid', $uniqueId); - $elem->setAttribute('isPermaLink', 'true'); - return $elem; - } - - protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode { - return $document->createElement('link', $contentUrl); - } - - protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode { - return $document->createElement('comments', $commentsUrl); - } - - protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode { - return null; - } -} diff --git a/src/Feeds/XmlFeedSerializer.php b/src/Feeds/XmlFeedSerializer.php deleted file mode 100644 index c7236a6..0000000 --- a/src/Feeds/XmlFeedSerializer.php +++ /dev/null @@ -1,79 +0,0 @@ -createRoot($document, $feed); - $root->appendChild($this->createTitle($document, $feed->getTitle())); - - if($feed->hasDescription()) - self::appendChild($root, $this->createDescription($document, $feed->getDescription())); - if($feed->hasLastUpdate()) - self::appendChild($root, $this->createLastUpdate($document, $feed->getLastUpdate())); - if($feed->hasContentUrl()) - self::appendChild($root, $this->createContentUrl($document, $feed->getContentUrl())); - if($feed->hasFeedUrl()) - self::appendChild($root, $this->createFeedUrl($document, $feed->getFeedUrl())); - - if($feed->hasItems()) { - foreach($feed->getItems() as $item) { - $root->appendChild($this->serializeFeedItem($document, $item)); - } - } - - return $document->saveXML(); - } - - private function serializeFeedItem(DOMDocument $document, FeedItem $feedItem): DOMNode { - $elem = $this->createItem($document, $feedItem); - $elem->appendChild($this->createItemTitle($document, $feedItem->getTitle())); - - if($feedItem->hasSummary()) - self::appendChild($elem, $this->createItemSummary($document, $feedItem->getSummary())); - if($feedItem->hasContent()) - self::appendChild($elem, $this->createItemContent($document, $feedItem->getContent())); - if($feedItem->hasCreationDate()) - self::appendChild($elem, $this->createItemCreationDate($document, $feedItem->getCreationDate())); - if($feedItem->hasUniqueId()) - self::appendChild($elem, $this->createItemUniqueId($document, $feedItem->getUniqueId())); - if($feedItem->hasContentUrl()) - self::appendChild($elem, $this->createItemContentUrl($document, $feedItem->getContentUrl())); - if($feedItem->hasCommentsUrl()) - self::appendChild($elem, $this->createItemCommentsUrl($document, $feedItem->getCommentsUrl())); - if($feedItem->hasAuthorName() || $feedItem->hasAuthorUrl()) - self::appendChild($elem, $this->createItemAuthor($document, $feedItem->getAuthorName(), $feedItem->getAuthorUrl())); - - return $elem; - } - - protected function cleanString(string $string): string { - return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT | ENT_SUBSTITUTE); - } - - protected static function appendChild(DOMNode $parent, ?DOMNode $elem): ?DOMNode { - if($elem !== null) - return $parent->appendChild($elem); - return $elem; - } - - abstract protected function formatTime(int $time): string; - abstract protected function createRoot(DOMDocument $document, Feed $feed): DOMNode; - abstract protected function createTitle(DOMDocument $document, string $title): DOMNode; - abstract protected function createDescription(DOMDocument $document, string $description): ?DOMNode; - abstract protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode; - abstract protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode; - abstract protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode; - abstract protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode; - abstract protected function createItemTitle(DOMDocument $document, string $title): DOMNode; - abstract protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode; - abstract protected function createItemContent(DOMDocument $document, string $content): ?DOMNode; - abstract protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode; - abstract protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode; - abstract protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode; - abstract protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode; - abstract protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode; -} diff --git a/src/Forum/ForumCategories.php b/src/Forum/ForumCategories.php index d8d4def..95d304f 100644 --- a/src/Forum/ForumCategories.php +++ b/src/Forum/ForumCategories.php @@ -5,16 +5,14 @@ use InvalidArgumentException; use RuntimeException; use stdClass; use Index\Colour\Colour; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class ForumCategories { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Forum/ForumCategoryInfo.php b/src/Forum/ForumCategoryInfo.php index 8925921..822d684 100644 --- a/src/Forum/ForumCategoryInfo.php +++ b/src/Forum/ForumCategoryInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Forum; use Carbon\CarbonImmutable; use Index\Colour\Colour; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ForumCategoryInfo { // should the types just be replaced with flags indicating what's allowed? @@ -44,7 +44,7 @@ class ForumCategoryInfo { private int $postsCount, ) {} - public static function fromResult(IDbResult $result): ForumCategoryInfo { + public static function fromResult(DbResult $result): ForumCategoryInfo { return new ForumCategoryInfo( id: $result->getString(0), order: $result->getInteger(1), diff --git a/src/Forum/ForumContext.php b/src/Forum/ForumContext.php index 1427248..e361e62 100644 --- a/src/Forum/ForumContext.php +++ b/src/Forum/ForumContext.php @@ -2,7 +2,7 @@ namespace Misuzu\Forum; use stdClass; -use Index\Data\IDbConnection; +use Index\Db\DbConnection; use Misuzu\Users\UserInfo; class ForumContext { @@ -14,7 +14,7 @@ class ForumContext { private array $totalUserTopics = []; private array $totalUserPosts = []; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->categories = new ForumCategories($dbConn); $this->topics = new ForumTopics($dbConn); $this->topicRedirects = new ForumTopicRedirects($dbConn); diff --git a/src/Forum/ForumPostInfo.php b/src/Forum/ForumPostInfo.php index 85d4014..a41fff6 100644 --- a/src/Forum/ForumPostInfo.php +++ b/src/Forum/ForumPostInfo.php @@ -4,7 +4,7 @@ namespace Misuzu\Forum; use Misuzu\Parsers\Parser; use Carbon\CarbonImmutable; use Index\XDateTime; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class ForumPostInfo { @@ -22,7 +22,7 @@ class ForumPostInfo { private ?int $deleted, ) {} - public static function fromResult(IDbResult $result): ForumPostInfo { + public static function fromResult(DbResult $result): ForumPostInfo { return new ForumPostInfo( id: $result->getString(0), topicId: $result->getString(1), diff --git a/src/Forum/ForumPosts.php b/src/Forum/ForumPosts.php index 7fe4e8a..e9c0527 100644 --- a/src/Forum/ForumPosts.php +++ b/src/Forum/ForumPosts.php @@ -5,18 +5,16 @@ use InvalidArgumentException; use RuntimeException; use stdClass; use Carbon\CarbonImmutable; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Index\Net\IPAddress; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class ForumPosts { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Forum/ForumTopicInfo.php b/src/Forum/ForumTopicInfo.php index 2376af6..2278dcb 100644 --- a/src/Forum/ForumTopicInfo.php +++ b/src/Forum/ForumTopicInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Forum; use Carbon\CarbonImmutable; use Index\XDateTime; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ForumTopicInfo { public const TYPE_DISCUSSION = 0; @@ -33,7 +33,7 @@ class ForumTopicInfo { private ?int $locked, ) {} - public static function fromResult(IDbResult $result): ForumTopicInfo { + public static function fromResult(DbResult $result): ForumTopicInfo { return new ForumTopicInfo( id: $result->getString(0), categoryId: $result->getString(1), diff --git a/src/Forum/ForumTopicRedirectInfo.php b/src/Forum/ForumTopicRedirectInfo.php index 74aeeae..4e42f1a 100644 --- a/src/Forum/ForumTopicRedirectInfo.php +++ b/src/Forum/ForumTopicRedirectInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Forum; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ForumTopicRedirectInfo { public function __construct( @@ -12,7 +12,7 @@ class ForumTopicRedirectInfo { private int $created, ) {} - public static function fromResult(IDbResult $result): ForumTopicRedirectInfo { + public static function fromResult(DbResult $result): ForumTopicRedirectInfo { return new ForumTopicRedirectInfo( topicId: $result->getString(0), userId: $result->getStringOrNull(1), diff --git a/src/Forum/ForumTopicRedirects.php b/src/Forum/ForumTopicRedirects.php index 7104952..e0e8fa3 100644 --- a/src/Forum/ForumTopicRedirects.php +++ b/src/Forum/ForumTopicRedirects.php @@ -2,15 +2,14 @@ namespace Misuzu\Forum; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class ForumTopicRedirects { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Forum/ForumTopics.php b/src/Forum/ForumTopics.php index a274789..bbf869c 100644 --- a/src/Forum/ForumTopics.php +++ b/src/Forum/ForumTopics.php @@ -4,17 +4,15 @@ namespace Misuzu\Forum; use InvalidArgumentException; use RuntimeException; use stdClass; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class ForumTopics { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Hanyuu/HanyuuRpcActions.php b/src/Hanyuu/HanyuuRpcActions.php index 7f4cb2c..3e4fac6 100644 --- a/src/Hanyuu/HanyuuRpcActions.php +++ b/src/Hanyuu/HanyuuRpcActions.php @@ -4,17 +4,17 @@ namespace Misuzu\Hanyuu; use RuntimeException; use Misuzu\CSRF; use Misuzu\Auth\AuthContext; -use Misuzu\URLs\URLRegistry; use Misuzu\Users\{UsersContext,UserInfo}; use Aiwass\Server\{RpcActionHandler,RpcProcedure}; use Index\Colour\Colour; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Urls\UrlRegistry; final class HanyuuRpcActions extends RpcActionHandler { public function __construct( private $getBaseUrl, - private IConfig $impersonateConfig, - private URLRegistry $urls, + private Config $impersonateConfig, + private UrlRegistry $urls, private UsersContext $usersCtx, private AuthContext $authCtx ) {} diff --git a/src/Home/HomeRoutes.php b/src/Home/HomeRoutes.php index 6fa9807..0e2c857 100644 --- a/src/Home/HomeRoutes.php +++ b/src/Home/HomeRoutes.php @@ -3,22 +3,24 @@ namespace Misuzu\Home; use RuntimeException; use Index\XDateTime; -use Index\Data\{DbTools,IDbConnection}; -use Index\Http\Routing\{HttpGet,RouteHandler}; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Db\{DbConnection,DbTools}; +use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait}; +use Index\Urls\{UrlFormat,UrlSource,UrlSourceTrait}; use Misuzu\{Pagination,SiteInfo,Template}; use Misuzu\Auth\AuthInfo; use Misuzu\Changelog\Changelog; use Misuzu\Comments\Comments; use Misuzu\Counters\Counters; use Misuzu\News\News; -use Misuzu\URLs\URLInfo; use Misuzu\Users\UsersContext; -class HomeRoutes extends RouteHandler { +class HomeRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; + public function __construct( - private IConfig $config, - private IDbConnection $dbConn, + private Config $config, + private DbConnection $dbConn, private SiteInfo $siteInfo, private AuthInfo $authInfo, private Changelog $changelog, @@ -151,7 +153,7 @@ class HomeRoutes extends RouteHandler { } #[HttpGet('/')] - #[URLInfo('index', '/')] + #[UrlFormat('index', '/')] public function getIndex(...$args) { return $this->authInfo->isLoggedIn() ? $this->getHome(...$args) diff --git a/src/Info/InfoRoutes.php b/src/Info/InfoRoutes.php index 3cd57e8..c957487 100644 --- a/src/Info/InfoRoutes.php +++ b/src/Info/InfoRoutes.php @@ -1,12 +1,14 @@ MSZ_ROOT, @@ -18,14 +20,14 @@ class InfoRoutes extends RouteHandler { ]; #[HttpGet('/info')] - #[URLInfo('info-index', '/info')] + #[UrlFormat('info-index', '/info')] public function getIndex() { return Template::renderRaw('info.index'); } #[HttpGet('/info/([A-Za-z0-9_]+)')] - #[URLInfo('info', '/info/')] - #[URLInfo('info-doc', '/info/<title>')] + #[UrlFormat('info', '/info/<title>')] + #[UrlFormat('info-doc', '/info/<title>')] public function getDocsPage($response, $request, string $name) { return $this->serveMarkdownDocument( sprintf('%s/%s.md', self::DOCS_PATH, $name) @@ -71,7 +73,7 @@ class InfoRoutes extends RouteHandler { } #[HttpGet('/info/([A-Za-z0-9_]+)/([A-Za-z0-9_]+)')] - #[URLInfo('info-project-doc', '/info/<project>/<title>')] + #[UrlFormat('info-project-doc', '/info/<project>/<title>')] public function getProjectPage($response, $request, string $project, string $name) { if(!array_key_exists($project, self::PROJECT_PATHS)) return 404; diff --git a/src/LegacyRoutes.php b/src/LegacyRoutes.php index a9ac8eb..2e5cf1a 100644 --- a/src/LegacyRoutes.php +++ b/src/LegacyRoutes.php @@ -1,15 +1,17 @@ <?php namespace Misuzu; -use Index\Http\Routing\{HttpGet,RouteHandler}; -use Misuzu\URLs\{IURLSource,URLInfo,URLRegistry}; +use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait}; +use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait}; + +class LegacyRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; -class LegacyRoutes extends RouteHandler implements IURLSource { public function __construct( - private URLRegistry $urls + private UrlRegistry $urls ) {} - public function registerURLs(URLRegistry $urls): void { + public function registerUrls(UrlRegistry $urls): void { // eventually this should be handled by context classes $urls->register('search-index', '/search.php'); $urls->register('search-query', '/search.php', ['q' => '<query>'], '<section>'); @@ -156,20 +158,6 @@ class LegacyRoutes extends RouteHandler implements IURLSource { $response->redirect($location, true); } - #[HttpGet('/news.php/rss')] - public function getNewsRssPHP($response, $request): void { - $catId = (int)$request->getParam('c', FILTER_SANITIZE_NUMBER_INT); - $location = $this->urls->format($catId > 0 ? 'news-category-feed-rss' : 'news-feed-rss', ['category' => $catId]); - $response->redirect($location, true); - } - - #[HttpGet('/news.php/atom')] - public function getNewsAtomPHP($response, $request): void { - $catId = (int)$request->getParam('c', FILTER_SANITIZE_NUMBER_INT); - $location = $this->urls->format($catId > 0 ? 'news-category-feed-atom' : 'news-feed-atom', ['category' => $catId]); - $response->redirect($location, true); - } - #[HttpGet('/news/index.php')] public function getNewsIndexPHP($response, $request): void { $response->redirect($this->urls->format('news-index', [ @@ -192,25 +180,15 @@ class LegacyRoutes extends RouteHandler implements IURLSource { ]), true); } + #[HttpGet('/news.php/rss')] + #[HttpGet('/news.php/atom')] #[HttpGet('/news/feed.php')] - public function getNewsFeedPHP($response, $request): int { - return 400; - } - #[HttpGet('/news/feed.php/rss')] - public function getNewsFeedRssPHP($response, $request): void { - $catId = (int)$request->getParam('c', FILTER_SANITIZE_NUMBER_INT); - $response->redirect($this->urls->format( - $catId > 0 ? 'news-category-feed-rss' : 'news-feed-rss', - ['category' => $catId] - ), true); - } - #[HttpGet('/news/feed.php/atom')] - public function getNewsFeedAtomPHP($response, $request): void { + public function getNewsFeedPHP($response, $request): void { $catId = (int)$request->getParam('c', FILTER_SANITIZE_NUMBER_INT); $response->redirect($this->urls->format( - $catId > 0 ? 'news-category-feed-atom' : 'news-feed-atom', + $catId > 0 ? 'news-category-feed' : 'news-feed', ['category' => $catId] ), true); } @@ -262,7 +240,7 @@ class LegacyRoutes extends RouteHandler implements IURLSource { } #[HttpGet('/manage')] - #[URLInfo('manage-index', '/manage')] + #[UrlFormat('manage-index', '/manage')] public function getManageIndex($response): void { $response->redirect($this->urls->format('manage-general-overview')); } diff --git a/src/Mailer.php b/src/Mailer.php index 27105fa..2c11a18 100644 --- a/src/Mailer.php +++ b/src/Mailer.php @@ -2,7 +2,7 @@ namespace Misuzu; use InvalidArgumentException; -use Syokuhou\IConfig; +use Index\Config\Config; use Symfony\Component\Mime\Email as SymfonyMessage; use Symfony\Component\Mime\Address as SymfonyAddress; use Symfony\Component\Mailer\Transport as SymfonyTransport; @@ -10,10 +10,10 @@ use Symfony\Component\Mailer\Transport as SymfonyTransport; final class Mailer { private const TEMPLATE_PATH = MSZ_ROOT . '/config/emails/%s.txt'; - private static IConfig $config; + private static Config $config; private static $transport = null; - public static function init(IConfig $config): void { + public static function init(Config $config): void { self::$config = $config; } diff --git a/src/Messages/MessageInfo.php b/src/Messages/MessageInfo.php index 60c96a1..caa804e 100644 --- a/src/Messages/MessageInfo.php +++ b/src/Messages/MessageInfo.php @@ -3,7 +3,7 @@ namespace Misuzu\Messages; use Misuzu\Parsers\Parser; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class MessageInfo { public function __construct( @@ -21,7 +21,7 @@ class MessageInfo { private ?int $deleted, ) {} - public static function fromResult(IDbResult $result): MessageInfo { + public static function fromResult(DbResult $result): MessageInfo { return new MessageInfo( messageId: $result->getString(0), ownerId: $result->getString(1), diff --git a/src/Messages/MessagesContext.php b/src/Messages/MessagesContext.php index 10d4500..f1144cb 100644 --- a/src/Messages/MessagesContext.php +++ b/src/Messages/MessagesContext.php @@ -1,11 +1,12 @@ <?php namespace Misuzu\Messages; -use Index\Data\IDbConnection; +use Index\Db\DbConnection; + class MessagesContext { private MessagesDatabase $database; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->database = new MessagesDatabase($dbConn); } diff --git a/src/Messages/MessagesDatabase.php b/src/Messages/MessagesDatabase.php index a3b0ce4..c634fb7 100644 --- a/src/Messages/MessagesDatabase.php +++ b/src/Messages/MessagesDatabase.php @@ -4,14 +4,14 @@ namespace Misuzu\Messages; use InvalidArgumentException; use RuntimeException; use DateTimeInterface; -use Index\Data\{DbStatementCache,DbTools,IDbConnection}; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; use Misuzu\Users\UserInfo; class MessagesDatabase { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Messages/MessagesRoutes.php b/src/Messages/MessagesRoutes.php index b6d4085..0a98464 100644 --- a/src/Messages/MessagesRoutes.php +++ b/src/Messages/MessagesRoutes.php @@ -5,16 +5,18 @@ use stdClass; use InvalidArgumentException; use RuntimeException; use Index\XString; -use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler}; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerTrait}; +use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait}; use Misuzu\{CSRF,Pagination,Perm,Template}; use Misuzu\Auth\AuthInfo; use Misuzu\Parsers\Parser; use Misuzu\Perms\Permissions; -use Misuzu\URLs\{URLInfo,URLRegistry}; use Misuzu\Users\{UsersContext,UserInfo}; -class MessagesRoutes extends RouteHandler { +class MessagesRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; + public const FOLDER_META = [ 'inbox' => [ 'title' => 'Inbox', 'icon' => 'fas fa-inbox fa-fw' ], 'drafts' => [ 'title' => 'Drafts', 'icon' => 'fas fa-pencil-alt fa-fw' ], @@ -23,8 +25,8 @@ class MessagesRoutes extends RouteHandler { ]; public function __construct( - private IConfig $config, - private URLRegistry $urls, + private Config $config, + private UrlRegistry $urls, private AuthInfo $authInfo, private MessagesContext $msgsCtx, private UsersContext $usersCtx, @@ -77,7 +79,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpGet('/messages')] - #[URLInfo('messages-index', '/messages', ['folder' => '<folder>', 'page' => '<page>'])] + #[UrlFormat('messages-index', '/messages', ['folder' => '<folder>', 'page' => '<page>'])] public function getIndex($response, $request, string $folderName = '') { $folderName = (string)$request->getParam('folder'); if($folderName === '') @@ -130,7 +132,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpGet('/messages/stats')] - #[URLInfo('messages-stats', '/messages/stats')] + #[UrlFormat('messages-stats', '/messages/stats')] public function getStats() { $selfInfo = $this->authInfo->getUserInfo(); $msgsDb = $this->msgsCtx->getDatabase(); @@ -147,7 +149,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/recipient')] - #[URLInfo('messages-recipient', '/messages/recipient')] + #[UrlFormat('messages-recipient', '/messages/recipient')] public function postRecipient($response, $request) { if(!$request->isFormContent()) return 400; @@ -187,7 +189,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpGet('/messages/compose')] - #[URLInfo('messages-compose', '/messages/compose', ['recipient' => '<recipient>'])] + #[UrlFormat('messages-compose', '/messages/compose', ['recipient' => '<recipient>'])] public function getEditor($response, $request) { if(!$this->canSendMessages) return 403; @@ -198,7 +200,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpGet('/messages/([A-Za-z0-9]+)')] - #[URLInfo('messages-view', '/messages/<message>')] + #[UrlFormat('messages-view', '/messages/<message>')] public function getView($response, $request, string $messageId) { if(strlen($messageId) !== 8) return 404; @@ -328,7 +330,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/create')] - #[URLInfo('messages-create', '/messages/create')] + #[UrlFormat('messages-create', '/messages/create')] public function postCreate($response, $request) { if(!$request->isFormContent()) return 400; @@ -431,7 +433,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/([A-Za-z0-9]+)')] - #[URLInfo('messages-update', '/messages/<message>')] + #[UrlFormat('messages-update', '/messages/<message>')] public function postUpdate($response, $request, string $messageId) { if(!$request->isFormContent()) return 400; @@ -522,7 +524,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/mark')] - #[URLInfo('messages-mark', '/messages/mark')] + #[UrlFormat('messages-mark', '/messages/mark')] public function postMark($response, $request) { if(!$request->isFormContent()) return 400; @@ -553,7 +555,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/delete')] - #[URLInfo('messages-delete', '/messages/delete')] + #[UrlFormat('messages-delete', '/messages/delete')] public function postDelete($response, $request) { if(!$request->isFormContent()) return 400; @@ -580,7 +582,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/restore')] - #[URLInfo('messages-restore', '/messages/restore')] + #[UrlFormat('messages-restore', '/messages/restore')] public function postRestore($response, $request) { if(!$request->isFormContent()) return 400; @@ -607,7 +609,7 @@ class MessagesRoutes extends RouteHandler { } #[HttpPost('/messages/nuke')] - #[URLInfo('messages-nuke', '/messages/nuke')] + #[UrlFormat('messages-nuke', '/messages/nuke')] public function postNuke($response, $request) { if(!$request->isFormContent()) return 400; diff --git a/src/MisuzuContext.php b/src/MisuzuContext.php index f559f3a..20fb654 100644 --- a/src/MisuzuContext.php +++ b/src/MisuzuContext.php @@ -13,14 +13,14 @@ use Misuzu\Messages\MessagesContext; use Misuzu\News\News; use Misuzu\Perms\Permissions; use Misuzu\Profile\ProfileFields; -use Misuzu\URLs\URLRegistry; use Misuzu\Users\{UsersContext,UserInfo}; use Aiwass\HmacVerificationProvider; use Aiwass\Server\RpcServer; -use Index\Data\IDbConnection; -use Index\Data\Migration\{IDbMigrationRepo,DbMigrationManager,FsDbMigrationRepo}; -use Sasae\SasaeEnvironment; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Db\DbConnection; +use Index\Db\Migration\{DbMigrationManager,DbMigrationRepo,FsDbMigrationRepo}; +use Index\Templating\TplEnvironment; +use Index\Urls\UrlRegistry; // this class should function as the root for everything going forward // no more magical static classes that are just kind of assumed to exist @@ -29,9 +29,9 @@ use Syokuhou\IConfig; // dunno if i want null checks some maybe some kind of init func should be called first like is the case // with the http shit class MisuzuContext { - private IDbConnection $dbConn; - private IConfig $config; - private SasaeEnvironment $templating; + private DbConnection $dbConn; + private Config $config; + private TplEnvironment $templating; private AuditLog $auditLog; private Counters $counters; @@ -53,9 +53,9 @@ class MisuzuContext { private SiteInfo $siteInfo; // this probably shouldn't be available - private URLRegistry $urls; + private UrlRegistry $urls; - public function __construct(IDbConnection $dbConn, IConfig $config) { + public function __construct(DbConnection $dbConn, Config $config) { $this->dbConn = $dbConn; $this->config = $config; @@ -77,7 +77,7 @@ class MisuzuContext { $this->profileFields = new ProfileFields($dbConn); } - public function getDbConn(): IDbConnection { + public function getDbConn(): DbConnection { return $this->dbConn; } @@ -90,15 +90,15 @@ class MisuzuContext { return new DbMigrationManager($this->dbConn, 'msz_' . DbMigrationManager::DEFAULT_TABLE); } - public function createMigrationRepo(): IDbMigrationRepo { + public function createMigrationRepo(): DbMigrationRepo { return new FsDbMigrationRepo(MSZ_MIGRATIONS); } - public function getURLs(): URLRegistry { + public function getUrls(): UrlRegistry { return $this->urls; } - public function getConfig(): IConfig { + public function getConfig(): Config { return $this->config; } @@ -198,12 +198,12 @@ class MisuzuContext { $globals['active_ban_info'] = $this->usersCtx->tryGetActiveBan($this->authInfo->getUserInfo()); $globals['display_timings_info'] = $isDebug || $this->authInfo->getPerms('global')->check(Perm::G_TIMINGS_VIEW); - $this->templating = new SasaeEnvironment( + $this->templating = new TplEnvironment( MSZ_TEMPLATES, cache: $isDebug ? null : ['Misuzu', GitInfo::hash(true)], debug: $isDebug ); - $this->templating->addExtension(new MisuzuSasaeExtension($this)); + $this->templating->addExtension(new TemplatingExtension($this)); $this->templating->addGlobal('globals', $globals); Template::init($this->templating); @@ -212,7 +212,7 @@ class MisuzuContext { public function createRouting(): RoutingContext { $routingCtx = new RoutingContext(); - $this->urls = $routingCtx->getURLs(); + $this->urls = $routingCtx->getUrls(); $routingCtx->register(new \Misuzu\Home\HomeRoutes( $this->config, diff --git a/src/News/News.php b/src/News/News.php index 877ac8b..586a642 100644 --- a/src/News/News.php +++ b/src/News/News.php @@ -4,18 +4,16 @@ namespace Misuzu\News; use InvalidArgumentException; use RuntimeException; use DateTimeInterface; -use Index\Data\DbStatementCache; -use Index\Data\IDbConnection; -use Index\Data\IDbResult; +use Index\Db\{DbConnection,DbStatementCache}; use Misuzu\Pagination; use Misuzu\Comments\CommentsCategoryInfo; use Misuzu\Users\UserInfo; class News { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/News/NewsCategoryInfo.php b/src/News/NewsCategoryInfo.php index eb49989..5558bd0 100644 --- a/src/News/NewsCategoryInfo.php +++ b/src/News/NewsCategoryInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\News; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class NewsCategoryInfo { public function __construct( @@ -14,7 +14,7 @@ class NewsCategoryInfo { private int $posts, ) {} - public static function fromResult(IDbResult $result): NewsCategoryInfo { + public static function fromResult(DbResult $result): NewsCategoryInfo { return new NewsCategoryInfo( id: $result->getString(0), name: $result->getString(1), diff --git a/src/News/NewsPostInfo.php b/src/News/NewsPostInfo.php index c2da950..c841e6e 100644 --- a/src/News/NewsPostInfo.php +++ b/src/News/NewsPostInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\News; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class NewsPostInfo { public function __construct( @@ -19,7 +19,7 @@ class NewsPostInfo { private ?int $deleted, ) {} - public static function fromResult(IDbResult $result): NewsPostInfo { + public static function fromResult(DbResult $result): NewsPostInfo { return new NewsPostInfo( id: $result->getString(0), categoryId: $result->getString(1), diff --git a/src/News/NewsRoutes.php b/src/News/NewsRoutes.php index fa1bd49..6f790dc 100644 --- a/src/News/NewsRoutes.php +++ b/src/News/NewsRoutes.php @@ -2,21 +2,22 @@ namespace Misuzu\News; use RuntimeException; -use Index\Data\{DbTools,IDbConnection}; -use Index\Http\Routing\{HttpGet,RouteHandler}; +use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait}; +use Index\Syndication\FeedBuilder; +use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait}; use Misuzu\{Pagination,SiteInfo,Template}; use Misuzu\Auth\AuthInfo; use Misuzu\Comments\{Comments,CommentsCategory,CommentsEx}; -use Misuzu\Feeds\{Feed,FeedItem,AtomFeedSerializer,RssFeedSerializer}; use Misuzu\Parsers\Parser; -use Misuzu\URLs\{URLInfo,URLRegistry}; use Misuzu\Users\UsersContext; -class NewsRoutes extends RouteHandler { +class NewsRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; + public function __construct( private SiteInfo $siteInfo, private AuthInfo $authInfo, - private URLRegistry $urls, + private UrlRegistry $urls, private News $news, private UsersContext $usersCtx, private Comments $comments @@ -81,7 +82,7 @@ class NewsRoutes extends RouteHandler { } #[HttpGet('/news')] - #[URLInfo('news-index', '/news', ['p' => '<page>'])] + #[UrlFormat('news-index', '/news', ['p' => '<page>'])] public function getIndex() { $categories = $this->news->getCategories(hidden: false); @@ -98,20 +99,8 @@ class NewsRoutes extends RouteHandler { ]); } - #[HttpGet('/news.rss')] - #[URLInfo('news-feed-rss', '/news.rss')] - public function getFeedRss($response) { - return $this->getFeed($response, 'rss'); - } - - #[HttpGet('/news.atom')] - #[URLInfo('news-feed-atom', '/news.atom')] - public function getFeedAtom($response) { - return $this->getFeed($response, 'atom'); - } - - #[HttpGet('/news/([0-9]+)(?:\.(rss|atom))?')] - #[URLInfo('news-category', '/news/<category>', ['p' => '<page>'])] + #[HttpGet('/news/([0-9]+)(?:\.(xml|rss|atom))?')] + #[UrlFormat('news-category', '/news/<category>', ['p' => '<page>'])] public function getCategory($response, $request, string $categoryId, string $type = '') { try { $categoryInfo = $this->news->getCategory(categoryId: $categoryId); @@ -119,12 +108,8 @@ class NewsRoutes extends RouteHandler { return 404; } - if($type === 'rss') - return $this->getCategoryFeedRss($response, $request, $categoryInfo); - elseif($type === 'atom') - return $this->getCategoryFeedAtom($response, $request, $categoryInfo); - elseif($type !== '') - return 404; + if($type !== '') + return $this->getFeed($response, $request, $categoryInfo); $pagination = new Pagination($this->news->countPosts(categoryInfo: $categoryInfo), 5); if(!$pagination->hasValidOffset()) @@ -139,19 +124,9 @@ class NewsRoutes extends RouteHandler { ]); } - #[URLInfo('news-category-feed-rss', '/news/<category>.rss')] - private function getCategoryFeedRss($response, $request, NewsCategoryInfo $categoryInfo) { - return $this->getFeed($response, 'rss', $categoryInfo); - } - - #[URLInfo('news-category-feed-atom', '/news/<category>.atom')] - private function getCategoryFeedAtom($response, $request, NewsCategoryInfo $categoryInfo) { - return $this->getFeed($response, 'atom', $categoryInfo); - } - #[HttpGet('/news/post/([0-9]+)')] - #[URLInfo('news-post', '/news/post/<post>')] - #[URLInfo('news-post-comments', '/news/post/<post>', fragment: 'comments')] + #[UrlFormat('news-post', '/news/post/<post>')] + #[UrlFormat('news-post-comments', '/news/post/<post>', fragment: 'comments')] public function getPost($response, $request, string $postId) { try { $postInfo = $this->news->getPost($postId); @@ -186,56 +161,56 @@ class NewsRoutes extends RouteHandler { ]); } - private function getFeed($response, string $feedType, ?NewsCategoryInfo $categoryInfo = null) { + #[HttpGet('/news.(?:xml|rss|atom)')] + #[UrlFormat('news-feed', '/news.xml')] + #[UrlFormat('news-category-feed', '/news/<category>.xml')] + public function getFeed($response, $request, ?NewsCategoryInfo $categoryInfo = null) { + $response->setContentType('application/rss+xml; charset=utf-8'); + $hasCategory = $categoryInfo !== null; $siteName = $this->siteInfo->getName(); + $siteUrl = $this->siteInfo->getURL(); $posts = $this->getNewsPostsForFeed($categoryInfo); - $serialiser = match($feedType) { - 'rss' => new RssFeedSerializer, - 'atom' => new AtomFeedSerializer, - default => throw new RuntimeException('Invalid $feedType specified.'), - }; - - $response->setContentType(sprintf('application/%s+xml; charset=utf-8', $feedType)); - $feed = (new Feed) - ->setTitle($siteName . ' » ' . ($hasCategory ? $categoryInfo->getName() : 'Featured News')) - ->setDescription($hasCategory ? $categoryInfo->getDescription() : 'A live featured news feed.') - ->setContentUrl($this->siteInfo->getURL() . ($hasCategory ? $this->urls->format('news-category', ['category' => $categoryInfo->getId()]) : $this->urls->format('news-index'))) - ->setFeedUrl($this->siteInfo->getURL() . ($hasCategory ? $this->urls->format("news-category-feed-{$feedType}", ['category' => $categoryInfo->getId()]) : $this->urls->format("news-feed-{$feedType}"))); - - foreach($posts as $post) { - $postInfo = $post['post']; - $userInfo = $post['user']; - - $userId = 0; - $userName = 'Author'; - if($userInfo !== null) { - $userId = $userInfo->getId(); - $userName = $userInfo->getName(); - } - - $postUrl = $this->siteInfo->getURL() . $this->urls->format('news-post', ['post' => $postInfo->getId()]); - $commentsUrl = $this->siteInfo->getURL() . $this->urls->format('news-post-comments', ['post' => $postInfo->getId()]); - $authorUrl = $this->siteInfo->getURL() . $this->urls->format('user-profile', ['user' => $userId]); - - $feedItem = (new FeedItem) - ->setTitle($postInfo->getTitle()) - ->setSummary($postInfo->getFirstParagraph()) - ->setContent(Parser::instance(Parser::MARKDOWN)->parseText($postInfo->getBody())) - ->setCreationDate($postInfo->getCreatedTime()) - ->setUniqueId($postUrl) - ->setContentUrl($postUrl) - ->setCommentsUrl($commentsUrl) - ->setAuthorName($userName) - ->setAuthorUrl($authorUrl); - - if(!$feed->hasLastUpdate() || $feed->getLastUpdate() < $feedItem->getCreationDate()) - $feed->setLastUpdate($feedItem->getCreationDate()); - - $feed->addItem($feedItem); + $feed = new FeedBuilder; + if($hasCategory) { + $feed->setTitle(sprintf('%s » %s', $siteName, $categoryInfo->getName())); + $feed->setDescription($categoryInfo->getDescription()); + $feed->setContentUrl($siteUrl . $this->urls->format('news-category', ['category' => $categoryInfo->getId()])); + $feed->setFeedUrl($siteUrl . $this->urls->format('news-category-feed', ['category' => $categoryInfo->getId()])); + } else { + $feed->setTitle(sprintf('%s » Featured News', $siteName)); + $feed->setDescription('A live featured news feed.'); + $feed->setContentUrl($siteUrl . $this->urls->format('news-index')); + $feed->setFeedUrl($siteUrl . $this->urls->format('news-feed')); } - return $serialiser->serializeFeed($feed); + $feedUpdatedAt = 0; + foreach($posts as $post) + $feed->createEntry(function($item) use ($feed, $post, $siteUrl, &$feedUpdatedAt) { + $postInfo = $post['post']; + $userInfo = $post['user']; + + $item->setTitle($postInfo->getTitle()); + $item->setDescription(Parser::instance(Parser::MARKDOWN)->parseText($postInfo->getBody())); + $item->setCreatedAt($postInfo->getCreatedTime()); + $item->setContentUrl($siteUrl . $this->urls->format('news-post', ['post' => $postInfo->getId()])); + $item->setCommentsUrl($siteUrl . $this->urls->format('news-post-comments', ['post' => $postInfo->getId()])); + + if($userInfo !== null) { + $item->setAuthorName($userInfo->getName()); + $item->setAuthorUrl($siteUrl . $this->urls->format('user-profile', ['user' => $userInfo->getId()])); + } + + $itemUpdatedAt = $postInfo->getUpdatedTime(); + if($feedUpdatedAt < $itemUpdatedAt) { + $feed->setUpdatedAt($feedUpdatedAt = $itemUpdatedAt); + + if($postInfo->getCreatedTime() < $itemUpdatedAt) + $item->setUpdatedAt($itemUpdatedAt); + } + }); + + return $feed->toXmlString(); } } diff --git a/src/Perms/PermissionInfo.php b/src/Perms/PermissionInfo.php index 141d308..8d8902a 100644 --- a/src/Perms/PermissionInfo.php +++ b/src/Perms/PermissionInfo.php @@ -1,7 +1,7 @@ <?php namespace Misuzu\Perms; -use Index\Data\IDbResult; +use Index\Db\DbResult; class PermissionInfo implements IPermissionResult { use PermissionResultShared; @@ -19,7 +19,7 @@ class PermissionInfo implements IPermissionResult { $this->calculated = $this->allow & ~$this->deny; } - public static function fromResult(IDbResult $result): PermissionInfo { + public static function fromResult(DbResult $result): PermissionInfo { return new PermissionInfo( userId: $result->getStringOrNull(0), roleId: $result->getStringOrNull(1), diff --git a/src/Perms/Permissions.php b/src/Perms/Permissions.php index e5677ba..b095791 100644 --- a/src/Perms/Permissions.php +++ b/src/Perms/Permissions.php @@ -5,14 +5,9 @@ use stdClass; use InvalidArgumentException; use RuntimeException; use Index\XDateTime; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; -use Index\Data\IDbStatement; -use Misuzu\Forum\ForumCategories; -use Misuzu\Forum\ForumCategoryInfo; -use Misuzu\Users\RoleInfo; -use Misuzu\Users\UserInfo; +use Index\Db\{DbConnection,DbStatement,DbStatementCache,DbTools}; +use Misuzu\Forum\{ForumCategories,ForumCategoryInfo}; +use Misuzu\Users\{RoleInfo,UserInfo}; class Permissions { // limiting this to 53-bit in case it ever has to be sent to javascript or any other implicit float language @@ -21,10 +16,10 @@ class Permissions { public const PERMS_MIN = 0; public const PERMS_MAX = 9007199254740991; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } @@ -302,7 +297,7 @@ class Permissions { self::precalculatePermissionsLog('Finished permission precalculations!'); } - private function precalculatePermissionsForForumCategory(IDbStatement $insert, array $userIds, object $forumCat, bool $doGuest, array $catIds = []): void { + private function precalculatePermissionsForForumCategory(DbStatement $insert, array $userIds, object $forumCat, bool $doGuest, array $catIds = []): void { $catIds[] = $currentCatId = $forumCat->info->getId(); self::precalculatePermissionsLog('Precalcuting permissions for forum category #%s (%s)...', $currentCatId, implode(' <- ', $catIds)); diff --git a/src/Profile/ProfileFieldFormatInfo.php b/src/Profile/ProfileFieldFormatInfo.php index 7e5b853..78ae04d 100644 --- a/src/Profile/ProfileFieldFormatInfo.php +++ b/src/Profile/ProfileFieldFormatInfo.php @@ -1,7 +1,7 @@ <?php namespace Misuzu\Profile; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ProfileFieldFormatInfo { public function __construct( @@ -12,7 +12,7 @@ class ProfileFieldFormatInfo { private string $displayFormat, ) {} - public static function fromResult(IDbResult $result): ProfileFieldFormatInfo { + public static function fromResult(DbResult $result): ProfileFieldFormatInfo { return new ProfileFieldFormatInfo( id: $result->getString(0), fieldId: $result->getString(1), diff --git a/src/Profile/ProfileFieldInfo.php b/src/Profile/ProfileFieldInfo.php index aa5a62f..476abf7 100644 --- a/src/Profile/ProfileFieldInfo.php +++ b/src/Profile/ProfileFieldInfo.php @@ -1,7 +1,7 @@ <?php namespace Misuzu\Profile; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ProfileFieldInfo { public function __construct( @@ -12,7 +12,7 @@ class ProfileFieldInfo { private string $regex, ) {} - public static function fromResult(IDbResult $result): ProfileFieldInfo { + public static function fromResult(DbResult $result): ProfileFieldInfo { return new ProfileFieldInfo( id: $result->getString(0), order: $result->getInteger(1), diff --git a/src/Profile/ProfileFieldValueInfo.php b/src/Profile/ProfileFieldValueInfo.php index 889e247..2bfd418 100644 --- a/src/Profile/ProfileFieldValueInfo.php +++ b/src/Profile/ProfileFieldValueInfo.php @@ -1,7 +1,7 @@ <?php namespace Misuzu\Profile; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ProfileFieldValueInfo { public function __construct( @@ -11,7 +11,7 @@ class ProfileFieldValueInfo { private string $value, ) {} - public static function fromResult(IDbResult $result): ProfileFieldValueInfo { + public static function fromResult(DbResult $result): ProfileFieldValueInfo { return new ProfileFieldValueInfo( fieldId: $result->getString(0), userId: $result->getString(1), diff --git a/src/Profile/ProfileFields.php b/src/Profile/ProfileFields.php index 3a046cd..e948b74 100644 --- a/src/Profile/ProfileFields.php +++ b/src/Profile/ProfileFields.php @@ -3,16 +3,13 @@ namespace Misuzu\Profile; use InvalidArgumentException; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; -use Index\Data\IDbResult; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Users\UserInfo; class ProfileFields { private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->cache = new DbStatementCache($dbConn); } diff --git a/src/RoutingContext.php b/src/RoutingContext.php index 3316070..606f1f5 100644 --- a/src/RoutingContext.php +++ b/src/RoutingContext.php @@ -1,33 +1,32 @@ <?php namespace Misuzu; -use Index\Http\Routing\{HttpRouter,IRouter,IRouteHandler}; -use Misuzu\URLs\{IURLSource,URLInfo,URLRegistry}; +use Index\Http\Routing\{HttpRouter,Router,RouteHandler}; +use Index\Urls\{ArrayUrlRegistry,UrlFormat,UrlRegistry,UrlSource}; class RoutingContext { - private URLRegistry $urls; + private UrlRegistry $urls; private HttpRouter $router; public function __construct() { - $this->urls = new URLRegistry; + $this->urls = new ArrayUrlRegistry; $this->router = new HttpRouter(errorHandler: new RoutingErrorHandler); $this->router->use('/', fn($resp) => $resp->setPoweredBy('Misuzu')); } - public function getURLs(): URLRegistry { + public function getUrls(): UrlRegistry { return $this->urls; } - public function getRouter(): IRouter { + public function getRouter(): Router { return $this->router; } - public function register(IRouteHandler|IURLSource $handler): void { - if($handler instanceof IRouteHandler) + public function register(RouteHandler|UrlSource $handler): void { + if($handler instanceof RouteHandler) $this->router->register($handler); - if($handler instanceof IURLSource) - $handler->registerURLs($this->urls); - URLInfo::handleAttributes($this->urls, $handler); + if($handler instanceof UrlSource) + $this->urls->register($handler); } public function dispatch(...$args): void { diff --git a/src/RoutingErrorHandler.php b/src/RoutingErrorHandler.php index 24c6f6f..ac09bc9 100644 --- a/src/RoutingErrorHandler.php +++ b/src/RoutingErrorHandler.php @@ -1,10 +1,9 @@ <?php namespace Misuzu; -use Index\Http\{HttpResponseBuilder,HttpRequest}; -use Index\Http\ErrorHandling\HtmlErrorHandler; +use Index\Http\{HtmlHttpErrorHandler,HttpResponseBuilder,HttpRequest}; -class RoutingErrorHandler extends HtmlErrorHandler { +class RoutingErrorHandler extends HtmlHttpErrorHandler { public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void { if(str_starts_with($request->getPath(), '/_')) { $response->setTypePlain(); diff --git a/src/Satori/SatoriRoutes.php b/src/Satori/SatoriRoutes.php index 4423fb7..ffad578 100644 --- a/src/Satori/SatoriRoutes.php +++ b/src/Satori/SatoriRoutes.php @@ -3,17 +3,19 @@ namespace Misuzu\Satori; use RuntimeException; use Index\Colour\Colour; -use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler}; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler,RouteHandlerTrait}; use Misuzu\Pagination; use Misuzu\RoutingContext; use Misuzu\Forum\ForumContext; use Misuzu\Profile\ProfileFields; use Misuzu\Users\UsersContext; -final class SatoriRoutes extends RouteHandler { +final class SatoriRoutes implements RouteHandler { + use RouteHandlerTrait; + public function __construct( - private IConfig $config, + private Config $config, private UsersContext $usersCtx, private ForumContext $forumCtx, private ProfileFields $profileFields diff --git a/src/SharpChat/SharpChatRoutes.php b/src/SharpChat/SharpChatRoutes.php index 65ce102..cdf69e9 100644 --- a/src/SharpChat/SharpChatRoutes.php +++ b/src/SharpChat/SharpChatRoutes.php @@ -6,19 +6,21 @@ use Misuzu\RoutingContext; use Misuzu\Auth\{AuthContext,AuthInfo,Sessions}; use Misuzu\Emoticons\Emotes; use Misuzu\Perms\Permissions; -use Misuzu\URLs\URLRegistry; use Misuzu\Users\{Bans,UsersContext,UserInfo}; use Index\Colour\Colour; -use Index\Http\Routing\{HandlerAttribute,HttpDelete,HttpGet,HttpOptions,HttpPost,RouteHandler}; -use Syokuhou\IConfig; +use Index\Config\Config; +use Index\Http\Routing\{HandlerAttribute,HttpDelete,HttpGet,HttpOptions,HttpPost,RouteHandler,RouteHandlerTrait}; +use Index\Urls\UrlRegistry; + +final class SharpChatRoutes implements RouteHandler { + use RouteHandlerTrait; -final class SharpChatRoutes extends RouteHandler { private string $hashKey; public function __construct( - private IConfig $config, - private IConfig $impersonateConfig, // this sucks lol - private URLRegistry $urls, + private Config $config, + private Config $impersonateConfig, // this sucks lol + private UrlRegistry $urls, private UsersContext $usersCtx, private AuthContext $authCtx, private Emotes $emotes, diff --git a/src/SiteInfo.php b/src/SiteInfo.php index 54eabe5..f8c167a 100644 --- a/src/SiteInfo.php +++ b/src/SiteInfo.php @@ -1,14 +1,14 @@ <?php namespace Misuzu; -use Syokuhou\IConfig; +use Index\Config\Config; class SiteInfo { private bool $loaded = false; private array $props; public function __construct( - private IConfig $config + private Config $config ) {} public function load(): void { diff --git a/src/Template.php b/src/Template.php index 95709be..0b26d3b 100644 --- a/src/Template.php +++ b/src/Template.php @@ -2,17 +2,15 @@ namespace Misuzu; use InvalidArgumentException; -use Sasae\SasaeContext; -use Sasae\SasaeEnvironment; -use Misuzu\MisuzuContext; +use Index\Templating\TplEnvironment; final class Template { private const FILE_EXT = '.twig'; - private static SasaeEnvironment $env; + private static TplEnvironment $env; private static array $vars = []; - public static function init(SasaeEnvironment $env): void { + public static function init(TplEnvironment $env): void { self::$env = $env; } diff --git a/src/MisuzuSasaeExtension.php b/src/TemplatingExtension.php similarity index 97% rename from src/MisuzuSasaeExtension.php rename to src/TemplatingExtension.php index c92c466..3146ab1 100644 --- a/src/MisuzuSasaeExtension.php +++ b/src/TemplatingExtension.php @@ -10,7 +10,7 @@ use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; -final class MisuzuSasaeExtension extends AbstractExtension { +final class TemplatingExtension extends AbstractExtension { private MisuzuContext $ctx; private ?object $assets; @@ -30,7 +30,7 @@ final class MisuzuSasaeExtension extends AbstractExtension { public function getFunctions() { return [ new TwigFunction('asset', $this->getAssetPath(...)), - new TwigFunction('url', $this->ctx->getURLs()->format(...)), + new TwigFunction('url', $this->ctx->getUrls()->format(...)), new TwigFunction('csrf_token', CSRF::token(...)), new TwigFunction('git_commit_hash', GitInfo::hash(...)), new TwigFunction('git_tag', GitInfo::tag(...)), @@ -63,7 +63,7 @@ final class MisuzuSasaeExtension extends AbstractExtension { public function getHeaderMenu(): array { $menu = []; - $urls = $this->ctx->getURLs(); + $urls = $this->ctx->getUrls(); $authInfo = $this->ctx->getAuthInfo(); $home = [ @@ -124,7 +124,7 @@ final class MisuzuSasaeExtension extends AbstractExtension { public function getUserMenu(bool $inBroomCloset, string $manageUrl = ''): array { $menu = []; - $urls = $this->ctx->getURLs(); + $urls = $this->ctx->getUrls(); $authInfo = $this->ctx->getAuthInfo(); $usersCtx = $this->ctx->getUsersContext(); @@ -194,7 +194,7 @@ final class MisuzuSasaeExtension extends AbstractExtension { } public function getManageMenu(): array { - $urls = $this->ctx->getURLs(); + $urls = $this->ctx->getUrls(); $authInfo = $this->ctx->getAuthInfo(); $globalPerms = $authInfo->getPerms('global'); if(!$authInfo->isLoggedIn() || !$globalPerms->check(Perm::G_IS_JANITOR)) diff --git a/src/URLs/IURLSource.php b/src/URLs/IURLSource.php deleted file mode 100644 index c01884b..0000000 --- a/src/URLs/IURLSource.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php -namespace Misuzu\URLs; - -interface IURLSource { - public function registerURLs(URLRegistry $urls): void; -} diff --git a/src/URLs/URLInfo.php b/src/URLs/URLInfo.php deleted file mode 100644 index 176d7cc..0000000 --- a/src/URLs/URLInfo.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -namespace Misuzu\URLs; - -use Attribute; -use InvalidArgumentException; -use ReflectionObject; - -#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] -class URLInfo { - public function __construct( - private string $name, - private string $path, - private array $query = [], - private string $fragment = '' - ) { - if($path === '') - throw new InvalidArgumentException('$path may not be empty.'); - if($path[0] !== '/') - throw new InvalidArgumentException('$path must begin with /.'); - } - - public function getName(): string { - return $this->name; - } - - public function getPath(): string { - return $this->path; - } - - public function hasQuery(): bool { - return !empty($this->query); - } - - public function getQuery(): array { - return $this->query; - } - - public function hasFragment(): bool { - return $this->fragment !== ''; - } - - public function getFragment(): string { - return $this->fragment; - } - - public static function handleAttributes(URLRegistry $urls, object $source): void { - $objectInfo = new ReflectionObject($source); - $methodInfos = $objectInfo->getMethods(); - - foreach($methodInfos as $methodInfo) { - $attrInfos = $methodInfo->getAttributes(URLInfo::class); - foreach($attrInfos as $attrInfo) - $urls->registerInfo($attrInfo->newInstance()); - } - } -} diff --git a/src/URLs/URLRegistry.php b/src/URLs/URLRegistry.php deleted file mode 100644 index c0585cd..0000000 --- a/src/URLs/URLRegistry.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php -namespace Misuzu\URLs; - -use InvalidArgumentException; - -class URLRegistry { - private array $infos = []; - - public function register(string $name, string $path, array $query = [], string $fragment = ''): void { - if(array_key_exists($name, $this->infos)) - throw new InvalidArgumentException('A URL with $name has already been registered.'); - - $this->infos[$name] = new URLInfo($name, $path, $query, $fragment); - } - - public function registerInfo(URLInfo $info): void { - if(array_key_exists($info->getName(), $this->infos)) - throw new InvalidArgumentException('A URL with $name has already been registered.'); - - $this->infos[$info->getName()] = $info; - } - - public function format(string $name, array $vars = [], bool $spacesAsPlus = false): string { - if(!array_key_exists($name, $this->infos)) - return ''; - - $urlInfo = $this->infos[$name]; - $urlStr = self::replaceVariables($urlInfo->getPath(), $vars); - - if($urlInfo->hasQuery()) { - $query = []; - $queryParts = $urlInfo->getQuery(); - foreach($queryParts as $name => $value) { - $value = self::replaceVariables($value, $vars); - if($value !== '' && !($name === 'page' && (int)$value <= 1)) - $query[$name] = $value; - } - - if(!empty($query)) - $urlStr .= '?' . http_build_query($query, '', '&', $spacesAsPlus ? PHP_QUERY_RFC1738 : PHP_QUERY_RFC3986); - } - - if($urlInfo->hasFragment()) { - $fragment = self::replaceVariables($urlInfo->getFragment(), $vars); - if($fragment !== '') - $urlStr .= '#' . $fragment; - } - - return $urlStr; - } - - public static function replaceVariables(string $str, array $vars): string { - // i: have no idea what i'm doing - $out = ''; - $varName = ''; - $inVarName = false; - - $length = strlen($str); - for($i = 0; $i < $length; ++$i) { - $char = $str[$i]; - - if($inVarName) { - if($char === '>') { - $inVarName = false; - if(array_key_exists($varName, $vars)) { - $varValue = $vars[$varName]; - if(is_array($varValue)) - $varValue = empty($varValue) ? '' : implode(',', $varValue); - elseif(is_int($varValue)) - $varValue = ($varName === 'page' ? $varValue < 2 : $varValue === 0) ? '' : (string)$varValue; - else - $varValue = (string)$varValue; - } else - $varValue = ''; - - $out .= $varValue; - $varName = ''; - continue; - } - - if($char === '<') { - $out .= '<' . $varName; - $varName = ''; - continue; - } - - $varName .= $char; - } else - $inVarName = $char === '<'; - - if(!$inVarName) - $out .= $char; - } - - if($varName !== '') - $out .= $varName; - - return $out; - } -} diff --git a/src/Users/Assets/AssetsRoutes.php b/src/Users/Assets/AssetsRoutes.php index db1aece..a2047e6 100644 --- a/src/Users/Assets/AssetsRoutes.php +++ b/src/Users/Assets/AssetsRoutes.php @@ -3,16 +3,18 @@ namespace Misuzu\Users\Assets; use InvalidArgumentException; use RuntimeException; -use Index\Http\Routing\{HttpGet,RouteHandler}; +use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait}; +use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait}; use Misuzu\Perm; use Misuzu\Auth\AuthInfo; -use Misuzu\URLs\{URLInfo,URLRegistry}; use Misuzu\Users\{UsersContext,UserInfo}; -class AssetsRoutes extends RouteHandler { +class AssetsRoutes implements RouteHandler, UrlSource { + use RouteHandlerTrait, UrlSourceTrait; + public function __construct( private AuthInfo $authInfo, - private URLRegistry $urls, + private UrlRegistry $urls, private UsersContext $usersCtx ) {} @@ -28,7 +30,7 @@ class AssetsRoutes extends RouteHandler { #[HttpGet('/assets/avatar')] #[HttpGet('/assets/avatar/([0-9]+)(?:\.[a-z]+)?')] - #[URLInfo('user-avatar', '/assets/avatar/<user>', ['res' => '<res>'])] + #[UrlFormat('user-avatar', '/assets/avatar/<user>', ['res' => '<res>'])] public function getAvatar($response, $request, string $userId = '') { $assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/no-avatar.png', MSZ_PUBLIC); @@ -50,7 +52,7 @@ class AssetsRoutes extends RouteHandler { #[HttpGet('/assets/profile-background')] #[HttpGet('/assets/profile-background/([0-9]+)(?:\.[a-z]+)?')] - #[URLInfo('user-background', '/assets/profile-background/<user>')] + #[UrlFormat('user-background', '/assets/profile-background/<user>')] public function getProfileBackground($response, $request, string $userId = '') { try { $userInfo = $this->usersCtx->getUserInfo($userId); diff --git a/src/Users/BanInfo.php b/src/Users/BanInfo.php index 6db545c..7d64e5c 100644 --- a/src/Users/BanInfo.php +++ b/src/Users/BanInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Users; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class BanInfo { public function __construct( @@ -16,7 +16,7 @@ class BanInfo { private ?int $expires, ) {} - public static function fromResult(IDbResult $result): BanInfo { + public static function fromResult(DbResult $result): BanInfo { return new BanInfo( id: $result->getString(0), userId: $result->getString(1), diff --git a/src/Users/Bans.php b/src/Users/Bans.php index f251b81..de5b981 100644 --- a/src/Users/Bans.php +++ b/src/Users/Bans.php @@ -5,19 +5,17 @@ use InvalidArgumentException; use RuntimeException; use DateTimeInterface; use Misuzu\Pagination; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; class Bans { public const SEVERITY_MAX = 10; public const SEVERITY_MIN = -10; public const SEVERITY_DEFAULT = 0; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Users/ModNoteInfo.php b/src/Users/ModNoteInfo.php index 4a4c2f9..5b1c28a 100644 --- a/src/Users/ModNoteInfo.php +++ b/src/Users/ModNoteInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Users; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class ModNoteInfo { public function __construct( @@ -14,7 +14,7 @@ class ModNoteInfo { private string $body, ) {} - public static function fromResult(IDbResult $result): ModNoteInfo { + public static function fromResult(DbResult $result): ModNoteInfo { return new ModNoteInfo( noteId: $result->getString(0), userId: $result->getString(1), diff --git a/src/Users/ModNotes.php b/src/Users/ModNotes.php index a40851c..7479483 100644 --- a/src/Users/ModNotes.php +++ b/src/Users/ModNotes.php @@ -3,16 +3,14 @@ namespace Misuzu\Users; use InvalidArgumentException; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; class ModNotes { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Users/RoleInfo.php b/src/Users/RoleInfo.php index 906295d..b470004 100644 --- a/src/Users/RoleInfo.php +++ b/src/Users/RoleInfo.php @@ -4,7 +4,7 @@ namespace Misuzu\Users; use Stringable; use Carbon\CarbonImmutable; use Index\Colour\Colour; -use Index\Data\IDbResult; +use Index\Db\DbResult; class RoleInfo implements Stringable { public function __construct( @@ -20,7 +20,7 @@ class RoleInfo implements Stringable { private int $created, ) {} - public static function fromResult(IDbResult $result): RoleInfo { + public static function fromResult(DbResult $result): RoleInfo { return new RoleInfo( id: $result->getString(0), string: $result->getStringOrNull(1), diff --git a/src/Users/Roles.php b/src/Users/Roles.php index 1ec61b6..dcba466 100644 --- a/src/Users/Roles.php +++ b/src/Users/Roles.php @@ -4,18 +4,16 @@ namespace Misuzu\Users; use InvalidArgumentException; use RuntimeException; use Index\Colour\Colour; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; class Roles { public const DEFAULT_ROLE = '1'; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Users/UserInfo.php b/src/Users/UserInfo.php index 0604d97..ead325c 100644 --- a/src/Users/UserInfo.php +++ b/src/Users/UserInfo.php @@ -4,7 +4,7 @@ namespace Misuzu\Users; use Misuzu\Parsers\Parser; use Carbon\CarbonImmutable; use Index\Colour\Colour; -use Index\Data\IDbResult; +use Index\Db\DbResult; use Index\Net\IPAddress; class UserInfo { @@ -32,7 +32,7 @@ class UserInfo { private ?string $title, ) {} - public static function fromResult(IDbResult $result): self { + public static function fromResult(DbResult $result): self { return new UserInfo( id: $result->getString(0), name: $result->getString(1), diff --git a/src/Users/Users.php b/src/Users/Users.php index c110f3f..8808b81 100644 --- a/src/Users/Users.php +++ b/src/Users/Users.php @@ -6,19 +6,17 @@ use RuntimeException; use DateTimeInterface; use Index\XString; use Index\Colour\Colour; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Index\Net\IPAddress; use Misuzu\Pagination; use Misuzu\Tools; use Misuzu\Parsers\Parser; class Users { - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/src/Users/UsersContext.php b/src/Users/UsersContext.php index 55a8454..b051ffb 100644 --- a/src/Users/UsersContext.php +++ b/src/Users/UsersContext.php @@ -2,7 +2,7 @@ namespace Misuzu\Users; use Index\Colour\Colour; -use Index\Data\IDbConnection; +use Index\Db\DbConnection; class UsersContext { private Users $users; @@ -17,7 +17,7 @@ class UsersContext { private array $activeBans = []; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->users = new Users($dbConn); $this->roles = new Roles($dbConn); $this->bans = new Bans($dbConn); diff --git a/src/Users/UsersRpcActions.php b/src/Users/UsersRpcActions.php index 5abe05c..79426dc 100644 --- a/src/Users/UsersRpcActions.php +++ b/src/Users/UsersRpcActions.php @@ -3,16 +3,16 @@ namespace Misuzu\Users; use RuntimeException; use Misuzu\SiteInfo; -use Misuzu\URLs\URLRegistry; use Misuzu\Users\Assets\UserAvatarAsset; use Aiwass\Server\{RpcActionHandler,RpcQuery}; use Index\XArray; use Index\Colour\{Colour,ColourRGB}; +use Index\Urls\UrlRegistry; final class UsersRpcActions extends RpcActionHandler { public function __construct( private SiteInfo $siteInfo, - private URLRegistry $urls, + private UrlRegistry $urls, private UsersContext $usersCtx ) {} diff --git a/src/Users/WarningInfo.php b/src/Users/WarningInfo.php index 61eaa73..e249d5f 100644 --- a/src/Users/WarningInfo.php +++ b/src/Users/WarningInfo.php @@ -2,7 +2,7 @@ namespace Misuzu\Users; use Carbon\CarbonImmutable; -use Index\Data\IDbResult; +use Index\Db\DbResult; class WarningInfo { public function __construct( @@ -13,7 +13,7 @@ class WarningInfo { private int $created, ) {} - public static function fromResult(IDbResult $result): WarningInfo { + public static function fromResult(DbResult $result): WarningInfo { return new WarningInfo( id: $result->getString(0), userId: $result->getString(1), diff --git a/src/Users/Warnings.php b/src/Users/Warnings.php index 268f29d..3ae2e5f 100644 --- a/src/Users/Warnings.php +++ b/src/Users/Warnings.php @@ -3,9 +3,7 @@ namespace Misuzu\Users; use InvalidArgumentException; use RuntimeException; -use Index\Data\DbStatementCache; -use Index\Data\DbTools; -use Index\Data\IDbConnection; +use Index\Db\{DbConnection,DbStatementCache,DbTools}; use Misuzu\Pagination; // this system is currently kinda useless because it only silently shows up on profiles @@ -14,10 +12,10 @@ use Misuzu\Pagination; class Warnings { public const VISIBLE_BACKLOG = 90 * 24 * 60 * 60; - private IDbConnection $dbConn; + private DbConnection $dbConn; private DbStatementCache $cache; - public function __construct(IDbConnection $dbConn) { + public function __construct(DbConnection $dbConn) { $this->dbConn = $dbConn; $this->cache = new DbStatementCache($dbConn); } diff --git a/templates/changelog/index.twig b/templates/changelog/index.twig index 6c44932..f1b327d 100644 --- a/templates/changelog/index.twig +++ b/templates/changelog/index.twig @@ -31,14 +31,9 @@ {% set feeds = [ { 'type': 'rss', - 'title': '', - 'url': url('changelog-feed-rss'), - }, - { - 'type': 'atom', - 'title': '', - 'url': url('changelog-feed-atom'), - }, + 'title': 'Changelog feed', + 'url': url('changelog-feed'), + } ] %} {% endif %} diff --git a/templates/news/category.twig b/templates/news/category.twig index 5654909..f4967d4 100644 --- a/templates/news/category.twig +++ b/templates/news/category.twig @@ -12,14 +12,9 @@ {% set feeds = [ { 'type': 'rss', - 'title': '', - 'url': url('news-category-feed-rss', {'category': news_category.id}), - }, - { - 'type': 'atom', - 'title': '', - 'url': url('news-category-feed-atom', {'category': news_category.id}), - }, + 'title': news_category.name ~ ' feed', + 'url': url('news-category-feed', {'category': news_category.id}), + } ] %} {% block content %} @@ -47,15 +42,7 @@ {{ container_title('Feeds') }} <div class="news__feeds"> - <a href="{{ url('news-category-feed-atom', {'category': news_category.id}) }}" class="news__feed"> - <div class="news__feed__icon"> - <i class="fas fa-rss"></i> - </div> - <div class="news__feed__type"> - Atom - </div> - </a> - <a href="{{ url('news-category-feed-rss', {'category': news_category.id}) }}" class="news__feed"> + <a href="{{ url('news-category-feed', {'category': news_category.id}) }}" class="news__feed"> <div class="news__feed__icon"> <i class="fas fa-rss"></i> </div> diff --git a/templates/news/index.twig b/templates/news/index.twig index 7904d68..27dbc27 100644 --- a/templates/news/index.twig +++ b/templates/news/index.twig @@ -11,14 +11,9 @@ {% set feeds = [ { 'type': 'rss', - 'title': '', - 'url': url('news-feed-rss'), - }, - { - 'type': 'atom', - 'title': '', - 'url': url('news-feed-atom'), - }, + 'title': 'Featured news feed', + 'url': url('news-feed'), + } ] %} {% block content %} @@ -55,15 +50,7 @@ {{ container_title('Feeds') }} <div class="news__feeds"> - <a href="{{ url('news-feed-atom') }}" class="news__feed"> - <div class="news__feed__icon"> - <i class="fas fa-rss"></i> - </div> - <div class="news__feed__type"> - Atom - </div> - </a> - <a href="{{ url('news-feed-rss') }}" class="news__feed"> + <a href="{{ url('news-feed') }}" class="news__feed"> <div class="news__feed__icon"> <i class="fas fa-rss"></i> </div> diff --git a/tools/migrate b/tools/migrate index 576e12d..29e1d2b 100755 --- a/tools/migrate +++ b/tools/migrate @@ -1,6 +1,6 @@ #!/usr/bin/env php <?php -use Index\Data\Migration\FsDbMigrationRepo; +use Index\Db\Migration\FsDbMigrationRepo; require_once __DIR__ . '/../misuzu.php'; diff --git a/tools/new-migration b/tools/new-migration index d69479e..8b0c47f 100755 --- a/tools/new-migration +++ b/tools/new-migration @@ -1,6 +1,6 @@ #!/usr/bin/env php <?php -use Index\Data\Migration\FsDbMigrationRepo; +use Index\Db\Migration\FsDbMigrationRepo; require_once __DIR__ . '/../misuzu.php';