Cleaned up various utility functions.
This commit is contained in:
parent
1bb9bd6541
commit
027ed5aff6
13 changed files with 63 additions and 106 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit bce5ba77a268ecd6338d0e3520e41ff4c40cbeda
|
Subproject commit 8f908d7f688bd95fdedd868c5bf8d25a3b500b99
|
|
@ -68,12 +68,16 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($change) && !empty($_POST['tags']) && is_array($_POST['tags']) && array_test($_POST['tags'], 'ctype_digit')) {
|
if(isset($change) && !empty($_POST['tags']) && is_array($_POST['tags'])) {
|
||||||
$applyTags = [];
|
$applyTags = [];
|
||||||
foreach($_POST['tags'] as $tagId)
|
foreach($_POST['tags'] as $tagId) {
|
||||||
|
if(!ctype_digit($tagId))
|
||||||
|
die('Invalid item encountered in roles list.');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$applyTags[] = ChangelogTag::byId((int)filter_var($tagId, FILTER_SANITIZE_NUMBER_INT));
|
$applyTags[] = ChangelogTag::byId((int)filter_var($tagId, FILTER_SANITIZE_NUMBER_INT));
|
||||||
} catch(ChangelogTagNotFoundException $ex) {}
|
} catch(ChangelogTagNotFoundException $ex) {}
|
||||||
|
}
|
||||||
$change->setTags($applyTags);
|
$change->setTags($applyTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,16 +61,21 @@ if(CSRF::validateRequest() && $canEdit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!empty($_POST['roles']) && is_array($_POST['roles']) && array_test($_POST['roles'], 'ctype_digit')) {
|
if(!empty($_POST['roles']) && is_array($_POST['roles'])) {
|
||||||
|
// Read user input array and throw intval on em
|
||||||
|
$applyRoles = [];
|
||||||
|
foreach($_POST['roles'] as $item) {
|
||||||
|
if(!ctype_digit($item))
|
||||||
|
die('Invalid item encountered in roles list.');
|
||||||
|
$applyRoles[] = (int)$item;
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch existing roles
|
// Fetch existing roles
|
||||||
$existingRoles = $userInfo->getRoles();
|
$existingRoles = $userInfo->getRoles();
|
||||||
|
|
||||||
// Initialise set array with existing roles
|
// Initialise set array with existing roles
|
||||||
$setRoles = $existingRoles;
|
$setRoles = $existingRoles;
|
||||||
|
|
||||||
// Read user input array and throw intval on em
|
|
||||||
$applyRoles = array_apply($_POST['roles'], 'intval');
|
|
||||||
|
|
||||||
// Storage array for roles to dump
|
// Storage array for roles to dump
|
||||||
$removeRoles = [];
|
$removeRoles = [];
|
||||||
|
|
||||||
|
|
|
@ -50,12 +50,18 @@ if(!empty($_POST['warning']) && is_array($_POST['warning'])) {
|
||||||
if(!empty($customDuration)) {
|
if(!empty($customDuration)) {
|
||||||
switch($warningDuration) {
|
switch($warningDuration) {
|
||||||
case -100: // YYYY-MM-DD
|
case -100: // YYYY-MM-DD
|
||||||
$splitDate = array_apply(explode('-', $customDuration, 3), function ($a) {
|
$splitDate = explode('-', $customDuration, 3);
|
||||||
return (int)$a;
|
if(count($splitDate) !== 3)
|
||||||
});
|
die('Invalid date specified.');
|
||||||
|
|
||||||
if(checkdate($splitDate[1], $splitDate[2], $splitDate[0]))
|
$wYear = (int)$splitDate[0];
|
||||||
$warningDuration = mktime(0, 0, 0, $splitDate[1], $splitDate[2], $splitDate[0]) - time();
|
$wMonth = (int)$splitDate[1];
|
||||||
|
$wDay = (int)$splitDate[2];
|
||||||
|
|
||||||
|
if(checkdate($wMonth, $wDay, $wYear))
|
||||||
|
$warningDuration = mktime(0, 0, 0, $wMonth, $wDay, $wYear) - time();
|
||||||
|
else
|
||||||
|
die('Invalid date specified.');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -200: // Raw seconds
|
case -200: // Raw seconds
|
||||||
|
|
|
@ -173,17 +173,28 @@ class AuthToken {
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function cookieDomain(bool $compatible = true): string {
|
||||||
|
$url = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST);
|
||||||
|
if(empty($url))
|
||||||
|
$url = $_SERVER['HTTP_HOST'];
|
||||||
|
|
||||||
|
if(!filter_var($url, FILTER_VALIDATE_IP) && $compatible)
|
||||||
|
$url = '.' . $url;
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
public function applyCookie(int $expires = 0): void {
|
public function applyCookie(int $expires = 0): void {
|
||||||
if($expires > 0)
|
if($expires > 0)
|
||||||
$this->cookieExpires = $expires;
|
$this->cookieExpires = $expires;
|
||||||
else
|
else
|
||||||
$expires = $this->cookieExpires;
|
$expires = $this->cookieExpires;
|
||||||
|
|
||||||
setcookie('msz_auth', $this->pack(), $expires, '/', msz_cookie_domain(), !empty($_SERVER['HTTPS']), true);
|
setcookie('msz_auth', $this->pack(), $expires, '/', self::cookieDomain(), !empty($_SERVER['HTTPS']), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function nukeCookie(): void {
|
public static function nukeCookie(): void {
|
||||||
setcookie('msz_auth', '', -9001, '/', msz_cookie_domain(), !empty($_SERVER['HTTPS']), true);
|
setcookie('msz_auth', '', -9001, '/', self::cookieDomain(), !empty($_SERVER['HTTPS']), true);
|
||||||
setcookie('msz_auth', '', -9001, '/', '', !empty($_SERVER['HTTPS']), true);
|
setcookie('msz_auth', '', -9001, '/', '', !empty($_SERVER['HTTPS']), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,11 @@ function forum_perms_get_user(?int $forum, int $user): array {
|
||||||
$getPerms->bind('user_id_1', $user);
|
$getPerms->bind('user_id_1', $user);
|
||||||
$getPerms->bind('user_id_2', $user);
|
$getPerms->bind('user_id_2', $user);
|
||||||
|
|
||||||
return $memo[$memoId] = array_bit_or($perms, $getPerms->fetch());
|
$userPerms = $getPerms->fetch();
|
||||||
|
foreach($perms as $key => $value)
|
||||||
|
$perms[$key] |= $userPerms[$key] ?? 0;
|
||||||
|
|
||||||
|
return $memo[$memoId] = $perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
function forum_perms_get_role(?int $forum, int $role): array {
|
function forum_perms_get_role(?int $forum, int $role): array {
|
||||||
|
@ -124,7 +128,11 @@ function forum_perms_get_role(?int $forum, int $role): array {
|
||||||
$getPerms->bind('forum_id', $forum);
|
$getPerms->bind('forum_id', $forum);
|
||||||
$getPerms->bind('role_id', $role);
|
$getPerms->bind('role_id', $role);
|
||||||
|
|
||||||
return $memo[$memoId] = array_bit_or($perms, $getPerms->fetch());
|
$userPerms = $getPerms->fetch();
|
||||||
|
foreach($perms as $key => $value)
|
||||||
|
$perms[$key] |= $userPerms[$key] ?? 0;
|
||||||
|
|
||||||
|
return $memo[$memoId] = $perms;
|
||||||
}
|
}
|
||||||
|
|
||||||
function forum_perms_get_user_raw(?int $forum, int $user): array {
|
function forum_perms_get_user_raw(?int $forum, int $user): array {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
namespace Misuzu;
|
namespace Misuzu;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use Index\XArray;
|
||||||
|
|
||||||
// get rid of this garbage as soon as possible
|
// get rid of this garbage as soon as possible
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ class Memoizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_callable($find)) {
|
if(is_callable($find)) {
|
||||||
$item = array_find($this->collection, $find) ?? $create();
|
$item = XArray::first($this->collection, $find) ?? $create();
|
||||||
if(method_exists($item, 'getId'))
|
if(method_exists($item, 'getId'))
|
||||||
$this->collection[$item->getId()] = $item;
|
$this->collection[$item->getId()] = $item;
|
||||||
else
|
else
|
||||||
|
|
|
@ -128,7 +128,9 @@ class NewsPost implements JsonSerializable {
|
||||||
return Parser::instance(Parser::MARKDOWN)->parseText($this->getText());
|
return Parser::instance(Parser::MARKDOWN)->parseText($this->getText());
|
||||||
}
|
}
|
||||||
public function getFirstParagraph(): string {
|
public function getFirstParagraph(): string {
|
||||||
return first_paragraph($this->getText());
|
$text = $this->getText();
|
||||||
|
$index = mb_strpos($text, "\n");
|
||||||
|
return $index === false ? $text : mb_substr($text, 0, $index);
|
||||||
}
|
}
|
||||||
public function getParsedFirstParagraph(): string {
|
public function getParsedFirstParagraph(): string {
|
||||||
return Parser::instance(Parser::MARKDOWN)->parseText($this->getFirstParagraph());
|
return Parser::instance(Parser::MARKDOWN)->parseText($this->getFirstParagraph());
|
||||||
|
|
|
@ -23,7 +23,6 @@ final class TwigMisuzu extends AbstractExtension {
|
||||||
new TwigFilter('byte_symbol', 'byte_symbol'),
|
new TwigFilter('byte_symbol', 'byte_symbol'),
|
||||||
new TwigFilter('parse_text', fn(string $text, int $parser): string => Parser::instance($parser)->parseText($text)),
|
new TwigFilter('parse_text', fn(string $text, int $parser): string => Parser::instance($parser)->parseText($text)),
|
||||||
new TwigFilter('perms_check', 'perms_check'),
|
new TwigFilter('perms_check', 'perms_check'),
|
||||||
new TwigFilter('clamp', 'clamp'),
|
|
||||||
new TwigFilter('time_diff', [$this, 'timeDiff'], ['needs_environment' => true]),
|
new TwigFilter('time_diff', [$this, 'timeDiff'], ['needs_environment' => true]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Misuzu\Users;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use JsonSerializable;
|
use JsonSerializable;
|
||||||
|
use Index\XString;
|
||||||
use Index\Colour\Colour;
|
use Index\Colour\Colour;
|
||||||
use Misuzu\DB;
|
use Misuzu\DB;
|
||||||
use Misuzu\HasRankInterface;
|
use Misuzu\HasRankInterface;
|
||||||
|
@ -666,7 +667,7 @@ class User implements HasRankInterface, JsonSerializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function validatePassword(string $password): string {
|
public static function validatePassword(string $password): string {
|
||||||
if(unique_chars($password) < self::PASSWORD_UNIQUE)
|
if(XString::countUnique($password) < self::PASSWORD_UNIQUE)
|
||||||
return 'weak';
|
return 'weak';
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
|
|
|
@ -55,9 +55,10 @@ final class Zalgo {
|
||||||
|
|
||||||
public static function getString(array $array, int $length): string {
|
public static function getString(array $array, int $length): string {
|
||||||
$string = '';
|
$string = '';
|
||||||
|
$rngMax = count($array) - 1;
|
||||||
|
|
||||||
for($i = 0; $i < $length; $i++)
|
for($i = 0; $i < $length; $i++)
|
||||||
$string .= array_rand_value($array);
|
$string .= $array[mt_rand(0, $rngMax)];
|
||||||
|
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,8 @@
|
||||||
|
|
||||||
{% if topic.topic_pages|default(0) > 1 %}
|
{% if topic.topic_pages|default(0) > 1 %}
|
||||||
<div class="forum__topic__pagination">
|
<div class="forum__topic__pagination">
|
||||||
{% for i in 1..topic.topic_pages|clamp(0, 3) %}
|
{% set topic_pages_start_end = min(3, topic.topic_pages) %}
|
||||||
|
{% for i in 1..topic_pages_start_end %}
|
||||||
<a href="{{ url('forum-topic', {'topic': topic.topic_id, 'page': i}) }}" class="forum__topic__pagination__item">
|
<a href="{{ url('forum-topic', {'topic': topic.topic_id, 'page': i}) }}" class="forum__topic__pagination__item">
|
||||||
{{ i }}
|
{{ i }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -334,7 +335,8 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for i in (topic.topic_pages - 2)|clamp(4, topic.topic_pages)..topic.topic_pages %}
|
{% set topic_pages_end_start = max(4, min(topic.topic_pages, topic.topic_pages - 2)) %}
|
||||||
|
{% for i in topic_pages_end_start..topic.topic_pages %}
|
||||||
<a href="{{ url('forum-topic', {'topic': topic.topic_id, 'page': i}) }}" class="forum__topic__pagination__item">
|
<a href="{{ url('forum-topic', {'topic': topic.topic_id, 'page': i}) }}" class="forum__topic__pagination__item">
|
||||||
{{ i }}
|
{{ i }}
|
||||||
</a>
|
</a>
|
||||||
|
|
83
utility.php
83
utility.php
|
@ -1,62 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
use Index\Colour\Colour;
|
use Index\Colour\Colour;
|
||||||
|
|
||||||
function array_test(array $array, callable $func): bool {
|
|
||||||
foreach($array as $value)
|
|
||||||
if(!$func($value))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_apply(array $array, callable $func): array {
|
|
||||||
for($i = 0; $i < count($array); ++$i)
|
|
||||||
$array[$i] = $func($array[$i]);
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_bit_or(array $array1, array $array2): array {
|
|
||||||
foreach($array1 as $key => $value)
|
|
||||||
$array1[$key] |= $array2[$key] ?? 0;
|
|
||||||
return $array1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_rand_value(array $array) {
|
|
||||||
return $array[mt_rand(0, count($array) - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
function array_find(array $array, callable $callback) {
|
|
||||||
foreach($array as $item)
|
|
||||||
if($callback($item))
|
|
||||||
return $item;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clamp($num, int $min, int $max): int {
|
|
||||||
return max($min, min($max, (int)$num));
|
|
||||||
}
|
|
||||||
|
|
||||||
function first_paragraph(string $text, string $delimiter = "\n"): string {
|
|
||||||
$index = mb_strpos($text, $delimiter);
|
|
||||||
return $index === false ? $text : mb_substr($text, 0, $index);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unique_chars(string $input, bool $multibyte = true): int {
|
|
||||||
$chars = [];
|
|
||||||
$strlen = $multibyte ? 'mb_strlen' : 'strlen';
|
|
||||||
$substr = $multibyte ? 'mb_substr' : 'substr';
|
|
||||||
$length = $strlen($input);
|
|
||||||
|
|
||||||
for($i = 0; $i < $length; $i++) {
|
|
||||||
$current = $substr($input, $i, 1);
|
|
||||||
|
|
||||||
if(!in_array($current, $chars, true)) {
|
|
||||||
$chars[] = $current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count($chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
function byte_symbol(int $bytes, bool $decimal = false, array $symbols = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']): string {
|
function byte_symbol(int $bytes, bool $decimal = false, array $symbols = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']): string {
|
||||||
if($bytes < 1)
|
if($bytes < 1)
|
||||||
return '0 B';
|
return '0 B';
|
||||||
|
@ -125,30 +69,3 @@ function html_colour(int|null|Colour $colour, $attribs = '--user-colour'): strin
|
||||||
|
|
||||||
return $css;
|
return $css;
|
||||||
}
|
}
|
||||||
|
|
||||||
function msz_server_timing(\Index\Performance\Timings $timings): string {
|
|
||||||
$laps = $timings->getLaps();
|
|
||||||
$timings = [];
|
|
||||||
|
|
||||||
foreach($laps as $lap) {
|
|
||||||
$timing = $lap->getName();
|
|
||||||
if($lap->hasComment())
|
|
||||||
$timing .= ';desc="' . strtr($lap->getComment(), ['"' => '\\"']) . '"';
|
|
||||||
|
|
||||||
$timing .= ';dur=' . round($lap->getDurationTime(), 5);
|
|
||||||
$timings[] = $timing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf('Server-Timing: %s', implode(', ', $timings));
|
|
||||||
}
|
|
||||||
|
|
||||||
function msz_cookie_domain(bool $compatible = true): string {
|
|
||||||
$url = parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST);
|
|
||||||
if(empty($url))
|
|
||||||
$url = $_SERVER['HTTP_HOST'];
|
|
||||||
|
|
||||||
if(!filter_var($url, FILTER_VALIDATE_IP) && $compatible)
|
|
||||||
$url = '.' . $url;
|
|
||||||
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue