Updated Index version.
This commit is contained in:
parent
f2233c5390
commit
6c7568e261
50 changed files with 483 additions and 457 deletions
composer.jsoncomposer.lockphpstan.neon
public-legacy/manage
public
src
Auth
Changelog
ClientInfo.phpComments
Emoticons
Forum
ForumCategoriesRoutes.phpForumPostInfo.phpForumPosts.phpForumPostsRoutes.phpForumTopicInfo.phpForumTopics.phpForumTopicsRoutes.php
Home
Info
LegacyRoutes.phpMessages
MisuzuContext.phpNews
Redirects
AliasRedirectsRoutes.phpIncrementalRedirectInfo.phpIncrementalRedirectsData.phpIncrementalRedirectsRoutes.phpLandingRedirectsRoutes.phpNamedRedirectsData.phpNamedRedirectsRoutes.phpSocialRedirectsRoutes.php
Routing
Satori
SharpChat
SiteInfo.phpUsers
|
@ -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
177
composer.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.';
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' => [
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'} ?? '';
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue