Updated Index version.

This commit is contained in:
flash 2025-01-29 23:13:17 +00:00
parent f2233c5390
commit 6c7568e261
50 changed files with 483 additions and 457 deletions

View file

@ -1,14 +1,14 @@
{
"require": {
"php": ">=8.4",
"flashwave/index": "^0.2410",
"flashii/rpcii": "^2.0",
"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/index": "^0.2501",
"flashii/rpcii": "~4.0",
"erusev/parsedown": "~1.7",
"chillerlan/php-qrcode": "~5.0",
"symfony/mailer": "~7.2",
"matomo/device-detector": "~6.4",
"sentry/sdk": "~4.0",
"nesbot/carbon": "~3.8"
},
"autoload": {
"classmap": [
@ -25,6 +25,7 @@
]
},
"require-dev": {
"phpstan/phpstan": "^2.0"
"phpstan/phpstan": "~2.1",
"filp/whoops": "~2.17"
}
}

177
composer.lock generated
View file

@ -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": "82b94e9d26ac6e86616be50e2bf37660",
"content-hash": "0da440b6622926a43462aaf9fd4d7bf6",
"packages": [
{
"name": "carbonphp/carbon-doctrine-types",
@ -77,16 +77,16 @@
},
{
"name": "chillerlan/php-qrcode",
"version": "4.4.2",
"version": "5.0.3",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-qrcode.git",
"reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4"
"reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4",
"reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4",
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/42e215640e9ebdd857570c9e4e52245d1ee51de2",
"reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2",
"shasum": ""
},
"require": {
@ -95,10 +95,14 @@
"php": "^7.4 || ^8.0"
},
"require-dev": {
"chillerlan/php-authenticator": "^4.3.1 || ^5.2.1",
"ext-fileinfo": "*",
"phan/phan": "^5.4.5",
"phpcompatibility/php-compatibility": "10.x-dev",
"phpmd/phpmd": "^2.15",
"phpunit/phpunit": "^9.6",
"setasign/fpdf": "^1.8.2",
"slevomat/coding-standard": "^8.15",
"squizlabs/php_codesniffer": "^3.11"
},
"suggest": {
@ -109,17 +113,26 @@
"type": "library",
"autoload": {
"psr-4": {
"chillerlan\\QRCode\\": "src/"
"chillerlan\\QRCode\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
"MIT",
"Apache-2.0"
],
"authors": [
{
"name": "Kazuhiko Arase",
"homepage": "https://github.com/kazuhikoarase"
"homepage": "https://github.com/kazuhikoarase/qrcode-generator"
},
{
"name": "ZXing Authors",
"homepage": "https://github.com/zxing/zxing"
},
{
"name": "Ashot Khanamiryan",
"homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder"
},
{
"name": "Smiley",
@ -131,26 +144,29 @@
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
}
],
"description": "A QR code generator with a user friendly API. PHP 7.4+",
"description": "A QR Code generator and reader with a user-friendly API. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-qrcode",
"keywords": [
"phpqrcode",
"qr",
"qr code",
"qr-reader",
"qrcode",
"qrcode-generator"
"qrcode-generator",
"qrcode-reader"
],
"support": {
"docs": "https://php-qrcode.readthedocs.io",
"issues": "https://github.com/chillerlan/php-qrcode/issues",
"source": "https://github.com/chillerlan/php-qrcode/tree/4.4.2"
"source": "https://github.com/chillerlan/php-qrcode"
},
"funding": [
{
"url": "https://ko-fi.com/codemasher",
"type": "ko_fi"
"type": "Ko-Fi"
}
],
"time": "2024-11-15T15:36:24+00:00"
"time": "2024-11-21T16:12:34+00:00"
},
{
"name": "chillerlan/php-settings-container",
@ -414,20 +430,20 @@
},
{
"name": "flashii/rpcii",
"version": "v2.0.1",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://patchii.net/flashii/rpcii-php.git",
"reference": "1cbc1edb061612dc1d014a82e24b741d2a0bc11a"
"reference": "7849b2effd7ac878e7cf174eef7e27914799e60d"
},
"require": {
"ext-msgpack": ">=2.2",
"flashwave/index": "^0.2410",
"php": ">=8.3"
"flashwave/index": "^0.2501",
"php": ">=8.4"
},
"require-dev": {
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^11.4"
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^11.5"
},
"type": "library",
"autoload": {
@ -449,25 +465,25 @@
],
"description": "HTTP RPC client/server library.",
"homepage": "https://railgun.sh/rpcii",
"time": "2024-11-14T02:22:09+00:00"
"time": "2025-01-29T22:00:17+00:00"
},
{
"name": "flashwave/index",
"version": "v0.2410.1091942",
"version": "v0.2501.221237",
"source": {
"type": "git",
"url": "https://patchii.net/flash/index.git",
"reference": "7da5e8095489dd930d81cdd033def3dfaed8689c"
"reference": "fee9a65e3bca341be7401fe2e21b795630f15f2a"
},
"require": {
"ext-mbstring": "*",
"php": ">=8.3",
"twig/html-extra": "^3.13",
"twig/twig": "^3.14"
"php": ">=8.4",
"twig/html-extra": "^3.18",
"twig/twig": "^3.18"
},
"require-dev": {
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^11.4"
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^11.5"
},
"suggest": {
"ext-memcache": "Support for the Index\\Cache\\Memcached namespace (only if you can't use ext-memcached for some reason).",
@ -504,7 +520,7 @@
],
"description": "Composer package for the common library for my projects.",
"homepage": "https://railgun.sh/index",
"time": "2025-01-17T19:52:39+00:00"
"time": "2025-01-22T12:38:11+00:00"
},
{
"name": "guzzlehttp/psr7",
@ -1706,39 +1722,39 @@
},
{
"name": "symfony/mailer",
"version": "v6.4.18",
"version": "v7.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
"reference": "e93a6ae2767d7f7578c2b7961d9d8e27580b2b11"
"reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/e93a6ae2767d7f7578c2b7961d9d8e27580b2b11",
"reference": "e93a6ae2767d7f7578c2b7961d9d8e27580b2b11",
"url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3",
"reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3",
"shasum": ""
},
"require": {
"egulias/email-validator": "^2.1.10|^3|^4",
"php": ">=8.1",
"php": ">=8.2",
"psr/event-dispatcher": "^1",
"psr/log": "^1|^2|^3",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/mime": "^6.2|^7.0",
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/mime": "^7.2",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"symfony/http-client-contracts": "<2.5",
"symfony/http-kernel": "<5.4",
"symfony/messenger": "<6.2",
"symfony/mime": "<6.2",
"symfony/twig-bridge": "<6.2.1"
"symfony/http-kernel": "<6.4",
"symfony/messenger": "<6.4",
"symfony/mime": "<6.4",
"symfony/twig-bridge": "<6.4"
},
"require-dev": {
"symfony/console": "^5.4|^6.0|^7.0",
"symfony/http-client": "^5.4|^6.0|^7.0",
"symfony/messenger": "^6.2|^7.0",
"symfony/twig-bridge": "^6.2|^7.0"
"symfony/console": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/messenger": "^6.4|^7.0",
"symfony/twig-bridge": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@ -1766,7 +1782,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/mailer/tree/v6.4.18"
"source": "https://github.com/symfony/mailer/tree/v7.2.3"
},
"funding": [
{
@ -1782,7 +1798,7 @@
"type": "tidelift"
}
],
"time": "2025-01-24T15:27:15+00:00"
"time": "2025-01-27T11:08:17+00:00"
},
{
"name": "symfony/mime",
@ -2816,6 +2832,77 @@
}
],
"packages-dev": [
{
"name": "filp/whoops",
"version": "2.17.0",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "075bc0c26631110584175de6523ab3f1652eb28e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/075bc0c26631110584175de6523ab3f1652eb28e",
"reference": "075bc0c26631110584175de6523ab3f1652eb28e",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3",
"symfony/var-dumper": "^4.0 || ^5.0"
},
"suggest": {
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
}
},
"autoload": {
"psr-4": {
"Whoops\\": "src/Whoops/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Filipe Dobreira",
"homepage": "https://github.com/filp",
"role": "Developer"
}
],
"description": "php error handling for cool kids",
"homepage": "https://filp.github.io/whoops/",
"keywords": [
"error",
"exception",
"handling",
"library",
"throwable",
"whoops"
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.17.0"
},
"funding": [
{
"url": "https://github.com/denis-sokolov",
"type": "github"
}
],
"time": "2025-01-25T12:00:00+00:00"
},
{
"name": "phpstan/phpstan",
"version": "2.1.2",

View file

@ -15,9 +15,6 @@ parameters:
-
identifier: variable.undefined
path: public-legacy/forum/posting.php
-
identifier: variable.undefined
path: public-legacy/forum/topic.php
-
identifier: variable.undefined
path: public-legacy/manage/changelog/tag.php

View file

@ -7,15 +7,13 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_CONFIG_MANAGE))
Template::throwError(403);
$valueName = (string)filter_input(INPUT_GET, 'name');
$valueInfo = $msz->config->getValueInfo($valueName);
$valueInfo = $msz->config->getValueInfo((string)filter_input(INPUT_GET, 'name'));
if($valueInfo === null)
Template::throwError(404);
if($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$valueName = $valueInfo->getName();
$msz->createAuditLog('CONFIG_DELETE', [$valueName]);
$msz->config->removeValues($valueName);
$msz->createAuditLog('CONFIG_DELETE', [$valueInfo->name]);
$msz->config->removeValues($valueInfo->name);
Tools::redirect($msz->urls->format('manage-general-settings'));
return;
}

View file

@ -19,9 +19,9 @@ if(!empty($sName)) {
$sInfo = $loadValueInfo();
if($sInfo !== null) {
$isNew = false;
$sName = $sInfo->getName();
$sType = $sInfo->getType();
$sValue = $sInfo->getValue();
$sName = $sInfo->name;
$sType = $sInfo->type;
$sValue = $sInfo->value;
}
}

View file

@ -174,7 +174,7 @@ if(CSRF::validateRequest() && $canEdit) {
if(!empty($_POST['colour']['enable'])) {
$setColour = \Index\Colour\Colour::parse((string)($_POST['colour']['hex'] ?? ''));
if($setColour->shouldInherit())
if($setColour->inherits)
$notices[] = 'Invalid colour specified.';
}

View file

@ -9,21 +9,22 @@ require_once __DIR__ . '/../misuzu.php';
if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
die('Misuzu is not initialised.');
set_exception_handler(function(\Throwable $ex) {
\Sentry\captureException($ex);
if(class_exists(\Whoops\Run::class))
(function($whoops) {
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
})(new \Whoops\Run);
else
set_exception_handler(function(\Throwable $ex) {
\Sentry\captureException($ex);
http_response_code(500);
ob_clean();
http_response_code(500);
ob_clean();
if(MSZ_DEBUG) {
header('Content-Type: text/plain; charset=utf-8');
echo (string)$ex;
} else {
header('Content-Type: text/html; charset=utf-8');
echo file_get_contents(MSZ_TEMPLATES . '/500.html');
}
exit;
});
exit;
});
// The whole wall of shit before the router setup and dispatch should be worked away
// Lockdown things should be middleware when there's no more legacy files
@ -129,8 +130,8 @@ CSRF::init(
$router = $msz->createRouting($request);
$msz->startTemplating();
if(in_array('main', $env->getArray(sprintf('domain:%s', $request->getHeaderLine('Host'))))) {
$mszRequestPath = substr($request->getPath(), 1);
if(in_array('main', $msz->env->getArray(sprintf('domain:%s', $request->getHeaderLine('Host'))))) {
$mszRequestPath = substr($request->path, 1);
$mszLegacyPathPrefix = MSZ_PUBLIC . '-legacy/';
$mszLegacyPath = $mszLegacyPathPrefix . $mszRequestPath;

View file

@ -137,7 +137,7 @@ class Sessions {
$stmt->nextParameter($countryCode);
$stmt->execute();
return $this->getSession(sessionId: (string)$this->dbConn->getLastInsertId());
return $this->getSession(sessionId: (string)$stmt->lastInsertId);
}
/**

View file

@ -17,9 +17,7 @@ class Changelog {
/** @var array<string, ChangeTagInfo> */
private array $tags = [];
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -213,7 +211,7 @@ class Changelog {
$stmt->nextParameter($body);
$stmt->execute();
return $this->getChange((string)$this->dbConn->getLastInsertId());
return $this->getChange((string)$stmt->lastInsertId);
}
public function deleteChange(ChangeInfo|string $infoOrId): void {
@ -332,7 +330,7 @@ class Changelog {
$stmt->nextParameter($archived ? 1 : 0);
$stmt->execute();
return $this->getTag((string)$this->dbConn->getLastInsertId());
return $this->getTag((string)$stmt->lastInsertId);
}
public function deleteTag(ChangeTagInfo|string $infoOrId): void {

View file

@ -4,16 +4,16 @@ namespace Misuzu\Changelog;
use ErrorException;
use RuntimeException;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Syndication\FeedBuilder;
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{Pagination,SiteInfo,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Comments\{Comments,CommentsEx};
use Misuzu\Users\UsersContext;
final class ChangelogRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private SiteInfo $siteInfo,
@ -130,17 +130,17 @@ final class ChangelogRoutes implements RouteHandler, UrlSource {
$changes = $this->changelog->getChanges(pagination: new Pagination(10));
$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'));
$feed->title = sprintf('%s » Changelog', $siteName);
$feed->description = sprintf('Live feed of changes to %s.', $siteName);
$feed->contentUrl = $siteUrl . $this->urls->format('changelog-index');
$feed->feedUrl = $siteUrl . $this->urls->format('changelog-feed');
foreach($changes as $change)
$feed->createEntry(function($item) use ($change, $siteUrl) {
$item->setTitle(sprintf('%s: %s', $change->actionText, $change->summary));
$item->setCreatedAt($change->createdTime);
$item->setContentUrl($siteUrl . $this->urls->format('changelog-change', ['change' => $change->id]));
$item->setCommentsUrl($siteUrl . $this->urls->format('changelog-change-comments', ['change' => $change->id]));
$item->title = sprintf('%s: %s', $change->actionText, $change->summary);
$item->createdAt = $change->createdTime;
$item->contentUrl = $siteUrl . $this->urls->format('changelog-change', ['change' => $change->id]);
$item->commentsUrl = $siteUrl . $this->urls->format('changelog-change-comments', ['change' => $change->id]);
});
return $feed->toXmlString();

View file

@ -6,10 +6,10 @@ use JsonSerializable;
use RuntimeException;
use Stringable;
use DeviceDetector\{ClientHints,DeviceDetector};
use Index\Json\{JsonProperty,JsonSerializableTrait};
use Index\Json\{JsonProperty,JsonSerializableCommon};
class ClientInfo implements Stringable, JsonSerializable {
use JsonSerializableTrait;
use JsonSerializableCommon;
private const SERIALIZE_VERSION = 1;

View file

@ -10,9 +10,7 @@ use Misuzu\Users\UserInfo;
class Comments {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -150,7 +148,7 @@ class Comments {
$stmt->nextParameter($owner);
$stmt->execute();
return $this->getCategory(categoryId: (string)$this->dbConn->getLastInsertId());
return $this->getCategory(categoryId: (string)$stmt->lastInsertId);
}
public function deleteCategory(CommentsCategoryInfo|string $category): void {
@ -379,7 +377,7 @@ class Comments {
$stmt->nextParameter($pin ? 1 : 0);
$stmt->execute();
return $this->getPost((string)$this->dbConn->getLastInsertId());
return $this->getPost((string)$stmt->lastInsertId);
}
public function deletePost(CommentsPostInfo|string $infoOrId): void {

View file

@ -14,9 +14,7 @@ class Emotes {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -107,7 +105,7 @@ class Emotes {
$stmt->nextParameter($order);
$stmt->execute();
return $this->getEmote((string)$this->dbConn->getLastInsertId());
return $this->getEmote((string)$stmt->lastInsertId);
}
public function deleteEmote(EmoteInfo|string $infoOrId): void {

View file

@ -4,14 +4,14 @@ namespace Misuzu\Forum;
use stdClass;
use RuntimeException;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpGet,HttpPost,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Pagination,Perm,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Users\UsersContext;
class ForumCategoriesRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private ForumContext $forum,
@ -22,7 +22,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
#[HttpGet('/forum')]
#[UrlFormat('forum-index', '/forum')]
#[UrlFormat('forum-category-root', '/forum', fragment: '<forum>')]
public function getIndex() {
public function getIndex(): string {
$cats = $this->forum->categories->getCategories(hidden: false, asTree: true);
// Filtering! This really needs cleaning up...
@ -38,7 +38,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
$unread = false;
// This is not fully recursive, idk why... probably shove this into ForumContext?
if($category->info->mayHaveChildren && !$unread)
if($category->info->mayHaveChildren)
foreach($category->children as $childId => $child) {
$childPerms = $this->authInfo->getPerms('forum', $child->info);
if(!$childPerms->check(Perm::F_CATEGORY_LIST)) {
@ -129,8 +129,8 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
$root->children = [];
}
$cats['0']->children[$categoryId] = $category;
unset($cats[$categoryId]);
$cats['0']->children[$category->id] = $category;
unset($cats[$category->id]);
if($category->info->mayHaveChildren || $category->info->mayHaveTopics) {
$catIds = [$category->info->id];
@ -172,7 +172,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
#[HttpGet('/forum/([0-9]+)')]
#[UrlFormat('forum-category', '/forum/<forum>', ['page' => '<page>'])]
public function getCategory(HttpResponseBuilder $response, HttpRequest $request, string $catId) {
public function getCategory(HttpResponseBuilder $response, HttpRequest $request, string $catId): mixed {
try {
$category = $this->forum->categories->getCategory(categoryId: $catId);
} catch(RuntimeException $ex) {
@ -186,7 +186,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
if($category->isLink) {
$this->forum->categories->incrementCategoryClicks($category);
$response->redirect($category->linkTarget ?? '/');
return;
return 301;
}
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo))
@ -209,7 +209,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
foreach($children as $childId => $child) {
$childPerms = $this->authInfo->getPerms('forum', $child->info);
if(!$childPerms->check(Perm::F_CATEGORY_LIST)) {
unset($category->children[$childId]);
unset($children[$childId]);
continue;
}
@ -330,7 +330,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/mark-as-read')]
#[UrlFormat('forum-mark-as-read', '/forum/mark-as-read', ['cat' => '<category>', 'rec' => '<recursive>'])]
public function postMarkAsRead(HttpResponseBuilder $response, HttpRequest $request) {
public function postMarkAsRead(HttpResponseBuilder $response, HttpRequest $request): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -341,13 +341,12 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
$catId = (string)$request->getParam('cat', FILTER_SANITIZE_NUMBER_INT);
$recursive = !empty($request->getParam('rec'));
// root category purge must be recursive
if($categoryId === '')
return 400;
if($catId === '') {
if(!$recursive)
return 400;
if($catId === '')
$cats = $this->forum->categories->getCategories();
elseif($recursive)
} elseif($recursive)
$cats = $this->forum->categories->getCategoryChildren(parentInfo: $catId, includeSelf: true);
else
try {
@ -357,7 +356,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
}
if(empty($cats)) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:category:none',
@ -376,7 +375,7 @@ class ForumCategoriesRoutes implements RouteHandler, UrlSource {
}
if(!$success) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:category:access',

View file

@ -53,7 +53,7 @@ class ForumPostInfo {
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
}
private static ?CarbonImmutable $markAsEditedThreshold = null; // @phpstan-ignore-line: property hook issue nope, it's written to!
private static ?CarbonImmutable $markAsEditedThreshold = null;
public bool $shouldMarkAsEdited {
get {
@ -71,7 +71,7 @@ class ForumPostInfo {
get => $this->editedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->editedTime);
}
private static ?CarbonImmutable $canBeDeletedThreshold = null; // @phpstan-ignore-line: property hook issue nope, it's written to!
private static ?CarbonImmutable $canBeDeletedThreshold = null;
public bool $canBeDeleted {
get {

View file

@ -12,9 +12,7 @@ use Misuzu\Users\UserInfo;
class ForumPosts {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -293,7 +291,7 @@ class ForumPosts {
$stmt->nextParameter($displaySignature ? 1 : 0);
$stmt->execute();
return $this->getPost(postId: (string)$this->dbConn->getLastInsertId());
return $this->getPost(postId: (string)$stmt->lastInsertId);
}
public function updatePost(

View file

@ -3,15 +3,15 @@ namespace Misuzu\Forum;
use RuntimeException;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpDelete,HttpGet,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpDelete,HttpGet,HttpPost,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Perm};
use Misuzu\AuditLog\AuditLog;
use Misuzu\Auth\AuthInfo;
use Misuzu\Users\UsersContext;
class ForumPostsRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private UrlRegistry $urls,
@ -23,7 +23,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
#[HttpGet('/forum/posts/([0-9]+)')]
#[UrlFormat('forum-post', '/forum/posts/<post>')]
public function getPost(HttpResponseBuilder $response, HttpRequest $request, string $postId) {
public function getPost(HttpResponseBuilder $response, HttpRequest $request, string $postId): mixed {
try {
$post = $this->forum->posts->getPost(postId: $postId);
} catch(RuntimeException $ex) {
@ -45,16 +45,18 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
);
$pageNumber = ((int)floor($postsCount / 10)) + 1; // epic magic number
return $response->redirect($this->urls->format('forum-topic', [
$response->redirect($this->urls->format('forum-topic', [
'topic' => $post->topicId,
'page' => $pageNumber,
'topic_fragment' => sprintf('p%s', $post->id),
]));
return 302;
}
#[HttpDelete('/forum/posts/([0-9]+)')]
#[UrlFormat('forum-post-delete', '/forum/posts/<post>')]
public function deletePost(HttpResponseBuilder $response, HttpRequest $request, string $postId) {
public function deletePost(HttpResponseBuilder $response, HttpRequest $request, string $postId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -62,8 +64,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -78,7 +80,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
deleted: false,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:post:none',
@ -89,7 +91,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $post->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:access',
@ -101,7 +103,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$topic = $this->forum->topics->getTopic(postInfo: $post);
if($topic->deleted) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:post:none',
@ -111,7 +113,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if($topic->locked) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:delete:lock',
@ -121,7 +123,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_OWN)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:delete:access',
@ -131,7 +133,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if($post->userId !== $this->authInfo->userId) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:delete:own',
@ -143,7 +145,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
// posts may only be deleted within a week of creation, this should be a config value
$deleteTimeFrame = 60 * 60 * 24 * 7;
if($post->createdTime < time() - $deleteTimeFrame) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:delete:age',
@ -155,7 +157,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$originalPost = $this->forum->posts->getPost(topicInfo: $post->topicId);
if($originalPost->id === $post->id) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:delete:opening',
@ -166,7 +168,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -180,8 +182,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_POST_DELETE',
[$post->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -189,7 +191,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/posts/([0-9]+)/nuke')]
#[UrlFormat('forum-post-nuke', '/forum/posts/<post>/nuke')]
public function postPostNuke(HttpResponseBuilder $response, HttpRequest $request, string $postId) {
public function postPostNuke(HttpResponseBuilder $response, HttpRequest $request, string $postId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -197,8 +199,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -213,7 +215,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
deleted: true,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:post:none',
@ -225,7 +227,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $post->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:access',
@ -235,7 +237,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:nuke:access',
@ -246,7 +248,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:post:archived',
@ -260,8 +262,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_POST_NUKE',
[$post->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -269,7 +271,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/posts/([0-9]+)/restore')]
#[UrlFormat('forum-post-restore', '/forum/posts/<post>/restore')]
public function postPostRestore(HttpResponseBuilder $response, HttpRequest $request, string $postId) {
public function postPostRestore(HttpResponseBuilder $response, HttpRequest $request, string $postId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -277,8 +279,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -293,7 +295,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
deleted: true,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:post:none',
@ -305,7 +307,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $post->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:access',
@ -315,7 +317,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:post:restore:access',
@ -326,7 +328,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:post:archived',
@ -340,8 +342,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_POST_RESTORE',
[$post->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;

View file

@ -101,7 +101,7 @@ class ForumTopicInfo {
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
}
private static ?CarbonImmutable $lastActiveAt = null; // @phpstan-ignore-line: property hook issue nope, it's written to!
private static ?CarbonImmutable $lastActiveAt = null;
public bool $active {
get {

View file

@ -9,11 +9,9 @@ use Misuzu\Pagination;
use Misuzu\Users\UserInfo;
class ForumTopics {
private DbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(DbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
@ -263,7 +261,7 @@ class ForumTopics {
$stmt->nextParameter($title);
$stmt->execute();
return $this->getTopic(topicId: (string)$this->dbConn->getLastInsertId());
return $this->getTopic(topicId: (string)$stmt->lastInsertId);
}
public function updateTopic(

View file

@ -4,18 +4,17 @@ namespace Misuzu\Forum;
use stdClass;
use RuntimeException;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpDelete,HttpGet,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpDelete,HttpGet,HttpPost,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Pagination,Perm,Template};
use Misuzu\AuditLog\AuditLog;
use Misuzu\Auth\AuthInfo;
use Misuzu\Users\UsersContext;
class ForumTopicsRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private UrlRegistry $urls,
private ForumContext $forum,
private UsersContext $usersCtx,
private AuditLog $auditLog,
@ -24,22 +23,19 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpGet('/forum/topics/([0-9]+)')]
#[UrlFormat('forum-topic', '/forum/topics/<topic>', ['page' => '<page>'], '<topic_fragment>')]
public function getTopic(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function getTopic(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
$isNuked = $deleted = $canDeleteAny = false;
try {
$isNuked = $deleted = $canDeleteAny = false;
$topic = $this->forum->topics->getTopic(topicId: $topicId);
} catch(RuntimeException $ex) {
$isNuked = true;
}
if(!$isNuked) {
$deleted = $topic->deleted;
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo))
$perms = $perms->apply(fn($calc) => $calc & (Perm::F_CATEGORY_LIST | Perm::F_CATEGORY_VIEW));
$canDeleteAny = $perms->check(Perm::F_POST_DELETE_ANY);
} catch(RuntimeException $ex) {
$isNuked = true;
}
if($isNuked || $deleted) {
@ -49,7 +45,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
if($isNuked || !$canDeleteAny) {
$response->redirect($redirect->linkTarget);
return;
return 301;
}
}
@ -57,7 +53,9 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 404;
}
if(!$perms->check(Perm::F_CATEGORY_VIEW))
if(empty($topic))
return 404;
if(empty($perms) || !$perms->check(Perm::F_CATEGORY_VIEW))
return 403;
$postsCount = $topic->postsCount;
@ -150,7 +148,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpDelete('/forum/topics/([0-9]+)')]
#[UrlFormat('forum-topic-delete', '/forum/topics/<topic>')]
public function deleteTopic(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function deleteTopic(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -158,8 +156,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -174,7 +172,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: false,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -186,7 +184,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -197,7 +195,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
if($topic->locked || !$perms->check(Perm::F_POST_DELETE_OWN)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:delete:access',
@ -207,7 +205,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if($topic->userId !== $this->authInfo->userId) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:delete:own',
@ -219,7 +217,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
// topics may only be deleted within a day of creation, this should be a config value
$deleteTimeFrame = 60 * 60 * 24;
if($topic->createdTime < time() - $deleteTimeFrame) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:delete:age',
@ -235,7 +233,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
// deleted posts are intentionally included
$topicPostCount = $this->forum->posts->countPosts(topicInfo: $topic);
if($topicPostCount > $deletePostThreshold) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:delete:replies',
@ -247,7 +245,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -261,8 +259,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_DELETE',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -270,7 +268,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/topics/([0-9]+)/restore')]
#[UrlFormat('forum-topic-restore', '/forum/topics/<topic>/restore')]
public function postTopicRestore(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function postTopicRestore(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -278,8 +276,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -294,7 +292,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: true,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -306,7 +304,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -316,7 +314,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:restore:access',
@ -327,7 +325,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -341,8 +339,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_RESTORE',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -350,7 +348,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/topics/([0-9]+)/nuke')]
#[UrlFormat('forum-topic-nuke', '/forum/topics/<topic>/nuke')]
public function postTopicNuke(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function postTopicNuke(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -358,8 +356,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -374,7 +372,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: true,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -386,7 +384,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -396,7 +394,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:nuke:access',
@ -407,7 +405,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -421,8 +419,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_NUKE',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -430,7 +428,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/topics/([0-9]+)/bump')]
#[UrlFormat('forum-topic-bump', '/forum/topics/<topic>/bump')]
public function postTopicBump(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function postTopicBump(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -438,8 +436,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -454,7 +452,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: false,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -466,7 +464,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -476,7 +474,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_TOPIC_BUMP)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:bump:access',
@ -487,7 +485,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -501,8 +499,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_BUMP',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -510,7 +508,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/topics/([0-9]+)/lock')]
#[UrlFormat('forum-topic-lock', '/forum/topics/<topic>/lock')]
public function postTopicLock(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function postTopicLock(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -518,8 +516,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -534,7 +532,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: false,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -546,7 +544,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -556,7 +554,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_TOPIC_LOCK)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:lock:access',
@ -566,7 +564,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if($topic->locked) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:lock:already',
@ -577,7 +575,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -591,8 +589,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_LOCK',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;
@ -600,7 +598,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
#[HttpPost('/forum/topics/([0-9]+)/unlock')]
#[UrlFormat('forum-topic-unlock', '/forum/topics/<topic>/unlock')]
public function postTopicUnlock(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function postTopicUnlock(HttpResponseBuilder $response, HttpRequest $request, string $topicId): mixed {
if(!$this->authInfo->isLoggedIn)
return 401;
@ -608,8 +606,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
return 403;
$response->setHeader('X-CSRF-Token', CSRF::token());
if($this->usersCtx->hasActiveBan($this->authInfo->authInfo)) {
$response->setStatusCode(403);
if($this->usersCtx->hasActiveBan($this->authInfo->userInfo)) {
$response->statusCode = 403;
return [
'error' => [
'name' => 'user:banned',
@ -624,7 +622,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
deleted: false,
);
} catch(RuntimeException $ex) {
$response->setStatusCode(404);
$response->statusCode = 404;
return [
'error' => [
'name' => 'forum:topic:none',
@ -636,7 +634,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$perms = $this->authInfo->getPerms('forum', $topic->categoryId);
if(!$perms->check(Perm::F_CATEGORY_VIEW)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:access',
@ -646,7 +644,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_TOPIC_LOCK)) {
$response->setStatusCode(403);
$response->statusCode = 403;
return [
'error' => [
'name' => 'forum:topic:lock:access',
@ -656,7 +654,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
if(!$topic->locked) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:lock:not',
@ -667,7 +665,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$category = $this->forum->categories->getCategory(topicInfo: $topic);
if($category->archived) {
$response->setStatusCode(400);
$response->statusCode = 400;
return [
'error' => [
'name' => 'forum:topic:archived',
@ -681,8 +679,8 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
$this->authInfo->userInfo,
'FORUM_TOPIC_UNLOCK',
[$topic->id],
$request->getRemoteAddress(),
$request->getCountryCode()
$request->remoteAddress,
$request->countryCode
);
return 204;

View file

@ -7,8 +7,8 @@ use Index\Config\Config;
use Index\Colour\Colour;
use Index\Db\{DbConnection,DbTools};
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceCommon};
use Misuzu\{Pagination,SiteInfo,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Changelog\Changelog;
@ -18,7 +18,7 @@ use Misuzu\News\{News,NewsCategoryInfo,NewsPostInfo};
use Misuzu\Users\{UsersContext,UserInfo};
class HomeRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private Config $config,

View file

@ -2,13 +2,13 @@
namespace Misuzu\Info;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlSource,UrlSourceCommon};
use Misuzu\Template;
use Misuzu\Parsers\Parser;
class InfoRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
private const DOCS_PATH = MSZ_ROOT . '/docs';
private const PROJECT_PATHS = [

View file

@ -2,11 +2,11 @@
namespace Misuzu;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource};
class LegacyRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait;
use RouteHandlerCommon;
public function __construct(
private UrlRegistry $urls

View file

@ -8,8 +8,8 @@ use Index\XString;
use Index\Config\Config;
use Index\Colour\Colour;
use Index\Http\{FormHttpContent,HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpGet,HttpMiddleware,HttpPost,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Pagination,Perm,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Parsers\Parser;
@ -17,7 +17,7 @@ use Misuzu\Perms\Permissions;
use Misuzu\Users\{UsersContext,UserInfo};
class MessagesRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public const FOLDER_META = [
'inbox' => [ 'title' => 'Inbox', 'icon' => 'fas fa-inbox fa-fw' ],
@ -55,9 +55,8 @@ class MessagesRoutes implements RouteHandler, UrlSource {
$this->canSendMessages = $globalPerms->check(Perm::G_MESSAGES_SEND)
&& !$this->usersCtx->hasActiveBan($this->authInfo->userInfo);
if($request->getMethod() === 'POST') {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if($request->method === 'POST') {
if(!($request->content instanceof FormHttpContent))
return 400;
if(!CSRF::validate($request->getHeaderLine('x-csrf-token')))
@ -178,11 +177,10 @@ class MessagesRoutes implements RouteHandler, UrlSource {
if(!$this->canSendMessages)
return 403;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$name = trim((string)$content->getParam('name'));
$name = trim((string)$request->content->getParam('name'));
// flappy hacks
if(str_starts_with(mb_strtolower($name), 'flappyzor'))
@ -363,16 +361,15 @@ class MessagesRoutes implements RouteHandler, UrlSource {
if(!$this->canSendMessages)
return 403;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$recipient = (string)$content->getParam('recipient');
$replyTo = (string)$content->getParam('reply');
$title = (string)$content->getParam('title');
$body = (string)$content->getParam('body');
$parser = (int)$content->getParam('parser', FILTER_SANITIZE_NUMBER_INT);
$draft = !empty($content->getParam('draft'));
$recipient = (string)$request->content->getParam('recipient');
$replyTo = (string)$request->content->getParam('reply');
$title = (string)$request->content->getParam('title');
$body = (string)$request->content->getParam('body');
$parser = (int)$request->content->getParam('parser', FILTER_SANITIZE_NUMBER_INT);
$draft = !empty($request->content->getParam('draft'));
$error = $this->checkMessageFields($title, $body, $parser);
if($error !== null)
@ -468,14 +465,13 @@ class MessagesRoutes implements RouteHandler, UrlSource {
if(!$this->canSendMessages)
return 403;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$title = (string)$content->getParam('title');
$body = (string)$content->getParam('body');
$parser = (int)$content->getParam('parser', FILTER_SANITIZE_NUMBER_INT);
$draft = !empty($content->getParam('draft'));
$title = (string)$request->content->getParam('title');
$body = (string)$request->content->getParam('body');
$parser = (int)$request->content->getParam('parser', FILTER_SANITIZE_NUMBER_INT);
$draft = !empty($request->content->getParam('draft'));
$error = $this->checkMessageFields($title, $body, $parser);
if($error !== null)
@ -558,12 +554,11 @@ class MessagesRoutes implements RouteHandler, UrlSource {
#[HttpPost('/messages/mark')]
#[UrlFormat('messages-mark', '/messages/mark')]
public function postMark(HttpResponseBuilder $response, HttpRequest $request): int|array {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$type = (string)$content->getParam('type');
$messages = explode(',', (string)$content->getParam('messages'));
$type = (string)$request->content->getParam('type');
$messages = explode(',', (string)$request->content->getParam('messages'));
if($type !== 'read' && $type !== 'unread')
return [
@ -590,11 +585,10 @@ class MessagesRoutes implements RouteHandler, UrlSource {
#[HttpPost('/messages/delete')]
#[UrlFormat('messages-delete', '/messages/delete')]
public function postDelete(HttpResponseBuilder $response, HttpRequest $request): int|array {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$messages = (string)$content->getParam('messages');
$messages = (string)$request->content->getParam('messages');
if($messages === '')
return [
'error' => [
@ -617,11 +611,10 @@ class MessagesRoutes implements RouteHandler, UrlSource {
#[HttpPost('/messages/restore')]
#[UrlFormat('messages-restore', '/messages/restore')]
public function postRestore(HttpResponseBuilder $response, HttpRequest $request) {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$messages = (string)$content->getParam('messages');
$messages = (string)$request->content->getParam('messages');
if($messages === '')
return [
'error' => [
@ -644,11 +637,10 @@ class MessagesRoutes implements RouteHandler, UrlSource {
#[HttpPost('/messages/nuke')]
#[UrlFormat('messages-nuke', '/messages/nuke')]
public function postNuke(HttpResponseBuilder $response, HttpRequest $request) {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$messages = (string)$content->getParam('messages');
$messages = (string)$request->content->getParam('messages');
if($messages === '')
return [
'error' => [

View file

@ -14,7 +14,7 @@ use Misuzu\News\News;
use Misuzu\Perms\Permissions;
use Misuzu\Profile\ProfileFields;
use Misuzu\Redirects\RedirectsContext;
use Misuzu\Routing\{BackedRoutingContext,RoutingContext};
use Misuzu\Routing\BackedRoutingContext;
use Misuzu\Users\{UsersContext,UserInfo};
use RPCii\HmacVerificationProvider;
use RPCii\Server\HttpRpcServer;
@ -150,7 +150,7 @@ class MisuzuContext {
Template::init($this->templating);
}
public function createRouting(HttpRequest $request): RoutingContext {
public function createRouting(HttpRequest $request): BackedRoutingContext {
$prefix = sprintf('domain:%s', $request->getHeaderLine('Host'));
$hostInfo = $this->env->scopeTo($prefix);
$purposes = $this->env->getArray($prefix);
@ -209,7 +209,6 @@ class MisuzuContext {
$this->authInfo,
));
$scopedCtx->register(new \Misuzu\Forum\ForumTopicsRoutes(
$this->urls,
$this->forumCtx,
$this->usersCtx,
$this->auditLog,

View file

@ -12,9 +12,7 @@ use Misuzu\Users\UserInfo;
class News {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -27,13 +25,11 @@ class News {
if($hasHidden)
$query .= sprintf(' WHERE category_is_hidden %s 0', $hidden ? '<>' : '=');
$result = $this->dbConn->query($query);
$count = 0;
$stmt = $this->cache->get($query);
$stmt->execute();
if($result->next())
$count = $result->getInteger(0);
return $count;
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
/** @return \Iterator<int, NewsCategoryInfo> */
@ -119,7 +115,7 @@ class News {
$stmt->nextParameter($hidden ? 1 : 0);
$stmt->execute();
return $this->getCategory(categoryId: (string)$this->dbConn->getLastInsertId());
return $this->getCategory(categoryId: (string)$stmt->lastInsertId);
}
public function deleteCategory(NewsCategoryInfo|string $infoOrId): void {
@ -306,7 +302,7 @@ class News {
$stmt->nextParameter($schedule);
$stmt->execute();
return $this->getPost((string)$this->dbConn->getLastInsertId());
return $this->getPost((string)$stmt->lastInsertId);
}
public function deletePost(NewsPostInfo|string $postInfo): void {

View file

@ -4,9 +4,9 @@ namespace Misuzu\News;
use RuntimeException;
use Index\Colour\Colour;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Syndication\FeedBuilder;
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{Pagination,SiteInfo,Template};
use Misuzu\Auth\AuthInfo;
use Misuzu\Comments\{Comments,CommentsCategory,CommentsEx};
@ -14,7 +14,7 @@ use Misuzu\Parsers\Parser;
use Misuzu\Users\{UsersContext,UserInfo};
class NewsRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private SiteInfo $siteInfo,
@ -192,15 +192,15 @@ class NewsRoutes implements RouteHandler, UrlSource {
$feed = new FeedBuilder;
if($hasCategory) {
$feed->setTitle(sprintf('%s » %s', $siteName, $categoryInfo->name));
$feed->setDescription($categoryInfo->description);
$feed->setContentUrl($siteUrl . $this->urls->format('news-category', ['category' => $categoryInfo->id]));
$feed->setFeedUrl($siteUrl . $this->urls->format('news-category-feed', ['category' => $categoryInfo->id]));
$feed->title = sprintf('%s » %s', $siteName, $categoryInfo->name);
$feed->description = $categoryInfo->description;
$feed->contentUrl = $siteUrl . $this->urls->format('news-category', ['category' => $categoryInfo->id]);
$feed->feedUrl = $siteUrl . $this->urls->format('news-category-feed', ['category' => $categoryInfo->id]);
} 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'));
$feed->title = sprintf('%s » Featured News', $siteName);
$feed->description = 'A live featured news feed.';
$feed->contentUrl = $siteUrl . $this->urls->format('news-index');
$feed->feedUrl = $siteUrl . $this->urls->format('news-feed');
}
$feedUpdatedAt = 0;
@ -209,23 +209,23 @@ class NewsRoutes implements RouteHandler, UrlSource {
$postInfo = $post['post'];
$userInfo = $post['user'];
$item->setTitle($postInfo->title);
$item->setDescription(Parser::instance(Parser::MARKDOWN)->parseText($postInfo->body));
$item->setCreatedAt($postInfo->createdTime);
$item->setContentUrl($siteUrl . $this->urls->format('news-post', ['post' => $postInfo->id]));
$item->setCommentsUrl($siteUrl . $this->urls->format('news-post-comments', ['post' => $postInfo->id]));
$item->title = $postInfo->title;
$item->description = Parser::instance(Parser::MARKDOWN)->parseText($postInfo->body);
$item->createdAt = $postInfo->createdTime;
$item->contentUrl = $siteUrl . $this->urls->format('news-post', ['post' => $postInfo->id]);
$item->commentsUrl = $siteUrl . $this->urls->format('news-post-comments', ['post' => $postInfo->id]);
if($userInfo !== null) {
$item->setAuthorName($userInfo->name);
$item->setAuthorUrl($siteUrl . $this->urls->format('user-profile', ['user' => $userInfo->id]));
$item->authorName = $userInfo->name;
$item->authorUrl = $siteUrl . $this->urls->format('user-profile', ['user' => $userInfo->id]);
}
$itemUpdatedAt = $postInfo->updatedTime;
if($feedUpdatedAt < $itemUpdatedAt) {
$feed->setUpdatedAt($feedUpdatedAt = $itemUpdatedAt);
$feed->updatedAt = $feedUpdatedAt = $itemUpdatedAt;
if($postInfo->createdTime < $itemUpdatedAt)
$item->setUpdatedAt($itemUpdatedAt);
$item->updatedAt = $itemUpdatedAt;
}
});

View file

@ -3,20 +3,18 @@ namespace Misuzu\Redirects;
use Index\Config\Config;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
class AliasRedirectsRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
private Config $config;
public function __construct(
private RedirectsContext $redirectsCtx,
) {
public function __construct(RedirectsContext $redirectsCtx) {
$this->config = $redirectsCtx->config->scopeTo('alias');
}
private function redirect(HttpResponseBuilder $response, HttpRequest $request, string $configKey, string $value) {
private function redirect(HttpResponseBuilder $response, HttpRequest $request, string $configKey, string $value): void {
$url = sprintf($this->config->getString($configKey), rawurlencode($value));
$params = $request->getParamString();
@ -28,22 +26,22 @@ class AliasRedirectsRoutes implements RouteHandler {
#[HttpGet('/[up]([0-9]+)')]
#[HttpGet('/[up]/([A-Za-z0-9\-_]+)')]
public function getProfileRedirect(HttpResponseBuilder $response, HttpRequest $request, string $userId) {
public function getProfileRedirect(HttpResponseBuilder $response, HttpRequest $request, string $userId): void {
$this->redirect($response, $request, 'user_profile', $userId);
}
#[HttpGet('/fc?/?([0-9]+)')]
public function getForumCategoryRedirect(HttpResponseBuilder $response, HttpRequest $request, string $categoryId) {
public function getForumCategoryRedirect(HttpResponseBuilder $response, HttpRequest $request, string $categoryId): void {
$this->redirect($response, $request, 'forum_category', $categoryId);
}
#[HttpGet('/ft/?([0-9]+)')]
public function getForumTopicRedirect(HttpResponseBuilder $response, HttpRequest $request, string $topicId) {
public function getForumTopicRedirect(HttpResponseBuilder $response, HttpRequest $request, string $topicId): void {
$this->redirect($response, $request, 'forum_topic', $topicId);
}
#[HttpGet('/fp/?([0-9]+)')]
public function getForumPostRedirect(HttpResponseBuilder $response, HttpRequest $request, string $postId) {
public function getForumPostRedirect(HttpResponseBuilder $response, HttpRequest $request, string $postId): void {
$this->redirect($response, $request, 'forum_post', $postId);
}
}

View file

@ -21,7 +21,7 @@ class IncrementalRedirectInfo implements RedirectInfo {
}
public string $id62 {
get => XNumber::toBase62($this->id);
get => XNumber::toBase62((int)$this->id);
}
public CarbonImmutable $createdAt {

View file

@ -11,6 +11,7 @@ class IncrementalRedirectsData {
$this->cache = new DbStatementCache($dbConn);
}
/** @return iterable<IncrementalRedirectInfo> */
public function getIncrementalRedirects(): iterable {
$query = <<<SQL
SELECT redir_id, redir_url, UNIX_TIMESTAMP(redir_created)
@ -56,7 +57,7 @@ class IncrementalRedirectsData {
$stmt->nextParameter($url);
$stmt->execute();
return $this->getIncrementalRedirect((string)$stmt->getLastInsertId());
return $this->getIncrementalRedirect((string)$stmt->lastInsertId);
}
public function deleteIncrementalRedirect(IncrementalRedirectInfo|string $redirectInfo): void {

View file

@ -4,38 +4,41 @@ namespace Misuzu\Redirects;
use RuntimeException;
use Index\XNumber;
use Index\Http\{FormHttpContent,HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,HttpPost,RouteHandler,RouteHandlerCommon};
class IncrementalRedirectsRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
public function __construct(
private RedirectsContext $redirectsCtx,
) {}
#[HttpGet('/[bg]/([A-Za-z0-9]+)')]
public function getIncrementalRedirect(HttpResponseBuilder $response, HttpRequest $request, string $linkId) {
public function getIncrementalRedirect(HttpResponseBuilder $response, HttpRequest $request, string $linkId): int {
$linkId = XNumber::fromBase62($linkId);
if($linkId === false)
return 400;
try {
$redirectInfo = $this->redirectsCtx->incremental->getIncrementalRedirect($linkId);
$redirectInfo = $this->redirectsCtx->incremental->getIncrementalRedirect((string)$linkId);
} catch(RuntimeException $ex) {
return 404;
}
$response->redirect($redirectInfo->url, true);
return 301;
}
/** @return int|array{url: string} */
#[HttpPost('/satori/create')]
public function postIncrementalRedirect(HttpResponseBuilder $response, HttpRequest $request) {
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
public function postIncrementalRedirect(HttpResponseBuilder $response, HttpRequest $request): int|array {
if(!($request->content instanceof FormHttpContent))
return 400;
$config = $this->redirectsCtx->config->scopeTo('incremental');
$url = (string)$content->getParam('u');
$time = (int)$content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$sign = base64_decode((string)$content->getParam('s'));
$url = (string)$request->content->getParam('u');
$time = (int)$request->content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$sign = base64_decode((string)$request->content->getParam('s'));
$hash = hash_hmac('sha256', "satori#create#{$time}#{$url}", $config->getString('secret'), true);
if(!hash_equals($hash, $sign))
@ -51,13 +54,7 @@ class IncrementalRedirectsRoutes implements RouteHandler {
IncrementalRedirectsData::INC_BY_URL
);
} catch(RuntimeException $ex) {
try {
$redirectInfo = $this->redirectsCtx->incremental->createIncrementalRedirect($url);
} catch(\Throwable $ex) {
return [
'url' => (string)$ex,
];
}
$redirectInfo = $this->redirectsCtx->incremental->createIncrementalRedirect($url);
}
return [

View file

@ -2,13 +2,13 @@
namespace Misuzu\Redirects;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
class LandingRedirectsRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
#[HttpGet('/')]
public function getIndex() {
public function getIndex(): string {
return <<<HTML
<!doctype html>
<meta charset=utf-8>

View file

@ -11,6 +11,7 @@ class NamedRedirectsData {
$this->cache = new DbStatementCache($dbConn);
}
/** @return iterable<NamedRedirectInfo> */
public function getNamedRedirects(): iterable {
$query = <<<SQL
SELECT redir_id, redir_vanity, redir_url, redir_clicks, UNIX_TIMESTAMP(redir_created)
@ -63,7 +64,7 @@ class NamedRedirectsData {
$stmt->nextParameter($url);
$stmt->execute();
return $this->getNamedRedirect((string)$stmt->getLastInsertId(), self::NAMED_BY_ID);
return $this->getNamedRedirect((string)$stmt->lastInsertId, self::NAMED_BY_ID);
}
public function deleteNamedRedirect(NamedRedirectInfo|string $redirectInfo): void {

View file

@ -4,21 +4,17 @@ namespace Misuzu\Redirects;
use RuntimeException;
use Index\Config\Config;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
class NamedRedirectsRoutes implements RouteHandler {
use RouteHandlerTrait;
private Config $config;
use RouteHandlerCommon;
public function __construct(
private RedirectsContext $redirectsCtx,
) {
$this->config = $redirectsCtx->config->scopeTo('named');
}
) {}
#[HttpGet('/([A-Za-z0-9\-_]+)')]
public function getNamedRedirect(HttpResponseBuilder $response, HttpRequest $request, string $name) {
public function getNamedRedirect(HttpResponseBuilder $response, HttpRequest $request, string $name): int {
try {
$redirectInfo = $this->redirectsCtx->named->getNamedRedirect(
$name,
@ -34,5 +30,6 @@ class NamedRedirectsRoutes implements RouteHandler {
$url .= (strpos($url, '?') === false ? '?' : '&') . $params;
$response->redirect($url, true);
return 301;
}
}

View file

@ -4,17 +4,17 @@ namespace Misuzu\Redirects;
use InvalidArgumentException;
use Index\Config\Config;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
class SocialRedirectsRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
private Config $config;
private $getWebAssetInfo;
/** @param callable(): object $getWebAssetInfo */
public function __construct(
RedirectsContext $redirectsCtx,
$getWebAssetInfo
private $getWebAssetInfo
) {
$this->config = $redirectsCtx->config->scopeTo('social');
if(!is_callable($getWebAssetInfo))
@ -23,7 +23,7 @@ class SocialRedirectsRoutes implements RouteHandler {
}
#[HttpGet('/bsky/((did:[a-z0-9]+:[A-Za-z0-9.\-_:%]+)|(([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])))')]
public function getBlueskyRedirect(HttpResponseBuilder $response, HttpRequest $request, string $handle) {
public function getBlueskyRedirect(HttpResponseBuilder $response, HttpRequest $request, string $handle): int|string {
$did = null;
if(str_starts_with($handle, 'did:'))
@ -48,7 +48,7 @@ class SocialRedirectsRoutes implements RouteHandler {
$format = $this->config->getString('bsky_profile', 'https://bsky.app/profile/%s');
if(is_string($did)) {
$response->redirect(sprintf($format, $did), true);
return;
return 301;
}
$handle = rawurlencode($handle);
@ -65,7 +65,7 @@ class SocialRedirectsRoutes implements RouteHandler {
}
#[HttpGet('/fedi/([A-Za-z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})')]
public function getFediverseRedirect(HttpResponseBuilder $response, HttpRequest $request, string $userName, string $instance) {
public function getFediverseRedirect(HttpResponseBuilder $response, HttpRequest $request, string $userName, string $instance): string {
$userName = rawurlencode($userName);
$instance = rawurlencode($instance);
$script = ($this->getWebAssetInfo)()->{'redir-fedi.js'} ?? '';

View file

@ -2,15 +2,15 @@
namespace Misuzu\Routing;
use Index\Http\HttpRequest;
use Index\Http\Routing\{HttpRouter,Router,RouteHandler};
use Index\Http\Routing\{HttpRouter,RouteHandler};
use Index\Urls\{ArrayUrlRegistry,UrlRegistry,UrlSource};
class BackedRoutingContext implements RoutingContext {
public private(set) Router $router;
public private(set) HttpRouter $router;
public private(set) UrlRegistry $urls;
public function __construct(
?Router $router = null,
?HttpRouter $router = null,
?UrlRegistry $urls = null
) {
$this->urls = $urls ?? new ArrayUrlRegistry;

View file

@ -8,5 +8,4 @@ use Index\Urls\UrlSource;
interface RoutingContext {
public function register(RouteHandler|UrlSource $handler): void;
public function scopeTo(string $namePrefix, string $pathPrefix): RoutingContext;
public function dispatch(?HttpRequest $request = null, array $args = []): void;
}

View file

@ -6,21 +6,21 @@ use Misuzu\Template;
class RoutingErrorHandler extends HtmlHttpErrorHandler {
public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void {
if(str_starts_with($request->getPath(), '/_')) {
if(str_starts_with($request->path, '/_')) {
$response->setTypePlain();
$response->setContent(sprintf('HTTP %03d', $code));
$response->content = sprintf('HTTP %03d', $code);
return;
}
if($code === 500 || $code === 503) {
$response->setTypeHTML();
$response->setContent(file_get_contents(sprintf('%s/%03d.html', MSZ_TEMPLATES, $code)));
$response->content = file_get_contents(sprintf('%s/%03d.html', MSZ_TEMPLATES, $code));
return;
}
if($code === 401 || $code === 403 || $code === 404) {
$response->setTypeHTML();
$response->setContent(Template::renderRaw(sprintf('errors.%03d', $code)));
$response->content = Template::renderRaw(sprintf('errors.%03d', $code));
return;
}

View file

@ -24,9 +24,4 @@ class ScopedRoutingContext implements RoutingContext {
$this->urls->scopeTo($namePrefix, $pathPrefix)
);
}
/** @param mixed[] $args */
public function dispatch(?HttpRequest $request = null, array $args = []): void {
$this->router->dispatch($request, $args);
}
}

View file

@ -5,14 +5,14 @@ use RuntimeException;
use Index\Colour\Colour;
use Index\Config\Config;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler,RouteHandlerCommon};
use Misuzu\Pagination;
use Misuzu\Forum\ForumContext;
use Misuzu\Profile\ProfileFields;
use Misuzu\Users\UsersContext;
final class SatoriRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
public function __construct(
private Config $config,
@ -34,7 +34,7 @@ final class SatoriRoutes implements RouteHandler {
if(empty($userHash) || $userTime < $currentTime - 60 || $userTime > $currentTime + 60)
return 403;
$verifyText = (string)$userTime . '#' . $request->getPath() . '?' . $request->getParamString();
$verifyText = (string)$userTime . '#' . $request->path . '?' . $request->getParamString();
$verifyHash = hash_hmac('sha256', $verifyText, $secretKey, true);
if(!hash_equals($verifyHash, $userHash))

View file

@ -10,11 +10,11 @@ use Misuzu\Users\{Bans,UsersContext,UserInfo};
use Index\Colour\Colour;
use Index\Config\Config;
use Index\Http\{FormHttpContent,HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HandlerAttribute,HttpDelete,HttpGet,HttpOptions,HttpPost,RouteHandler,RouteHandlerTrait};
use Index\Http\Routing\{HandlerAttribute,HttpDelete,HttpGet,HttpOptions,HttpPost,RouteHandler,RouteHandlerCommon};
use Index\Urls\UrlRegistry;
final class SharpChatRoutes implements RouteHandler {
use RouteHandlerTrait;
use RouteHandlerCommon;
private string $hashKey;
@ -40,7 +40,7 @@ final class SharpChatRoutes implements RouteHandler {
$response->setHeader('Access-Control-Allow-Methods', 'GET');
$response->setHeader('Access-Control-Allow-Headers', 'Cache-Control');
if($request->getMethod() === 'OPTIONS')
if($request->method === 'OPTIONS')
return 204;
$this->counters->increment('dev:legacy_emotes_loads');
@ -108,7 +108,7 @@ final class SharpChatRoutes implements RouteHandler {
$response->setHeader('Vary', 'Origin');
}
if($request->getMethod() === 'OPTIONS')
if($request->method === 'OPTIONS')
return 204;
$tokenInfo = $this->authInfo->tokenInfo;
@ -147,15 +147,14 @@ final class SharpChatRoutes implements RouteHandler {
if(!$request->hasHeader('X-SharpChat-Signature'))
return 400;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$bumpList = $content->getParam('u', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
$bumpList = $request->content->getParam('u', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
if(!is_array($bumpList))
return 400;
$userTime = (int)$content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$userTime = (int)$request->content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$signature = "bump#{$userTime}";
foreach($bumpList as $userId => $ipAddr)
@ -189,13 +188,12 @@ final class SharpChatRoutes implements RouteHandler {
if(!$request->hasHeader('X-SharpChat-Signature'))
return 400;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return ['success' => false, 'reason' => 'request'];
$authMethod = (string)$content->getParam('method');
$authToken = (string)$content->getParam('token');
$ipAddress = (string)$content->getParam('ipaddr');
$authMethod = (string)$request->content->getParam('method');
$authToken = (string)$request->content->getParam('token');
$ipAddress = (string)$request->content->getParam('ipaddr');
$userHash = (string)$request->getHeaderFirstLine('X-SharpChat-Signature');
if(strlen($userHash) !== 64)
@ -404,19 +402,18 @@ final class SharpChatRoutes implements RouteHandler {
if(!$request->hasHeader('X-SharpChat-Signature'))
return 400;
$content = $request->getContent();
if(!($content instanceof FormHttpContent))
if(!($request->content instanceof FormHttpContent))
return 400;
$userHash = (string)$request->getHeaderFirstLine('X-SharpChat-Signature');
$userTime = (int)$content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$userId = (string)$content->getParam('ui', FILTER_SANITIZE_NUMBER_INT);
$userAddr = (string)$content->getParam('ua');
$modId = (string)$content->getParam('mi', FILTER_SANITIZE_NUMBER_INT);
$modAddr = (string)$content->getParam('ma');
$duration = (int)$content->getParam('d', FILTER_SANITIZE_NUMBER_INT);
$isPermanent = (int)$content->getParam('p', FILTER_SANITIZE_NUMBER_INT);
$reason = (string)$content->getParam('r');
$userTime = (int)$request->content->getParam('t', FILTER_SANITIZE_NUMBER_INT);
$userId = (string)$request->content->getParam('ui', FILTER_SANITIZE_NUMBER_INT);
$userAddr = (string)$request->content->getParam('ua');
$modId = (string)$request->content->getParam('mi', FILTER_SANITIZE_NUMBER_INT);
$modAddr = (string)$request->content->getParam('ma');
$duration = (int)$request->content->getParam('d', FILTER_SANITIZE_NUMBER_INT);
$isPermanent = (int)$request->content->getParam('p', FILTER_SANITIZE_NUMBER_INT);
$reason = (string)$request->content->getParam('r');
$signature = implode('#', [
'create', $userTime, $userId, $userAddr,

View file

@ -8,21 +8,12 @@ class SiteInfo {
private array $props; // @phpstan-ignore-line: Seems PHPStan doesn't support property hooks yet :)
public function __construct(Config $config) {
try {
$this->props = $config->getValues([
['name:s', 'Misuzu'],
'desc:s',
'url:s',
'ext_logo:s',
]);
} catch(RuntimeException $ex) {
$this->props = [
'name' => 'Misuzu',
'desc' => '',
'url' => '',
'ext_logo' => '',
];
}
$this->props = $config->getValues([
['name:s', 'Misuzu'],
'desc:s',
'url:s',
'ext_logo:s',
]);
}
public string $name {

View file

@ -4,14 +4,14 @@ namespace Misuzu\Users\Assets;
use InvalidArgumentException;
use RuntimeException;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerTrait};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceTrait};
use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\Perm;
use Misuzu\Auth\AuthInfo;
use Misuzu\Users\{UsersContext,UserInfo};
class AssetsRoutes implements RouteHandler, UrlSource {
use RouteHandlerTrait, UrlSourceTrait;
use RouteHandlerCommon, UrlSourceCommon;
public function __construct(
private AuthInfo $authInfo,
@ -52,7 +52,7 @@ class AssetsRoutes implements RouteHandler, UrlSource {
$this->serveAsset($response, $request, $assetInfo);
}
/** @return int|void */
/** @return string|void */
#[HttpGet('/assets/profile-background')]
#[HttpGet('/assets/profile-background/([0-9]+)(?:\.[a-z]+)?')]
#[UrlFormat('user-background', '/assets/profile-background/<user>')]
@ -70,14 +70,14 @@ class AssetsRoutes implements RouteHandler, UrlSource {
if(!isset($assetInfo)) {
// circumvent the default error page
$response->setContent('Not Found');
return 404;
$response->statusCode = 404;
return 'not found';
}
$this->serveAsset($response, $request, $assetInfo);
}
/** @return int|void */
/** @return string|void */
#[HttpGet('/user-assets.php')]
public function getUserAssets(HttpResponseBuilder $response, HttpRequest $request) {
$userId = (string)$request->getParam('u', FILTER_SANITIZE_NUMBER_INT);
@ -92,8 +92,8 @@ class AssetsRoutes implements RouteHandler, UrlSource {
return $this->getProfileBackground($response, $request, $userId);
// circumvent the default error page
$response->setContent('Not Found');
return 404;
$response->statusCode = 404;
return 'not found';
}
private function serveAsset(HttpResponseBuilder $response, HttpRequest $request, UserImageAssetInterface $assetInfo): void {

View file

@ -59,7 +59,7 @@ class BanInfo {
1 => 'second',
];
private static function getTimeString(?int $left, int $right): string { // @phpstan-ignore-line: property hook issue
private static function getTimeString(?int $left, int $right): string {
if($left === null)
return 'permanent';

View file

@ -12,11 +12,9 @@ class Bans {
public const SEVERITY_MIN = -10;
public const SEVERITY_DEFAULT = 0;
private DbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(DbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
@ -171,7 +169,7 @@ class Bans {
$stmt->nextParameter($expires);
$stmt->execute();
return $this->getBan((string)$this->dbConn->getLastInsertId());
return $this->getBan((string)$stmt->lastInsertId);
}
/** @param BanInfo|string|array<BanInfo|string> $banInfos */

View file

@ -9,9 +9,7 @@ use Misuzu\Pagination;
class ModNotes {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -121,7 +119,7 @@ class ModNotes {
$stmt->nextParameter($body);
$stmt->execute();
return $this->getNote((string)$this->dbConn->getLastInsertId());
return $this->getNote((string)$stmt->lastInsertId);
}
/** @param ModNoteInfo|string|array<ModNoteInfo|string> $noteInfos */

View file

@ -12,9 +12,7 @@ class Roles {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -113,7 +111,7 @@ class Roles {
bool $hidden = false,
bool $leavable = false
): RoleInfo {
$colour = $colour->shouldInherit() ? null : Colour::toMisuzu($colour);
$colour = $colour->inherits ? null : Colour::toMisuzu($colour);
if($string === '')
$string = null;
@ -133,7 +131,7 @@ class Roles {
$stmt->nextParameter($colour);
$stmt->execute();
return $this->getRole((string)$this->dbConn->getLastInsertId());
return $this->getRole((string)$stmt->lastInsertId);
}
/** @param RoleInfo|string|array<RoleInfo|string> $roleInfos */
@ -182,7 +180,7 @@ class Roles {
$applyLeavable = $leavable !== null;
if($applyColour)
$colour = $colour->shouldInherit() ? null : Colour::toMisuzu($colour);
$colour = $colour->inherits ? null : Colour::toMisuzu($colour);
if($string === '')
$string = null;

View file

@ -14,9 +14,7 @@ use Misuzu\Parsers\Parser;
class Users {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -306,7 +304,7 @@ class Users {
$stmt->nextParameter($displayRoleInfo);
$stmt->execute();
return $this->getUser((string)$this->dbConn->getLastInsertId(), self::GET_USER_ID);
return $this->getUser((string)$stmt->lastInsertId, self::GET_USER_ID);
}
public function updateUser(
@ -364,7 +362,7 @@ class Users {
if($colour !== null) {
$fields[] = 'user_colour = ?';
$values[] = $colour->shouldInherit() ? null : Colour::toMisuzu($colour);
$values[] = $colour->inherits ? null : Colour::toMisuzu($colour);
}
if($displayRoleInfo !== null) {

View file

@ -50,7 +50,7 @@ final class UsersRpcHandler implements RpcHandler {
$colour = $this->usersCtx->getUserColour($userInfo);
if($colour->shouldInherit()) {
if($colour->inherits) {
$colourRaw = null;
$colourCSS = (string)$colour;
} else {

View file

@ -14,9 +14,7 @@ class Warnings {
private DbStatementCache $cache;
public function __construct(
private DbConnection $dbConn
) {
public function __construct(DbConnection $dbConn) {
$this->cache = new DbStatementCache($dbConn);
}
@ -136,7 +134,7 @@ class Warnings {
$stmt->nextParameter($body);
$stmt->execute();
return $this->getWarning((string)$this->dbConn->getLastInsertId());
return $this->getWarning((string)$stmt->lastInsertId);
}
/** @param WarningInfo|string|array<WarningInfo|string> $warnInfos */