Ran PHPStan over everything and attempted some fixes.
This commit is contained in:
parent
3a118fef15
commit
d55585372e
49 changed files with 115 additions and 195 deletions
assets/js/misuzu
misuzu.phpphpstan.neonsrc
AuditLog.phpAuthToken.php
utility.phpChangelog
Colour.phpComments
DB.phpEmoticon.phpFeeds
Forum
Http
Imaging
Mailer.phpMediaType.phpPagination.phpStream.phpTOTP.phpTemplate.phpUsers
Zalgo.phpperms.phpurl.php
|
@ -1,104 +0,0 @@
|
||||||
Misuzu.UserRelations = {};
|
|
||||||
Misuzu.UserRelations.Type = DefineEnum({ none: 0, follow: 1, });
|
|
||||||
Misuzu.UserRelations.init = function() {
|
|
||||||
var buttons = document.getElementsByClassName('js-user-relation-action');
|
|
||||||
|
|
||||||
for(var i = 0; i < buttons.length; ++i) {
|
|
||||||
switch(buttons[i].tagName.toLowerCase()) {
|
|
||||||
case 'a':
|
|
||||||
buttons[i].removeAttribute('href');
|
|
||||||
buttons[i].removeAttribute('target');
|
|
||||||
buttons[i].removeAttribute('rel');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons[i].addEventListener('click', Misuzu.UserRelations.setRelationHandler);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Misuzu.UserRelations.setRelation = function(user, type, onSuccess, onFailure) {
|
|
||||||
var xhr = new XMLHttpRequest;
|
|
||||||
xhr.addEventListener('readystatechange', function() {
|
|
||||||
if(xhr.readyState !== 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
|
|
||||||
|
|
||||||
var json = JSON.parse(xhr.responseText),
|
|
||||||
message = json.error || json.message;
|
|
||||||
|
|
||||||
if(message && onFailure)
|
|
||||||
onFailure(message);
|
|
||||||
else if(!message && onSuccess)
|
|
||||||
onSuccess(json);
|
|
||||||
});
|
|
||||||
xhr.open('GET', Misuzu.Urls.format('user-relation-create', [Misuzu.Urls.v('user', user), Misuzu.Urls.v('type', type)]));
|
|
||||||
xhr.setRequestHeader('X-Misuzu-XHR', 'user_relation');
|
|
||||||
xhr.setRequestHeader('X-Misuzu-CSRF', Misuzu.CSRF.getToken());
|
|
||||||
xhr.send();
|
|
||||||
};
|
|
||||||
Misuzu.UserRelations.ICO_ADD = 'fas fa-user-plus';
|
|
||||||
Misuzu.UserRelations.ICO_REM = 'fas fa-user-minus';
|
|
||||||
Misuzu.UserRelations.ICO_BUS = 'fas fa-spinner fa-pulse';
|
|
||||||
Misuzu.UserRelations.BTN_BUS = 'input__button--busy';
|
|
||||||
Misuzu.UserRelations.setRelationHandler = function(ev) {
|
|
||||||
var target = this,
|
|
||||||
userId = parseInt(target.dataset.relationUser),
|
|
||||||
relationType = parseInt(target.dataset.relationType),
|
|
||||||
isButton = target.classList.contains('input__button'),
|
|
||||||
icon = target.querySelector('[class^="fa"]');
|
|
||||||
|
|
||||||
if(isButton) {
|
|
||||||
if(target.classList.contains(Misuzu.UserRelations.BTN_BUS))
|
|
||||||
return;
|
|
||||||
target.classList.add(Misuzu.UserRelations.BTN_BUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(icon)
|
|
||||||
icon.className = Misuzu.UserRelations.ICO_BUS;
|
|
||||||
|
|
||||||
Misuzu.UserRelations.setRelation(
|
|
||||||
userId,
|
|
||||||
relationType,
|
|
||||||
function(info) {
|
|
||||||
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
|
|
||||||
|
|
||||||
switch(info.relation_type) {
|
|
||||||
case Misuzu.UserRelations.Type.none:
|
|
||||||
if(isButton) {
|
|
||||||
if(target.classList.contains('input__button--destroy'))
|
|
||||||
target.classList.remove('input__button--destroy');
|
|
||||||
|
|
||||||
target.textContent = 'Follow';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(icon) {
|
|
||||||
icon.className = Misuzu.UserRelations.ICO_ADD;
|
|
||||||
target.title = 'Follow';
|
|
||||||
}
|
|
||||||
|
|
||||||
target.dataset.relationType = Misuzu.UserRelations.Type.follow.toString();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Misuzu.UserRelations.Type.follow:
|
|
||||||
if(isButton) {
|
|
||||||
if(!target.classList.contains('input__button--destroy'))
|
|
||||||
target.classList.add('input__button--destroy');
|
|
||||||
|
|
||||||
target.textContent = 'Unfollow';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(icon) {
|
|
||||||
icon.className = Misuzu.UserRelations.ICO_REM;
|
|
||||||
target.title = 'Unfollow';
|
|
||||||
}
|
|
||||||
|
|
||||||
target.dataset.relationType = Misuzu.UserRelations.Type.none.toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function(msg) {
|
|
||||||
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
|
|
||||||
Misuzu.showMessageBox(msg);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -242,7 +242,7 @@ if(parse_url($_SERVER['PHP_SELF'], PHP_URL_PATH) !== '/index.php')
|
||||||
if(!empty($userInfo))
|
if(!empty($userInfo))
|
||||||
Template::set('current_user', $userInfo);
|
Template::set('current_user', $userInfo);
|
||||||
|
|
||||||
$inManageMode = starts_with($_SERVER['REQUEST_URI'], '/manage');
|
$inManageMode = str_starts_with($_SERVER['REQUEST_URI'], '/manage');
|
||||||
$hasManageAccess = User::hasCurrent()
|
$hasManageAccess = User::hasCurrent()
|
||||||
&& !User::getCurrent()->hasActiveWarning()
|
&& !User::getCurrent()->hasActiveWarning()
|
||||||
&& perms_check_user(MSZ_PERMS_GENERAL, User::getCurrent()->getId(), MSZ_PERM_GENERAL_CAN_MANAGE);
|
&& perms_check_user(MSZ_PERMS_GENERAL, User::getCurrent()->getId(), MSZ_PERM_GENERAL_CAN_MANAGE);
|
||||||
|
|
6
phpstan.neon
Normal file
6
phpstan.neon
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
parameters:
|
||||||
|
level: 5
|
||||||
|
paths:
|
||||||
|
- src
|
||||||
|
bootstrapFiles:
|
||||||
|
- misuzu.php
|
|
@ -149,7 +149,7 @@ class AuditLog {
|
||||||
|
|
||||||
public static function create(string $action, array $params = [], ?User $user = null, ?string $remoteAddr = null): void {
|
public static function create(string $action, array $params = [], ?User $user = null, ?string $remoteAddr = null): void {
|
||||||
$user = $user ?? User::getCurrent();
|
$user = $user ?? User::getCurrent();
|
||||||
$remoteAddr = $ipAddress ?? IPAddress::remote();
|
$remoteAddr = $remoteAddr ?? IPAddress::remote();
|
||||||
$createLog = DB::prepare(
|
$createLog = DB::prepare(
|
||||||
'INSERT INTO `' . DB::PREFIX . self::TABLE . '` (`log_action`, `user_id`, `log_params`, `log_ip`, `log_country`)'
|
'INSERT INTO `' . DB::PREFIX . self::TABLE . '` (`log_action`, `user_id`, `log_params`, `log_ip`, `log_country`)'
|
||||||
. ' VALUES (:action, :user, :params, INET6_ATON(:ip), :country)'
|
. ' VALUES (:action, :user, :params, INET6_ATON(:ip), :country)'
|
||||||
|
@ -162,7 +162,7 @@ class AuditLog {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countAll(?User $user = null): int {
|
public static function countAll(?User $user = null): int {
|
||||||
$getCount = DB::prepare(
|
$getCount = DB::prepare(
|
||||||
|
|
|
@ -65,7 +65,7 @@ class AuthToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function unpack(string $data, bool $base64 = true): self {
|
public static function unpack(string $data, bool $base64 = true): self {
|
||||||
$obj = new static;
|
$obj = new AuthToken;
|
||||||
|
|
||||||
if(empty($data))
|
if(empty($data))
|
||||||
return $obj;
|
return $obj;
|
||||||
|
@ -83,7 +83,7 @@ class AuthToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function create(User $user, UserSession $session): self {
|
public static function create(User $user, UserSession $session): self {
|
||||||
return (new static)
|
return (new AuthToken)
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
->setSession($session);
|
->setSession($session);
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ class ChangelogChange implements JsonSerializable {
|
||||||
return [
|
return [
|
||||||
'id' => $this->getId(),
|
'id' => $this->getId(),
|
||||||
'user' => $this->getUserId(),
|
'user' => $this->getUserId(),
|
||||||
'action' => $this->getActionId(),
|
'action' => $this->getAction(),
|
||||||
'header' => $this->getHeader(),
|
'header' => $this->getHeader(),
|
||||||
'body' => $this->getBody(),
|
'body' => $this->getBody(),
|
||||||
'comments' => $this->getCommentsCategoryName(),
|
'comments' => $this->getCommentsCategoryName(),
|
||||||
|
|
|
@ -78,7 +78,7 @@ class ChangelogChangeTag implements JsonSerializable {
|
||||||
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 byExact(ChangelogChange $change, ChangelogTag $tag): array {
|
public static function byExact(ChangelogChange $change, ChangelogTag $tag): self {
|
||||||
$tag = DB::prepare(self::byQueryBase() . ' WHERE `tag_id` = :tag')
|
$tag = DB::prepare(self::byQueryBase() . ' WHERE `tag_id` = :tag')
|
||||||
->bind('change', $change->getId())
|
->bind('change', $change->getId())
|
||||||
->bind('tag', $tag->getId())
|
->bind('tag', $tag->getId())
|
||||||
|
|
|
@ -18,14 +18,14 @@ class Colour {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function none(): self {
|
public static function none(): self {
|
||||||
return new static(self::FLAG_INHERIT);
|
return new Colour(self::FLAG_INHERIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromRgb(int $red, int $green, int $blue): self {
|
public static function fromRgb(int $red, int $green, int $blue): self {
|
||||||
return (new static)->setRed($red)->setGreen($green)->setBlue($blue);
|
return (new Colour)->setRed($red)->setGreen($green)->setBlue($blue);
|
||||||
}
|
}
|
||||||
public static function fromHex(string $hex): self {
|
public static function fromHex(string $hex): self {
|
||||||
return (new static)->setHex($hex);
|
return (new Colour)->setHex($hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRaw(): int {
|
public function getRaw(): int {
|
||||||
|
@ -99,7 +99,7 @@ class Colour {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLuminance(): int {
|
public function getLuminance(): float {
|
||||||
return self::LUMINANCE_WEIGHT_RED * $this->getRed()
|
return self::LUMINANCE_WEIGHT_RED * $this->getRed()
|
||||||
+ self::LUMINANCE_WEIGHT_GREEN * $this->getGreen()
|
+ self::LUMINANCE_WEIGHT_GREEN * $this->getGreen()
|
||||||
+ self::LUMINANCE_WEIGHT_BLUE * $this->getBlue();
|
+ self::LUMINANCE_WEIGHT_BLUE * $this->getBlue();
|
||||||
|
|
|
@ -128,7 +128,7 @@ class CommentsVote implements JsonSerializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function fake(CommentsPost $post, User $user, int $vote): CommentsVote {
|
private static function fake(CommentsPost $post, User $user, int $vote): CommentsVote {
|
||||||
$fake = new static;
|
$fake = new CommentsVote;
|
||||||
$fake->comment_id = $post->getId();
|
$fake->comment_id = $post->getId();
|
||||||
$fake->comment = $post;
|
$fake->comment = $post;
|
||||||
$fake->user_id = $user->getId();
|
$fake->user_id = $user->getId();
|
||||||
|
|
|
@ -4,6 +4,14 @@ namespace Misuzu;
|
||||||
use PDO;
|
use PDO;
|
||||||
use Misuzu\Database\Database;
|
use Misuzu\Database\Database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static PDO getPDO()
|
||||||
|
* @method static int queries()
|
||||||
|
* @method static int exec(string $stmt)
|
||||||
|
* @method static \Misuzu\Database\DatabaseStatement prepare(string $stmt, array $options = [])
|
||||||
|
* @method static \Misuzu\Database\DatabaseStatement query(string $stmt, ?int $fetchMode = null, ...$args)
|
||||||
|
* @method static int lastId()
|
||||||
|
*/
|
||||||
final class DB {
|
final class DB {
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Misuzu;
|
namespace Misuzu;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
final class Emoticon {
|
final class Emoticon {
|
||||||
|
private int $emote_id;
|
||||||
|
private int $emote_order;
|
||||||
|
private int $emote_hierarchy;
|
||||||
|
private string $emote_url;
|
||||||
|
|
||||||
public const ALL = PHP_INT_MAX;
|
public const ALL = PHP_INT_MAX;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
@ -132,7 +139,7 @@ final class Emoticon {
|
||||||
|
|
||||||
public static function byId(int $emoteId): self {
|
public static function byId(int $emoteId): self {
|
||||||
if($emoteId < 1)
|
if($emoteId < 1)
|
||||||
return [];
|
throw new InvalidArgumentException('$emoteId is not a valid emoticon id.');
|
||||||
|
|
||||||
$getEmote = DB::prepare('
|
$getEmote = DB::prepare('
|
||||||
SELECT `emote_id`, `emote_order`, `emote_hierarchy`, `emote_url`
|
SELECT `emote_id`, `emote_order`, `emote_hierarchy`, `emote_url`
|
||||||
|
|
|
@ -70,8 +70,6 @@ class Feed {
|
||||||
return count($this->feedItems) > 0;
|
return count($this->feedItems) > 0;
|
||||||
}
|
}
|
||||||
public function addItem(FeedItem $item): self {
|
public function addItem(FeedItem $item): self {
|
||||||
if($item === null)
|
|
||||||
throw new InvalidArgumentException('item may not be null');
|
|
||||||
$this->feedItems[] = $item;
|
$this->feedItems[] = $item;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,9 +238,8 @@ function forum_get_child_ids(int $forumId): array {
|
||||||
}
|
}
|
||||||
|
|
||||||
function forum_topics_unread(int $forumId, int $userId): int {
|
function forum_topics_unread(int $forumId, int $userId): int {
|
||||||
if($userId < 1 || $forumId < 1) {
|
if($userId < 1 || $forumId < 1)
|
||||||
return false;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
static $memoized = [];
|
static $memoized = [];
|
||||||
$memoId = "{$forumId}-{$userId}";
|
$memoId = "{$forumId}-{$userId}";
|
||||||
|
|
|
@ -308,7 +308,7 @@ function forum_post_can_delete($postId, ?int $userId = null): int {
|
||||||
return MSZ_E_FORUM_POST_DELETE_OWNER;
|
return MSZ_E_FORUM_POST_DELETE_OWNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strtotime($post['post_created']) <= time() - MSZ_FORUM_POST_DELETE_LIMIT) {
|
if(strtotime($post['post_created']) <= (time() - MSZ_FORUM_POST_DELETE_LIMIT)) {
|
||||||
return MSZ_E_FORUM_POST_DELETE_OLD;
|
return MSZ_E_FORUM_POST_DELETE_OLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -575,7 +575,7 @@ function forum_topic_can_delete($topicId, ?int $userId = null): int {
|
||||||
return MSZ_E_FORUM_TOPIC_DELETE_OWNER;
|
return MSZ_E_FORUM_TOPIC_DELETE_OWNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strtotime($topic['topic_created']) <= time() - MSZ_FORUM_TOPIC_DELETE_TIME_LIMIT) {
|
if(strtotime($topic['topic_created']) <= (time() - MSZ_FORUM_TOPIC_DELETE_TIME_LIMIT)) {
|
||||||
return MSZ_E_FORUM_TOPIC_DELETE_OLD;
|
return MSZ_E_FORUM_TOPIC_DELETE_OLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ChangelogHandler extends Handler {
|
||||||
if($filterDate !== null)
|
if($filterDate !== null)
|
||||||
try {
|
try {
|
||||||
$dateParts = explode('-', $filterDate, 3);
|
$dateParts = explode('-', $filterDate, 3);
|
||||||
$filterDate = gmmktime(12, 0, 0, $dateParts[1], $dateParts[2], $dateParts[0]);
|
$filterDate = gmmktime(12, 0, 0, intval($dateParts[1]), intval($dateParts[2]), intval($dateParts[0]));
|
||||||
} catch(ErrorException $ex) {
|
} catch(ErrorException $ex) {
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ final class ForumHandler extends Handler {
|
||||||
$forumId = (int)$request->getQueryParam('forum', FILTER_SANITIZE_NUMBER_INT);
|
$forumId = (int)$request->getQueryParam('forum', FILTER_SANITIZE_NUMBER_INT);
|
||||||
$response->setTemplate('confirm', [
|
$response->setTemplate('confirm', [
|
||||||
'title' => 'Mark forum as read',
|
'title' => 'Mark forum as read',
|
||||||
'message' => 'Are you sure you want to mark ' . ($forumId === null ? 'the entire' : 'this') . ' forum as read?',
|
'message' => 'Are you sure you want to mark ' . ($forumId === 0 ? 'the entire' : 'this') . ' forum as read?',
|
||||||
'return' => url($forumId ? 'forum-category' : 'forum-index', ['forum' => $forumId]),
|
'return' => url($forumId ? 'forum-category' : 'forum-index', ['forum' => $forumId]),
|
||||||
'params' => [
|
'params' => [
|
||||||
'forum' => $forumId,
|
'forum' => $forumId,
|
||||||
|
|
|
@ -20,7 +20,7 @@ final class InfoHandler extends Handler {
|
||||||
'title' => '',
|
'title' => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
$isMisuzuDoc = $name === 'misuzu' || starts_with($name, 'misuzu/');
|
$isMisuzuDoc = $name === 'misuzu' || str_starts_with($name, 'misuzu/');
|
||||||
|
|
||||||
if($isMisuzuDoc) {
|
if($isMisuzuDoc) {
|
||||||
$filename = substr($name, 7);
|
$filename = substr($name, 7);
|
||||||
|
@ -41,8 +41,8 @@ final class InfoHandler extends Handler {
|
||||||
if(empty($document['content']))
|
if(empty($document['content']))
|
||||||
return 404;
|
return 404;
|
||||||
|
|
||||||
if(empty($document['title'])) {
|
if($document['title'] === '') {
|
||||||
if(starts_with($document['content'], '# ')) {
|
if(str_starts_with($document['content'], '# ')) {
|
||||||
$titleOffset = strpos($document['content'], "\n");
|
$titleOffset = strpos($document['content'], "\n");
|
||||||
$document['title'] = trim(substr($document['content'], 2, $titleOffset - 1));
|
$document['title'] = trim(substr($document['content'], 2, $titleOffset - 1));
|
||||||
$document['content'] = substr($document['content'], $titleOffset);
|
$document['content'] = substr($document['content'], $titleOffset);
|
||||||
|
|
|
@ -13,7 +13,7 @@ use Misuzu\Feeds\RssFeedSerializer;
|
||||||
use Misuzu\News\NewsCategory;
|
use Misuzu\News\NewsCategory;
|
||||||
use Misuzu\News\NewsPost;
|
use Misuzu\News\NewsPost;
|
||||||
use Misuzu\News\NewsCategoryNotFoundException;
|
use Misuzu\News\NewsCategoryNotFoundException;
|
||||||
use Misuzu\News\NewsPostNotException;
|
use Misuzu\News\NewsPostNotFoundException;
|
||||||
use Misuzu\Parsers\Parser;
|
use Misuzu\Parsers\Parser;
|
||||||
use Misuzu\Users\User;
|
use Misuzu\Users\User;
|
||||||
|
|
||||||
|
|
|
@ -67,12 +67,14 @@ final class SockChatHandler extends Handler {
|
||||||
|
|
||||||
$body = $request->getParsedBody();
|
$body = $request->getParsedBody();
|
||||||
|
|
||||||
if(isset($body['bump'], $body['hash']) && is_string($body['bump']) && is_string($body['hash']))
|
if(isset($body['bump'], $body['hash']) && is_string($body['bump']) && is_string($body['hash'])) {
|
||||||
return $this->bump(
|
$this->bump(
|
||||||
$response,
|
$response,
|
||||||
$request->setHeader('X-SharpChat-Signature', $body['hash'])
|
$request->setHeader('X-SharpChat-Signature', $body['hash'])
|
||||||
->setBody(Stream::create($body['bump']))
|
->setBody(Stream::create($body['bump']))
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$source = isset($body['user_id']) ? $body : $query;
|
$source = isset($body['user_id']) ? $body : $query;
|
||||||
|
|
||||||
|
@ -381,9 +383,10 @@ final class SockChatHandler extends Handler {
|
||||||
$userInfo = User::byUsername($param);
|
$userInfo = User::byUsername($param);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch(UserNotFoundException $ex) {
|
} catch(UserNotFoundException $ex) {}
|
||||||
|
|
||||||
|
if(!isset($userInfo))
|
||||||
return [];
|
return [];
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'user_id' => $userInfo->getId(),
|
'user_id' => $userInfo->getId(),
|
||||||
|
|
|
@ -16,7 +16,7 @@ class AcceptHttpHeaderChild implements HasQualityInterface {
|
||||||
if(isset($parts[1])) {
|
if(isset($parts[1])) {
|
||||||
$split = explode('=', $parts[1], 2);
|
$split = explode('=', $parts[1], 2);
|
||||||
if($split[0] === 'q' && isset($split[1]))
|
if($split[0] === 'q' && isset($split[1]))
|
||||||
$this->quality = max(min(round(filter_var($split[1], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) ?? 1, 2), 1), 0);
|
$this->quality = max(min(round((float)filter_var($split[1], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION), 2), 1), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ class HttpHeader {
|
||||||
case 'TE':
|
case 'TE':
|
||||||
return new AcceptHttpHeader($name, $line);
|
return new AcceptHttpHeader($name, $line);
|
||||||
default:
|
default:
|
||||||
return new static($name, $line);
|
return new HttpHeader($name, $line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ class HttpRequestMessage extends HttpMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isset($headers['Authorization'])) {
|
if(empty($headers['Authorization'])) {
|
||||||
if(isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
|
if(isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
|
||||||
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
|
$headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
|
||||||
} elseif(isset($_SERVER['PHP_AUTH_USER'])) {
|
} elseif(isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
|
|
|
@ -131,7 +131,6 @@ class HttpResponseMessage extends HttpMessage {
|
||||||
414 => 'URI Too Long',
|
414 => 'URI Too Long',
|
||||||
416 => 'Range Not Satisfiable',
|
416 => 'Range Not Satisfiable',
|
||||||
417 => 'Expectation Failed',
|
417 => 'Expectation Failed',
|
||||||
417 => 'Expectation Failed',
|
|
||||||
418 => 'I\'m a teapot',
|
418 => 'I\'m a teapot',
|
||||||
421 => 'Misdirected Request',
|
421 => 'Misdirected Request',
|
||||||
422 => 'Unprocessable Entity',
|
422 => 'Unprocessable Entity',
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Route {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function create(array $methods, string $path, ?string $method = null, ?string $class = null): self {
|
public static function create(array $methods, string $path, ?string $method = null, ?string $class = null): self {
|
||||||
return new static($methods, $path, $method, $class);
|
return new Route($methods, $path, $method, $class);
|
||||||
}
|
}
|
||||||
public static function get(string $path, ?string $method = null, ?string $class = null): self {
|
public static function get(string $path, ?string $method = null, ?string $class = null): self {
|
||||||
return self::create(['GET'], $path, $method, $class);
|
return self::create(['GET'], $path, $method, $class);
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Router {
|
||||||
if($name[0] === '_')
|
if($name[0] === '_')
|
||||||
return null;
|
return null;
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
(new static)->setInstance();
|
(new Router)->setInstance();
|
||||||
return self::$instance->{'_' . $name}(...$args);
|
return self::$instance->{'_' . $name}(...$args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class Router {
|
||||||
|
|
||||||
$handlerMethod = $route->getHandlerMethod();
|
$handlerMethod = $route->getHandlerMethod();
|
||||||
if(is_callable($handlerMethod)) {
|
if(is_callable($handlerMethod)) {
|
||||||
$result = call_user_func_array($handlerMethod, $args);
|
$result = call_user_func_array($handlerMethod, $matches);
|
||||||
} elseif($handlerMethod[0] === '/') {
|
} elseif($handlerMethod[0] === '/') {
|
||||||
$response->redirect($handlerMethod);
|
$response->redirect($handlerMethod);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,7 +38,7 @@ class UploadedFile {
|
||||||
$this->stream = $fileNameOrStream;
|
$this->stream = $fileNameOrStream;
|
||||||
|
|
||||||
if($size === null && $this->stream !== null)
|
if($size === null && $this->stream !== null)
|
||||||
$this->size = $stream->getSize();
|
$this->size = $this->stream->getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class UploadedFile {
|
||||||
throw new RuntimeException('Can\'t open stream because of an upload error.');
|
throw new RuntimeException('Can\'t open stream because of an upload error.');
|
||||||
if($this->hasMoved)
|
if($this->hasMoved)
|
||||||
throw new RuntimeException('Can\'t open stream because file has already been moved.');
|
throw new RuntimeException('Can\'t open stream because file has already been moved.');
|
||||||
if($this->steam === null)
|
if($this->stream === null)
|
||||||
$this->stream = Stream::createFromFile($this->fileName);
|
$this->stream = Stream::createFromFile($this->fileName);
|
||||||
|
|
||||||
return $this->stream;
|
return $this->stream;
|
||||||
|
@ -97,7 +97,7 @@ class UploadedFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createFromFILE(array $file): self {
|
public static function createFromFILE(array $file): self {
|
||||||
return new static(
|
return new UploadedFile(
|
||||||
$file['tmp_name'] ?? '',
|
$file['tmp_name'] ?? '',
|
||||||
$file['error'] ?? UPLOAD_ERR_NO_FILE,
|
$file['error'] ?? UPLOAD_ERR_NO_FILE,
|
||||||
$file['size'] ?? null,
|
$file['size'] ?? null,
|
||||||
|
|
|
@ -26,7 +26,7 @@ final class GdImage extends Image {
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct($pathOrWidth, int $height = -1) {
|
public function __construct($pathOrWidth, int $height = -1) {
|
||||||
parent::__construct($pathOrWidth, $height);
|
parent::__construct($pathOrWidth);
|
||||||
|
|
||||||
if(is_int($pathOrWidth)) {
|
if(is_int($pathOrWidth)) {
|
||||||
$this->gd = imagecreatetruecolor($pathOrWidth, $height < 1 ? $pathOrWidth : $height);
|
$this->gd = imagecreatetruecolor($pathOrWidth, $height < 1 ? $pathOrWidth : $height);
|
||||||
|
|
|
@ -5,7 +5,7 @@ use InvalidArgumentException;
|
||||||
use UnexpectedValueException;
|
use UnexpectedValueException;
|
||||||
|
|
||||||
abstract class Image {
|
abstract class Image {
|
||||||
public function __construct($pathOrWidth, int $height = -1) {
|
public function __construct($pathOrWidth) {
|
||||||
if(!is_int($pathOrWidth) && !is_string($pathOrWidth))
|
if(!is_int($pathOrWidth) && !is_string($pathOrWidth))
|
||||||
throw new InvalidArgumentException('The first argument must be or type string to open an image file, or int to set a width for a new image.');
|
throw new InvalidArgumentException('The first argument must be or type string to open an image file, or int to set a width for a new image.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ final class ImagickImage extends Image {
|
||||||
private ?Imagick $imagick = null;
|
private ?Imagick $imagick = null;
|
||||||
|
|
||||||
public function __construct($pathOrWidth, int $height = -1) {
|
public function __construct($pathOrWidth, int $height = -1) {
|
||||||
parent::__construct($pathOrWidth, $height);
|
parent::__construct($pathOrWidth);
|
||||||
|
|
||||||
if(is_int($pathOrWidth)) {
|
if(is_int($pathOrWidth)) {
|
||||||
$this->imagick = new Imagick();
|
$this->imagick = new Imagick();
|
||||||
$this->newImage($pathOrWidth, $height < 1 ? $pathOrWidth : $height, 'none');
|
$this->imagick->newImage($pathOrWidth, $height < 1 ? $pathOrWidth : $height, 'none');
|
||||||
$this->setImageFormat('png');
|
$this->imagick->setImageFormat('png');
|
||||||
} elseif(is_string($pathOrWidth)) {
|
} elseif(is_string($pathOrWidth)) {
|
||||||
$imagick = new Imagick($pathOrWidth);
|
$imagick = new Imagick($pathOrWidth);
|
||||||
$imagick->setImageFormat($imagick->getNumberImages() > 1 ? 'gif' : 'png');
|
$imagick->setImageFormat($imagick->getNumberImages() > 1 ? 'gif' : 'png');
|
||||||
|
|
|
@ -14,6 +14,9 @@ final class Mailer {
|
||||||
private static $dsn = 'null://null';
|
private static $dsn = 'null://null';
|
||||||
private static $transport = null;
|
private static $transport = null;
|
||||||
|
|
||||||
|
private static string $senderName = 'Flashii';
|
||||||
|
private static string $senderAddr = 'sys@flashii.net';
|
||||||
|
|
||||||
public static function init(string $method, array $config): void {
|
public static function init(string $method, array $config): void {
|
||||||
if($method !== 'smtp') {
|
if($method !== 'smtp') {
|
||||||
self::$dsn = 'null://null';
|
self::$dsn = 'null://null';
|
||||||
|
@ -42,6 +45,12 @@ final class Mailer {
|
||||||
$dsn .= $config['port'] ?? 25;
|
$dsn .= $config['port'] ?? 25;
|
||||||
|
|
||||||
self::$dsn = $dsn;
|
self::$dsn = $dsn;
|
||||||
|
|
||||||
|
if(!empty($config['sender_name']))
|
||||||
|
self::$senderName = $config['sender_name'];
|
||||||
|
|
||||||
|
if(!empty($config['sender_addr']))
|
||||||
|
self::$senderAddr = $config['sender_addr'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTransport() {
|
public static function getTransport() {
|
||||||
|
@ -59,8 +68,8 @@ final class Mailer {
|
||||||
$message = new SymfonyMessage;
|
$message = new SymfonyMessage;
|
||||||
|
|
||||||
$message->from(new SymfonyAddress(
|
$message->from(new SymfonyAddress(
|
||||||
$config['sender_addr'] ?? 'sys@flashii.net',
|
self::$senderAddr,
|
||||||
$config['sender_name'] ?? 'Flashii'
|
self::$senderName
|
||||||
));
|
));
|
||||||
|
|
||||||
if($bcc)
|
if($bcc)
|
||||||
|
|
|
@ -68,7 +68,7 @@ class MediaType implements HasQualityInterface {
|
||||||
}
|
}
|
||||||
public function matchPattern(string $pattern): bool {
|
public function matchPattern(string $pattern): bool {
|
||||||
try {
|
try {
|
||||||
$mediaType = new static($pattern);
|
$mediaType = new MediaType($pattern);
|
||||||
} catch(InvalidArgumentException $ex) {
|
} catch(InvalidArgumentException $ex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ final class Pagination {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPages(): int {
|
public function getPages(): int {
|
||||||
return ceil($this->getCount() / $this->getRange());
|
return (int)ceil($this->getCount() / $this->getRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasValidOffset(): bool {
|
public function hasValidOffset(): bool {
|
||||||
|
@ -50,7 +50,7 @@ final class Pagination {
|
||||||
if($this->getOffset() < 1)
|
if($this->getOffset() < 1)
|
||||||
return self::START_PAGE;
|
return self::START_PAGE;
|
||||||
|
|
||||||
return floor($this->getOffset() / $this->getRange()) + self::START_PAGE;
|
return (int)floor($this->getOffset() / $this->getRange()) + self::START_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPage(int $page, bool $zeroBased = false): self {
|
public function setPage(int $page, bool $zeroBased = false): self {
|
||||||
|
@ -70,7 +70,7 @@ final class Pagination {
|
||||||
$source ??= $_GET;
|
$source ??= $_GET;
|
||||||
|
|
||||||
if(isset($source[$name]) && is_string($source[$name]) && ctype_digit($source[$name]))
|
if(isset($source[$name]) && is_string($source[$name]) && ctype_digit($source[$name]))
|
||||||
return $source[$name];
|
return intval($source[$name]);
|
||||||
|
|
||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Stream {
|
||||||
if($contents instanceof Stream)
|
if($contents instanceof Stream)
|
||||||
return $contents;
|
return $contents;
|
||||||
|
|
||||||
return new static($contents);
|
return new Stream($contents);
|
||||||
}
|
}
|
||||||
public static function createFromFile(string $filename, string $mode = 'rb'): Stream {
|
public static function createFromFile(string $filename, string $mode = 'rb'): Stream {
|
||||||
if(!in_array($mode[0], ['r', 'w', 'a', 'x', 'c']))
|
if(!in_array($mode[0], ['r', 'w', 'a', 'x', 'c']))
|
||||||
|
@ -79,9 +79,9 @@ class Stream {
|
||||||
return $this->readable;
|
return $this->readable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function read($length): int {
|
public function read($length): string {
|
||||||
if(!$this->isReadable())
|
if(!$this->isReadable())
|
||||||
throw RuntimeException('Can\'t read from this stream.');
|
throw new RuntimeException('Can\'t read from this stream.');
|
||||||
|
|
||||||
return fread($this->stream, $length);
|
return fread($this->stream, $length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,6 @@ class TOTP {
|
||||||
$bin |= (ord($hash[$offset + 3]) & 0xFF);
|
$bin |= (ord($hash[$offset + 3]) & 0xFF);
|
||||||
$otp = $bin % pow(10, self::DIGITS);
|
$otp = $bin % pow(10, self::DIGITS);
|
||||||
|
|
||||||
return str_pad($otp, self::DIGITS, STR_PAD_LEFT);
|
return str_pad(strval($otp), self::DIGITS, '0', STR_PAD_LEFT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ final class Template {
|
||||||
define('MSZ_TPL_RENDER', microtime(true));
|
define('MSZ_TPL_RENDER', microtime(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ends_with($file, self::FILE_EXT)) {
|
if(!str_ends_with($file, self::FILE_EXT)) {
|
||||||
$file = str_replace('.', DIRECTORY_SEPARATOR, $file) . self::FILE_EXT;
|
$file = str_replace('.', DIRECTORY_SEPARATOR, $file) . self::FILE_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ class UserAvatarAsset extends UserImageAsset implements UserAssetScalableInterfa
|
||||||
}
|
}
|
||||||
public function getScaledFileExtension(int $dims): string {
|
public function getScaledFileExtension(int $dims): string {
|
||||||
$imageSize = getimagesize($this->getScaledPath($dims));
|
$imageSize = getimagesize($this->getScaledPath($dims));
|
||||||
if($imageSize === null)
|
if($imageSize === false)
|
||||||
return 'img';
|
return 'img';
|
||||||
return self::TYPES_EXT[$imageSize[2]] ?? 'img';
|
return self::TYPES_EXT[$imageSize[2]] ?? 'img';
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ class UserBackgroundAsset extends UserImageAsset {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
public function isBlend(): bool {
|
public function isBlend(): bool {
|
||||||
return $this->getAttributes() & self::ATTRIB_BLEND;
|
return ($this->getAttributes() & self::ATTRIB_BLEND) > 0;
|
||||||
}
|
}
|
||||||
public function setBlend(bool $blend): self {
|
public function setBlend(bool $blend): self {
|
||||||
$this->getUser()->setBackgroundSettings(
|
$this->getUser()->setBackgroundSettings(
|
||||||
|
@ -105,7 +105,7 @@ class UserBackgroundAsset extends UserImageAsset {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
public function isSlide(): bool {
|
public function isSlide(): bool {
|
||||||
return $this->getAttributes() & self::ATTRIB_SLIDE;
|
return ($this->getAttributes() & self::ATTRIB_SLIDE) > 0;
|
||||||
}
|
}
|
||||||
public function setSlide(bool $slide): self {
|
public function setSlide(bool $slide): self {
|
||||||
$this->getUser()->setBackgroundSettings(
|
$this->getUser()->setBackgroundSettings(
|
||||||
|
|
|
@ -120,7 +120,7 @@ abstract class UserImageAsset implements JsonSerializable, UserImageAssetInterfa
|
||||||
|
|
||||||
public function setFromData(string $data): void {
|
public function setFromData(string $data): void {
|
||||||
$file = tempnam(sys_get_temp_dir(), 'msz');
|
$file = tempnam(sys_get_temp_dir(), 'msz');
|
||||||
if($file === null || !is_file($file))
|
if($file === false || !is_file($file))
|
||||||
throw new UserImageAssetFileCreationFailedException;
|
throw new UserImageAssetFileCreationFailedException;
|
||||||
chmod($file, 0664);
|
chmod($file, 0664);
|
||||||
file_put_contents($file, $data);
|
file_put_contents($file, $data);
|
||||||
|
|
|
@ -790,7 +790,7 @@ class User implements HasRankInterface, JsonSerializable {
|
||||||
************/
|
************/
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countAll(bool $showDeleted = false): int {
|
public static function countAll(bool $showDeleted = false): int {
|
||||||
return (int)DB::prepare(
|
return (int)DB::prepare(
|
||||||
|
|
|
@ -93,7 +93,7 @@ class UserLoginAttempt {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countAll(?User $user = null): int {
|
public static function countAll(?User $user = null): int {
|
||||||
$getCount = DB::prepare(
|
$getCount = DB::prepare(
|
||||||
|
|
|
@ -83,7 +83,7 @@ class UserRole implements ArrayAccess, HasRankInterface {
|
||||||
public function getCanLeave(): bool {
|
public function getCanLeave(): bool {
|
||||||
return boolval($this->role_can_leave);
|
return boolval($this->role_can_leave);
|
||||||
}
|
}
|
||||||
public function setCanLeave(bool $canLeave): bool {
|
public function setCanLeave(bool $canLeave): self {
|
||||||
$this->role_can_leave = $canLeave ? 1 : 0;
|
$this->role_can_leave = $canLeave ? 1 : 0;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ class UserRole implements ArrayAccess, HasRankInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countAll(bool $showHidden = false): int {
|
public static function countAll(bool $showHidden = false): int {
|
||||||
return (int)DB::prepare(
|
return (int)DB::prepare(
|
||||||
|
|
|
@ -60,7 +60,7 @@ class UserRoleRelation {
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
// data is predictable, just create a "fake"
|
// data is predictable, just create a "fake"
|
||||||
$object = new static;
|
$object = new UserRoleRelation;
|
||||||
$object->user = $user;
|
$object->user = $user;
|
||||||
$object->user_id = $user->getId();
|
$object->user_id = $user->getId();
|
||||||
$object->role = $role;
|
$object->role = $role;
|
||||||
|
@ -69,7 +69,7 @@ class UserRoleRelation {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countUsers(UserRole $role): int {
|
public static function countUsers(UserRole $role): int {
|
||||||
return (int)DB::prepare(self::countQueryBase() . ' WHERE `role_id` = :role')
|
return (int)DB::prepare(self::countQueryBase() . ' WHERE `role_id` = :role')
|
||||||
|
|
|
@ -199,7 +199,7 @@ class UserSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countAll(?User $user = null): int {
|
public static function countAll(?User $user = null): int {
|
||||||
$getCount = DB::prepare(
|
$getCount = DB::prepare(
|
||||||
|
|
|
@ -197,7 +197,7 @@ class UserWarning {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function countQueryBase(): string {
|
private static function countQueryBase(): string {
|
||||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
return sprintf(self::QUERY_SELECT, 'COUNT(*)');
|
||||||
}
|
}
|
||||||
public static function countByRemoteAddress(?string $address = null, bool $withDuration = true): int {
|
public static function countByRemoteAddress(?string $address = null, bool $withDuration = true): int {
|
||||||
$address = $address ?? IPAddress::remote();
|
$address = $address ?? IPAddress::remote();
|
||||||
|
|
|
@ -86,6 +86,7 @@ final class Zalgo {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$str .= $char;
|
$str .= $char;
|
||||||
|
$num_up = $num_mid = $num_down = 0;
|
||||||
|
|
||||||
switch($mode) {
|
switch($mode) {
|
||||||
case self::MODE_MINI:
|
case self::MODE_MINI:
|
||||||
|
|
|
@ -74,17 +74,15 @@ function perms_get_key(string $prefix, string $suffix): string {
|
||||||
function perms_get_select(array $modes = MSZ_PERM_MODES, string $allow = MSZ_PERMS_ALLOW, string $deny = MSZ_PERMS_DENY): string {
|
function perms_get_select(array $modes = MSZ_PERM_MODES, string $allow = MSZ_PERMS_ALLOW, string $deny = MSZ_PERMS_DENY): string {
|
||||||
$select = '';
|
$select = '';
|
||||||
|
|
||||||
if(empty($select)) {
|
foreach($modes as $mode) {
|
||||||
foreach($modes as $mode) {
|
$select .= sprintf(
|
||||||
$select .= sprintf(
|
'(BIT_OR(`%1$s_perms_%2$s`) &~ BIT_OR(`%1$s_perms_%3$s`)) AS `%1$s`,',
|
||||||
'(BIT_OR(`%1$s_perms_%2$s`) &~ BIT_OR(`%1$s_perms_%3$s`)) AS `%1$s`,',
|
$mode, $allow, $deny
|
||||||
$mode, $allow, $deny
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$select = substr($select, 0, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$select = substr($select, 0, -1);
|
||||||
|
|
||||||
return $select;
|
return $select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/url.php
12
src/url.php
|
@ -132,7 +132,7 @@ function url(string $name, array $variables = []): string {
|
||||||
|
|
||||||
$info = MSZ_URLS[$name];
|
$info = MSZ_URLS[$name];
|
||||||
|
|
||||||
if(!is_string($info[0] ?? null)) {
|
if(!isset($info[0]) || !is_string($info[0])) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,13 +175,13 @@ function url_redirect(string $name, array $variables = []): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
function url_variable(string $value, array $variables): string {
|
function url_variable(string $value, array $variables): string {
|
||||||
if(starts_with($value, '<') && ends_with($value, '>'))
|
if(str_starts_with($value, '<') && str_ends_with($value, '>'))
|
||||||
return $variables[trim($value, '<>')] ?? '';
|
return $variables[trim($value, '<>')] ?? '';
|
||||||
|
|
||||||
if(starts_with($value, '[') && ends_with($value, ']'))
|
if(str_starts_with($value, '[') && str_ends_with($value, ']'))
|
||||||
return constant(trim($value, '[]'));
|
return constant(trim($value, '[]'));
|
||||||
|
|
||||||
if(starts_with($value, '{') && ends_with($value, '}'))
|
if(str_starts_with($value, '{') && str_ends_with($value, '}'))
|
||||||
return \Misuzu\CSRF::token();
|
return \Misuzu\CSRF::token();
|
||||||
|
|
||||||
// Hack that allows variables with file extensions
|
// Hack that allows variables with file extensions
|
||||||
|
@ -201,7 +201,7 @@ function url_list(): array {
|
||||||
$collection = [];
|
$collection = [];
|
||||||
|
|
||||||
foreach(MSZ_URLS as $name => $urlInfo) {
|
foreach(MSZ_URLS as $name => $urlInfo) {
|
||||||
if(empty($hasManageAccess) && starts_with($name, 'manage-'))
|
if(empty($hasManageAccess) && str_starts_with($name, 'manage-'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$item = [
|
$item = [
|
||||||
|
@ -271,5 +271,5 @@ function is_local_url(string $url): bool {
|
||||||
if($url[0] === '/' && ($length > 1 ? $url[1] !== '/' : true))
|
if($url[0] === '/' && ($length > 1 ? $url[1] !== '/' : true))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return starts_with($url, url_prefix());
|
return str_starts_with($url, url_prefix());
|
||||||
}
|
}
|
||||||
|
|
12
utility.php
12
utility.php
|
@ -33,16 +33,12 @@ function clamp($num, int $min, int $max): int {
|
||||||
return max($min, min($max, intval($num)));
|
return max($min, min($max, intval($num)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function starts_with(string $string, string $text, bool $multibyte = true): bool {
|
function starts_with(string $string, string $text): bool {
|
||||||
$strlen = $multibyte ? 'mb_strlen' : 'strlen';
|
return str_starts_with($string, $text);
|
||||||
$substr = $multibyte ? 'mb_substr' : 'substr';
|
|
||||||
return $substr($string, 0, $strlen($text)) === $text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ends_with(string $string, string $text, bool $multibyte = true): bool {
|
function ends_with(string $string, string $text): bool {
|
||||||
$strlen = $multibyte ? 'mb_strlen' : 'strlen';
|
return str_ends_with($string, $text);
|
||||||
$substr = $multibyte ? 'mb_substr' : 'substr';
|
|
||||||
return $substr($string, 0 - $strlen($text)) === $text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function first_paragraph(string $text, string $delimiter = "\n"): string {
|
function first_paragraph(string $text, string $delimiter = "\n"): string {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue