Fixed various errors and oversights caught by phpstan.

This commit is contained in:
flash 2023-07-18 22:24:23 +00:00
parent 2f7cddde19
commit e6c826a7d7
23 changed files with 130 additions and 188 deletions

View file

@ -11,11 +11,9 @@ use Misuzu\Pagination;
use Misuzu\Users\User; use Misuzu\Users\User;
class AuditLog { class AuditLog {
private IDbConnection $dbConn;
private DbStatementCache $cache; private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) { public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn); $this->cache = new DbStatementCache($dbConn);
} }
@ -34,8 +32,8 @@ class AuditLog {
$args = 0; $args = 0;
$query = 'SELECT COUNT(*) FROM msz_audit_log'; $query = 'SELECT COUNT(*) FROM msz_audit_log';
if($hasUserInfo) { if($hasUserInfo) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' user_id = ?'; $query .= ' WHERE user_id = ?';
} }
if($hasRemoteAddr) { if($hasRemoteAddr) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');
@ -77,8 +75,8 @@ class AuditLog {
$args = 0; $args = 0;
$query = 'SELECT user_id, log_action, log_params, UNIX_TIMESTAMP(log_created), INET6_NTOA(log_ip), log_country FROM msz_audit_log'; $query = 'SELECT user_id, log_action, log_params, UNIX_TIMESTAMP(log_created), INET6_NTOA(log_ip), log_country FROM msz_audit_log';
if($hasUserInfo) { if($hasUserInfo) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' user_id = ?'; $query .= ' WHERE user_id = ?';
} }
if($hasRemoteAddr) { if($hasRemoteAddr) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');

View file

@ -131,8 +131,8 @@ class AuthToken {
if(!hash_equals($realHash, $userHash)) if(!hash_equals($realHash, $userHash))
return $obj; return $obj;
extract(unpack('Ntimestamp', $timestamp)); $unpacked = unpack('Nts', $timestamp);
$obj->timestamp = $timestamp; $obj->timestamp = (int)$unpacked['ts'];
$stream = MemoryStream::fromString($data); $stream = MemoryStream::fromString($data);
$stream->seek(0); $stream->seek(0);

View file

@ -111,8 +111,8 @@ class Changelog {
$query = 'SELECT COUNT(*) FROM msz_changelog_changes'; $query = 'SELECT COUNT(*) FROM msz_changelog_changes';
if($hasUserInfo) { if($hasUserInfo) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' user_id = ?'; $query .= ' WHERE user_id = ?';
} }
if($hasDateTime) { if($hasDateTime) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');
@ -166,8 +166,8 @@ class Changelog {
$query = 'SELECT change_id, user_id, change_action, UNIX_TIMESTAMP(change_created), change_log, change_text FROM msz_changelog_changes'; $query = 'SELECT change_id, user_id, change_action, UNIX_TIMESTAMP(change_created), change_log, change_text FROM msz_changelog_changes';
if($hasUserInfo) { if($hasUserInfo) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' user_id = ?'; $query .= ' WHERE user_id = ?';
} }
if($hasDateTime) { if($hasDateTime) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');

View file

@ -231,12 +231,12 @@ class Comments {
$query = 'SELECT COUNT(*) FROM msz_comments_posts'; $query = 'SELECT COUNT(*) FROM msz_comments_posts';
if($hasParent) { if($hasParent) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' comment_reply_to = ?'; $query .= ' WHERE comment_reply_to = ?';
} else { } else {
if($hasCategory) { if($hasCategory) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' category_id = ?'; $query .= ' WHERE category_id = ?';
} }
if(!$includeReplies) { if(!$includeReplies) {
@ -295,12 +295,12 @@ class Comments {
$query .= ' FROM msz_comments_posts AS cpp'; $query .= ' FROM msz_comments_posts AS cpp';
if($hasParent) { if($hasParent) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' comment_reply_to = ?'; $query .= ' WHERE comment_reply_to = ?';
} else { } else {
if($hasCategory) { if($hasCategory) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' category_id = ?'; $query .= ' WHERE category_id = ?';
} }
if(!$includeReplies) { if(!$includeReplies) {

View file

@ -11,12 +11,10 @@ use Misuzu\DbStatementCache;
use Misuzu\Pagination; use Misuzu\Pagination;
class DbConfig implements IConfig { class DbConfig implements IConfig {
private IDbConnection $dbConn;
private DbStatementCache $cache; private DbStatementCache $cache;
private array $values = []; private array $values = [];
public function __construct(IDbConnection $dbConn) { public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn); $this->cache = new DbStatementCache($dbConn);
} }
@ -265,16 +263,6 @@ class DbConfig implements IConfig {
return $valueInfo?->isArray() ? $valueInfo->getArray() : $default; return $valueInfo?->isArray() ? $valueInfo->getArray() : $default;
} }
private function setValue(string $name, $value): void {
$this->values[$name] = $value;
$value = serialize($value);
$stmt = $this->cache->get('REPLACE INTO msz_config (config_name, config_value) VALUES (?, ?)');
$stmt->addParameter(1, $name);
$stmt->addParameter(2, $value);
$stmt->execute();
}
public function setValues(array $values): void { public function setValues(array $values): void {
if(empty($values)) if(empty($values))
return; return;

View file

@ -24,6 +24,7 @@ class DbConfigValueInfo implements IConfigValueInfo {
'i' => 'int', 'i' => 'int',
'b' => 'bool', 'b' => 'bool',
'd' => 'float', 'd' => 'float',
default => 'unknown',
}; };
} }

View file

@ -24,7 +24,7 @@ class ScopedConfig implements IConfig {
private function prefixNames(string|array $names): array { private function prefixNames(string|array $names): array {
if(is_string($names)) if(is_string($names))
return [$this->prefix . $name]; return [$this->prefix . $names];
foreach($names as $key => $name) foreach($names as $key => $name)
$names[$key] = $this->prefix . $name; $names[$key] = $this->prefix . $name;
@ -41,7 +41,7 @@ class ScopedConfig implements IConfig {
} }
public function hasValues(string|array $names): bool { public function hasValues(string|array $names): bool {
$this->config->hasValues($this->prefixNames($names)); return $this->config->hasValues($this->prefixNames($names));
} }
public function removeValues(string|array $names): void { public function removeValues(string|array $names): void {

View file

@ -3,15 +3,17 @@ namespace Misuzu\Feeds;
use DOMDocument; use DOMDocument;
use DOMElement; use DOMElement;
use DOMNode;
class AtomFeedSerializer extends XmlFeedSerializer { class AtomFeedSerializer extends XmlFeedSerializer {
protected function formatTime(int $time): string { protected function formatTime(int $time): string {
return date('c', $time); return date('c', $time);
} }
protected function createRoot(DOMDocument $document, Feed $feed): DOMElement { protected function createRoot(DOMDocument $document, Feed $feed): DOMNode {
$atom = $document->appendChild($document->createElement('feed')); $atom = $document->appendChild($document->createElement('feed'));
$atom->setAttribute('xmlns', 'http://www.w3.org/2005/Atom'); if($atom instanceof DOMElement)
$atom->setAttribute('xmlns', 'http://www.w3.org/2005/Atom');
$atom->appendChild( $atom->appendChild(
$document->createElement( $document->createElement(
@ -25,32 +27,32 @@ class AtomFeedSerializer extends XmlFeedSerializer {
return $atom; return $atom;
} }
protected function createTitle(DOMDocument $document, string $title): DOMElement { protected function createTitle(DOMDocument $document, string $title): DOMNode {
return $document->createElement('title', $this->cleanString($title)); return $document->createElement('title', $this->cleanString($title));
} }
protected function createDescription(DOMDocument $document, string $description): ?DOMElement { protected function createDescription(DOMDocument $document, string $description): ?DOMNode {
return $document->createElement('subtitle', $this->cleanString($description)); return $document->createElement('subtitle', $this->cleanString($description));
} }
protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMElement { protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode {
return $document->createElement('updated', $this->formatTime($lastUpdate)); return $document->createElement('updated', $this->formatTime($lastUpdate));
} }
protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement { protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode {
$link = $document->createElement('link'); $link = $document->createElement('link');
$link->setAttribute('href', $this->cleanString($contentUrl)); $link->setAttribute('href', $this->cleanString($contentUrl));
return $link; return $link;
} }
protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMElement { protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode {
$link = $document->createElement('link'); $link = $document->createElement('link');
$link->setAttribute('href', $this->cleanString($feedUrl)); $link->setAttribute('href', $this->cleanString($feedUrl));
$link->setAttribute('ref', 'self'); $link->setAttribute('ref', 'self');
return $link; return $link;
} }
protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMElement { protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode {
$elem = $document->createElement('entry'); $elem = $document->createElement('entry');
$elem->appendChild( $elem->appendChild(
@ -65,40 +67,40 @@ class AtomFeedSerializer extends XmlFeedSerializer {
return $elem; return $elem;
} }
protected function createItemTitle(DOMDocument $document, string $title): DOMElement { protected function createItemTitle(DOMDocument $document, string $title): DOMNode {
return $document->createElement('title', $this->cleanString($title)); return $document->createElement('title', $this->cleanString($title));
} }
protected function createItemSummary(DOMDocument $document, string $summary): ?DOMElement { protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode {
return $document->createElement('summary', $this->cleanString($summary)); return $document->createElement('summary', $this->cleanString($summary));
} }
protected function createItemContent(DOMDocument $document, string $content): ?DOMElement { protected function createItemContent(DOMDocument $document, string $content): ?DOMNode {
$elem = $document->createElement('content', $this->cleanString($content)); $elem = $document->createElement('content', $this->cleanString($content));
$elem->setAttribute('type', 'html'); $elem->setAttribute('type', 'html');
return $elem; return $elem;
} }
protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMElement { protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode {
return $document->createElement('updated', $this->formatTime($creationDate)); return $document->createElement('updated', $this->formatTime($creationDate));
} }
protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMElement { protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode {
return null; return null;
} }
protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement { protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode {
$elem = $document->createElement('link'); $elem = $document->createElement('link');
$elem->setAttribute('href', $this->cleanString($contentUrl)); $elem->setAttribute('href', $this->cleanString($contentUrl));
$elem->setAttribute('type', 'text/html'); $elem->setAttribute('type', 'text/html');
return $elem; return $elem;
} }
protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMElement { protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode {
return null; return null;
} }
protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMElement { protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode {
if(empty($authorName) && empty($authorUrl)) if(empty($authorName) && empty($authorUrl))
return null; return null;

View file

@ -3,80 +3,83 @@ namespace Misuzu\Feeds;
use DOMDocument; use DOMDocument;
use DOMElement; use DOMElement;
use DOMNode;
class RssFeedSerializer extends XmlFeedSerializer { class RssFeedSerializer extends XmlFeedSerializer {
protected function formatTime(int $time): string { protected function formatTime(int $time): string {
return date('r', $time); return date('r', $time);
} }
protected function createRoot(DOMDocument $document, Feed $feed): DOMElement { protected function createRoot(DOMDocument $document, Feed $feed): DOMNode {
$rss = $document->appendChild($document->createElement('rss')); $rss = $document->appendChild($document->createElement('rss'));
$rss->setAttribute('version', '2.0'); if($rss instanceof DOMElement) {
$rss->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom'); $rss->setAttribute('version', '2.0');
$rss->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom');
}
$channel = $rss->appendChild($document->createElement('channel')); $channel = $rss->appendChild($document->createElement('channel'));
$channel->appendChild($document->createElement('ttl', '900')); $channel->appendChild($document->createElement('ttl', '900'));
return $channel; return $channel;
} }
protected function createTitle(DOMDocument $document, string $title): DOMElement { protected function createTitle(DOMDocument $document, string $title): DOMNode {
return $document->createElement('title', $this->cleanString($title)); return $document->createElement('title', $this->cleanString($title));
} }
protected function createDescription(DOMDocument $document, string $description): ?DOMElement { protected function createDescription(DOMDocument $document, string $description): ?DOMNode {
return $document->createElement('description', $this->cleanString($description)); return $document->createElement('description', $this->cleanString($description));
} }
protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMElement { protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode {
return $document->createElement('pubDate', $this->formatTime($lastUpdate)); return $document->createElement('pubDate', $this->formatTime($lastUpdate));
} }
protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement { protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode {
return $document->createElement('link', $this->cleanString($contentUrl)); return $document->createElement('link', $this->cleanString($contentUrl));
} }
protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMElement { protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode {
$link = $document->createElement('atom:link'); $link = $document->createElement('atom:link');
$link->setAttribute('href', $this->cleanString($feedUrl)); $link->setAttribute('href', $this->cleanString($feedUrl));
$link->setAttribute('ref', 'self'); $link->setAttribute('ref', 'self');
return $link; return $link;
} }
protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMElement { protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode {
return $document->createElement('item'); return $document->createElement('item');
} }
protected function createItemTitle(DOMDocument $document, string $title): DOMElement { protected function createItemTitle(DOMDocument $document, string $title): DOMNode {
return $document->createElement('title', $this->cleanString($title)); return $document->createElement('title', $this->cleanString($title));
} }
protected function createItemSummary(DOMDocument $document, string $summary): ?DOMElement { protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode {
return $document->createElement('description', $this->cleanString($summary)); return $document->createElement('description', $this->cleanString($summary));
} }
protected function createItemContent(DOMDocument $document, string $content): ?DOMElement { protected function createItemContent(DOMDocument $document, string $content): ?DOMNode {
return null; return null;
} }
protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMElement { protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode {
return $document->createElement('pubDate', $this->formatTime($creationDate)); return $document->createElement('pubDate', $this->formatTime($creationDate));
} }
protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMElement { protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode {
$elem = $document->createElement('guid', $uniqueId); $elem = $document->createElement('guid', $uniqueId);
$elem->setAttribute('isPermaLink', 'true'); $elem->setAttribute('isPermaLink', 'true');
return $elem; return $elem;
} }
protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement { protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode {
return $document->createElement('link', $contentUrl); return $document->createElement('link', $contentUrl);
} }
protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMElement { protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode {
return $document->createElement('comments', $commentsUrl); return $document->createElement('comments', $commentsUrl);
} }
protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMElement { protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode {
return null; return null;
} }
} }

View file

@ -2,7 +2,7 @@
namespace Misuzu\Feeds; namespace Misuzu\Feeds;
use DOMDocument; use DOMDocument;
use DOMElement; use DOMNode;
abstract class XmlFeedSerializer extends FeedSerializer { abstract class XmlFeedSerializer extends FeedSerializer {
public function serializeFeed(Feed $feed): string { public function serializeFeed(Feed $feed): string {
@ -28,7 +28,7 @@ abstract class XmlFeedSerializer extends FeedSerializer {
return $document->saveXML(); return $document->saveXML();
} }
private function serializeFeedItem(DOMDocument $document, FeedItem $feedItem): DOMElement { private function serializeFeedItem(DOMDocument $document, FeedItem $feedItem): DOMNode {
$elem = $this->createItem($document, $feedItem); $elem = $this->createItem($document, $feedItem);
$elem->appendChild($this->createItemTitle($document, $feedItem->getTitle())); $elem->appendChild($this->createItemTitle($document, $feedItem->getTitle()));
@ -54,26 +54,26 @@ abstract class XmlFeedSerializer extends FeedSerializer {
return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT | ENT_SUBSTITUTE); return htmlspecialchars($string, ENT_XML1 | ENT_COMPAT | ENT_SUBSTITUTE);
} }
protected static function appendChild(DOMElement $parent, ?DOMElement $elem): ?DOMElement { protected static function appendChild(DOMNode $parent, ?DOMNode $elem): ?DOMNode {
if($elem !== null) if($elem !== null)
return $parent->appendChild($elem); return $parent->appendChild($elem);
return $elem; return $elem;
} }
abstract protected function formatTime(int $time): string; abstract protected function formatTime(int $time): string;
abstract protected function createRoot(DOMDocument $document, Feed $feed): DOMElement; abstract protected function createRoot(DOMDocument $document, Feed $feed): DOMNode;
abstract protected function createTitle(DOMDocument $document, string $title): DOMElement; abstract protected function createTitle(DOMDocument $document, string $title): DOMNode;
abstract protected function createDescription(DOMDocument $document, string $description): ?DOMElement; abstract protected function createDescription(DOMDocument $document, string $description): ?DOMNode;
abstract protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMElement; abstract protected function createLastUpdate(DOMDocument $document, int $lastUpdate): ?DOMNode;
abstract protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement; abstract protected function createContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode;
abstract protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMElement; abstract protected function createFeedUrl(DOMDocument $document, string $feedUrl): ?DOMNode;
abstract protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMElement; abstract protected function createItem(DOMDocument $document, FeedItem $feedItem): DOMNode;
abstract protected function createItemTitle(DOMDocument $document, string $title): DOMElement; abstract protected function createItemTitle(DOMDocument $document, string $title): DOMNode;
abstract protected function createItemSummary(DOMDocument $document, string $summary): ?DOMElement; abstract protected function createItemSummary(DOMDocument $document, string $summary): ?DOMNode;
abstract protected function createItemContent(DOMDocument $document, string $content): ?DOMElement; abstract protected function createItemContent(DOMDocument $document, string $content): ?DOMNode;
abstract protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMElement; abstract protected function createItemCreationDate(DOMDocument $document, int $creationDate): ?DOMNode;
abstract protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMElement; abstract protected function createItemUniqueId(DOMDocument $document, string $uniqueId): ?DOMNode;
abstract protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMElement; abstract protected function createItemContentUrl(DOMDocument $document, string $contentUrl): ?DOMNode;
abstract protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMElement; abstract protected function createItemCommentsUrl(DOMDocument $document, string $commentsUrl): ?DOMNode;
abstract protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMElement; abstract protected function createItemAuthor(DOMDocument $document, ?string $authorName, ?string $authorUrl): ?DOMNode;
} }

View file

@ -616,7 +616,7 @@ function forum_topic_can_delete($topicId, ?int $userId = null): int {
return MSZ_E_FORUM_TOPIC_DELETE_OLD; return MSZ_E_FORUM_TOPIC_DELETE_OLD;
} }
$totalReplies = $topic['topic_count_posts'] + $topic['topic_count_posts_deleted']; $totalReplies = (int)$topic['topic_count_posts'] + (int)$topic['topic_count_posts_deleted'];
if($totalReplies > MSZ_E_FORUM_TOPIC_DELETE_POSTS) { if($totalReplies > MSZ_E_FORUM_TOPIC_DELETE_POSTS) {
return MSZ_E_FORUM_TOPIC_DELETE_POSTS; return MSZ_E_FORUM_TOPIC_DELETE_POSTS;

View file

@ -86,7 +86,7 @@ final class AssetsHandler extends Handler {
} }
public function serveLegacy($response, $request) { public function serveLegacy($response, $request) {
$assetUserId = (int)$request->getParam('u', FILTER_SANITIZE_NUMBER_INT); $assetUserId = $request->getParam('u', FILTER_SANITIZE_NUMBER_INT);
switch($request->getParam('m')) { switch($request->getParam('m')) {
case 'avatar': case 'avatar':

View file

@ -47,8 +47,8 @@ abstract class Image {
$this->resize($targetWidth, $targetHeight); $this->resize($targetWidth, $targetHeight);
$this->crop( $this->crop(
$dimensions, $dimensions, $dimensions, $dimensions,
ceil(($targetWidth - $dimensions) / 2), (int)ceil(($targetWidth - $dimensions) / 2),
ceil(($targetHeight - $dimensions) / 2) (int)ceil(($targetHeight - $dimensions) / 2)
); );
$this->setPage($dimensions, $dimensions, 0, 0); $this->setPage($dimensions, $dimensions, 0, 0);
} while($this->next()); } while($this->next());

View file

@ -15,9 +15,6 @@ final class Mailer {
private static IConfig $config; private static IConfig $config;
private static $transport = null; private static $transport = null;
private static string $senderName = 'Flashii';
private static string $senderAddr = 'sys@flashii.net';
public static function init(IConfig $config): void { public static function init(IConfig $config): void {
self::$config = $config; self::$config = $config;
} }
@ -49,12 +46,6 @@ final class Mailer {
$dsn .= ':'; $dsn .= ':';
$dsn .= $config['port'] ?? 25; $dsn .= $config['port'] ?? 25;
if(!empty($config['sender.name']))
self::$senderName = $config['sender.name'];
if(!empty($config['sender.address']))
self::$senderAddr = $config['sender.address'];
return $dsn; return $dsn;
} }
@ -71,8 +62,8 @@ final class Mailer {
} }
$config = self::$config->getValues([ $config = self::$config->getValues([
'sender.name:s', ['sender.name:s', 'Flashii'],
'sender.address:s', ['sender.address:s', 'sys@flashii.net'],
]); ]);
$message = new SymfonyMessage; $message = new SymfonyMessage;
@ -90,14 +81,8 @@ final class Mailer {
$message->subject(trim($subject)); $message->subject(trim($subject));
$message->text(trim($contents)); $message->text(trim($contents));
try { self::getTransport()->send($message);
self::getTransport()->send($message); return true;
return true;
} catch(TransportExceptionInterface $ex) {
if(MSZ_DEBUG)
throw $ex;
return false;
}
} }
public static function template(string $name, array $vars = []): array { public static function template(string $name, array $vars = []): array {

View file

@ -10,7 +10,6 @@ use Misuzu\Emoticons\Emotes;
use Misuzu\News\News; use Misuzu\News\News;
use Misuzu\SharpChat\SharpChatRoutes; use Misuzu\SharpChat\SharpChatRoutes;
use Misuzu\Users\User; use Misuzu\Users\User;
use Misuzu\Users\Users;
use Index\Data\IDbConnection; use Index\Data\IDbConnection;
use Index\Data\Migration\IDbMigrationRepo; use Index\Data\Migration\IDbMigrationRepo;
use Index\Data\Migration\DbMigrationManager; use Index\Data\Migration\DbMigrationManager;
@ -25,7 +24,6 @@ use Index\Routing\Router;
class MisuzuContext { class MisuzuContext {
private IDbConnection $dbConn; private IDbConnection $dbConn;
private IConfig $config; private IConfig $config;
private Users $users;
private HttpFx $router; private HttpFx $router;
private AuditLog $auditLog; private AuditLog $auditLog;
private Emotes $emotes; private Emotes $emotes;
@ -36,7 +34,6 @@ class MisuzuContext {
public function __construct(IDbConnection $dbConn, IConfig $config) { public function __construct(IDbConnection $dbConn, IConfig $config) {
$this->dbConn = $dbConn; $this->dbConn = $dbConn;
$this->config = $config; $this->config = $config;
$this->users = new Users($this->dbConn);
$this->auditLog = new AuditLog($this->dbConn); $this->auditLog = new AuditLog($this->dbConn);
$this->emotes = new Emotes($this->dbConn); $this->emotes = new Emotes($this->dbConn);
$this->changelog = new Changelog($this->dbConn); $this->changelog = new Changelog($this->dbConn);
@ -69,10 +66,6 @@ class MisuzuContext {
return $this->router->getRouter(); return $this->router->getRouter();
} }
/*public function getUsers(): Users {
return $this->users;
}*/
public function getEmotes(): Emotes { public function getEmotes(): Emotes {
return $this->emotes; return $this->emotes;
} }

View file

@ -182,8 +182,8 @@ class News {
$args = 0; $args = 0;
$query = 'SELECT COUNT(*) FROM msz_news_posts'; $query = 'SELECT COUNT(*) FROM msz_news_posts';
if($onlyFeatured) { if($onlyFeatured) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' post_is_featured = 1'; $query .= ' WHERE post_is_featured = 1';
} }
if(!$includeScheduled) { if(!$includeScheduled) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');
@ -247,8 +247,8 @@ class News {
$query = self::POSTS_SELECT_QUERY; $query = self::POSTS_SELECT_QUERY;
if($onlyFeatured) { if($onlyFeatured) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); ++$args;
$query .= ' post_is_featured = 1'; $query .= ' WHERE post_is_featured = 1';
} }
if(!$includeScheduled) { if(!$includeScheduled) {
$query .= (++$args > 1 ? ' AND' : ' WHERE'); $query .= (++$args > 1 ? ' AND' : ' WHERE');

View file

@ -3,6 +3,7 @@ namespace Misuzu\SharpChat;
use Index\Colour\Colour; use Index\Colour\Colour;
use Index\Routing\IRouter; use Index\Routing\IRouter;
use Index\Http\HttpFx;
use Misuzu\AuthToken; use Misuzu\AuthToken;
use Misuzu\Config\IConfig; use Misuzu\Config\IConfig;
use Misuzu\Emoticons\Emotes; use Misuzu\Emoticons\Emotes;
@ -35,23 +36,24 @@ final class SharpChatRoutes {
} }
// Simplify default error pages // Simplify default error pages
$router->use('/_sockchat', function() use($router) { if($router instanceof HttpFx)
$router->addErrorHandler(400, function($response) { $router->use('/_sockchat', function() use($router) {
$response->setContent('HTTP 400'); $router->addErrorHandler(400, function($response) {
$response->setContent('HTTP 400');
});
$router->addErrorHandler(403, function($response) {
$response->setContent('HTTP 403');
});
$router->addErrorHandler(404, function($response) {
$response->setContent('HTTP 404');
});
$router->addErrorHandler(500, function($response) {
$response->setContent('HTTP 500');
});
$router->addErrorHandler(503, function($response) {
$response->setContent('HTTP 503');
});
}); });
$router->addErrorHandler(403, function($response) {
$response->setContent('HTTP 403');
});
$router->addErrorHandler(404, function($response) {
$response->setContent('HTTP 404');
});
$router->addErrorHandler(500, function($response) {
$response->setContent('HTTP 500');
});
$router->addErrorHandler(503, function($response) {
$response->setContent('HTTP 503');
});
});
// Public endpoints // Public endpoints
$router->get('/_sockchat/emotes', [$this, 'getEmotes']); $router->get('/_sockchat/emotes', [$this, 'getEmotes']);
@ -201,6 +203,8 @@ final class SharpChatRoutes {
} else { } else {
$bumpString = (string)$request->getContent(); $bumpString = (string)$request->getContent();
$signature = $bumpString; $signature = $bumpString;
$userTime = 0;
$bumpList = [];
} }
$userHash = (string)$request->getHeaderFirstLine('X-SharpChat-Signature'); $userHash = (string)$request->getHeaderFirstLine('X-SharpChat-Signature');
@ -212,7 +216,6 @@ final class SharpChatRoutes {
if($userTime < time() - 60) if($userTime < time() - 60)
return 403; return 403;
} else { } else {
$bumpList = [];
$bumpInfo = json_decode($bumpString); $bumpInfo = json_decode($bumpString);
if(empty($bumpInfo)) if(empty($bumpInfo))
return; return;
@ -246,7 +249,7 @@ final class SharpChatRoutes {
if(strlen($userHash) !== 64) if(strlen($userHash) !== 64)
return ['success' => false, 'reason' => 'length']; return ['success' => false, 'reason' => 'length'];
if(isset($authInfo) && !empty($authInfo->token) && !empty($authInfo->ip)) { if(!empty($authInfo->token) && !empty($authInfo->ip)) {
// user_id is discarded now // user_id is discarded now
// tokens should be entirely unique anyway // tokens should be entirely unique anyway
@ -257,13 +260,14 @@ final class SharpChatRoutes {
} else [$authMethod, $authToken] = $tokenParts; } else [$authMethod, $authToken] = $tokenParts;
$ipAddress = $authInfo->ip; $ipAddress = $authInfo->ip;
$signature = "{$authInfo->user_id}#{$authInfo->token}#{$authInfo->ip}"; $sigUserId = $authInfo->user_id ?? 0; // still need it for the signature
$signature = "{$sigUserId}#{$authInfo->token}#{$authInfo->ip}";
} }
if(empty($authMethod) || empty($authToken)) if(empty($authMethod) || empty($authToken) || empty($ipAddress))
return ['success' => false, 'reason' => 'data']; return ['success' => false, 'reason' => 'data'];
if(!isset($signature)) if(empty($signature))
$signature = "verify#{$authMethod}#{$authToken}#{$ipAddress}"; $signature = "verify#{$authMethod}#{$authToken}#{$ipAddress}";
$realHash = hash_hmac('sha256', $signature, $this->hashKey); $realHash = hash_hmac('sha256', $signature, $this->hashKey);
@ -463,8 +467,8 @@ final class SharpChatRoutes {
// IPs cannot be banned on their own // IPs cannot be banned on their own
// substituting with the unused Railgun account for now. // substituting with the unused Railgun account for now.
if(empty($targetId)) if(empty($userId))
$targetId = 69; $userId = 69;
if(empty($modId)) if(empty($modId))
$modId = 69; $modId = 69;

View file

@ -93,7 +93,7 @@ abstract class UserImageAsset implements UserImageAssetInterface {
throw new UserImageAssetFileNotFoundException; throw new UserImageAssetFileNotFoundException;
$imageInfo = getimagesize($path); $imageInfo = getimagesize($path);
if($imageInfo === false || count($imageInfo) < 3 || $imageInfo[0] < 1 || $imageInfo[1] < 1) if($imageInfo === false || $imageInfo[0] < 1 || $imageInfo[1] < 1)
throw new UserImageAssetInvalidImageException; throw new UserImageAssetInvalidImageException;
if(!self::isAllowedType($imageInfo[2])) if(!self::isAllowedType($imageInfo[2]))

View file

@ -4,6 +4,12 @@ namespace Misuzu\Users;
use Misuzu\DB; use Misuzu\DB;
class ProfileField { class ProfileField {
// Database fields
public $field_id;
public $user_id;
public $field_regex;
public $field_value;
public static function createField( public static function createField(
string $fieldKey, string $fieldKey,
string $fieldTitle, string $fieldTitle,

View file

@ -779,7 +779,12 @@ class User implements HasRankInterface {
private static function byQueryBase(): string { private static function byQueryBase(): string {
return sprintf(self::QUERY_SELECT, sprintf(self::SELECT, self::TABLE)); return sprintf(self::QUERY_SELECT, sprintf(self::SELECT, self::TABLE));
} }
public static function byId(int $userId): ?self { public static function byId(string|int $userId): ?self {
// newer classes all treat ids as if they're strings
// php plays nice with it but may as well be sure since phpstan screams about it
if(is_string($userId))
$userId = (int)$userId;
return self::memoizer()->find($userId, function() use ($userId) { return self::memoizer()->find($userId, function() use ($userId) {
$user = DB::prepare(self::byQueryBase() . ' WHERE `user_id` = :user_id') $user = DB::prepare(self::byQueryBase() . ' WHERE `user_id` = :user_id')
->bind('user_id', $userId) ->bind('user_id', $userId)

View file

@ -33,7 +33,6 @@ class UserRole implements ArrayAccess, HasRankInterface {
. ', UNIX_TIMESTAMP(%1$s.`role_created`) AS `role_created`'; . ', UNIX_TIMESTAMP(%1$s.`role_created`) AS `role_created`';
private $colour = null; private $colour = null;
private $users = [];
private $userCount = -1; private $userCount = -1;
public function getId(): int { public function getId(): int {

View file

@ -1,43 +0,0 @@
<?php
namespace Misuzu\Users;
use DateTimeImmutable;
use Index\Data\IDbConnection;
final class Users {
private IDbConnection $dbConn;
private array $cached = [];
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
}
public function getById(string $userId): User {
//
}
public function getByName(string $userName): User {
//
}
public function getByMailAddress(string $mailAddress): User {
//
}
public function getByNameOrMailAddress(string $userNameOrMailAddress): User {
//
}
public function getByIdOrName(string $userIdOrName): User {
//
}
public function getByBirthDate(DateTimeImmutable $dateTime): array {
//
}
public function getByAll(bool $includeDeleted = false, ?Pagination $pagination = null): array {
//
}
}

View file

@ -66,6 +66,7 @@ function manage_perms_apply(array $list, array $post, ?array $raw = null): ?arra
foreach($section['perms'] as $perm) { foreach($section['perms'] as $perm) {
if(empty($post[$section['section']][$perm['section']]['value'])) if(empty($post[$section['section']][$perm['section']]['value']))
continue; continue;
$perm['perm'] = (int)$perm['perm']; // makes phpstan happy
switch($post[$section['section']][$perm['section']]['value']) { switch($post[$section['section']][$perm['section']]['value']) {
case MSZ_MANAGE_PERM_YES: case MSZ_MANAGE_PERM_YES: