Cleaned up various utility functions.

This commit is contained in:
flash 2023-07-05 01:33:12 +00:00
parent 1bb9bd6541
commit 027ed5aff6
13 changed files with 63 additions and 106 deletions

@ -1 +1 @@
Subproject commit bce5ba77a268ecd6338d0e3520e41ff4c40cbeda
Subproject commit 8f908d7f688bd95fdedd868c5bf8d25a3b500b99

View file

@ -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 = [];
foreach($_POST['tags'] as $tagId)
foreach($_POST['tags'] as $tagId) {
if(!ctype_digit($tagId))
die('Invalid item encountered in roles list.');
try {
$applyTags[] = ChangelogTag::byId((int)filter_var($tagId, FILTER_SANITIZE_NUMBER_INT));
} catch(ChangelogTagNotFoundException $ex) {}
}
$change->setTags($applyTags);
}

View file

@ -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
$existingRoles = $userInfo->getRoles();
// Initialise set array with existing roles
$setRoles = $existingRoles;
// Read user input array and throw intval on em
$applyRoles = array_apply($_POST['roles'], 'intval');
// Storage array for roles to dump
$removeRoles = [];

View file

@ -50,12 +50,18 @@ if(!empty($_POST['warning']) && is_array($_POST['warning'])) {
if(!empty($customDuration)) {
switch($warningDuration) {
case -100: // YYYY-MM-DD
$splitDate = array_apply(explode('-', $customDuration, 3), function ($a) {
return (int)$a;
});
$splitDate = explode('-', $customDuration, 3);
if(count($splitDate) !== 3)
die('Invalid date specified.');
if(checkdate($splitDate[1], $splitDate[2], $splitDate[0]))
$warningDuration = mktime(0, 0, 0, $splitDate[1], $splitDate[2], $splitDate[0]) - time();
$wYear = (int)$splitDate[0];
$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;
case -200: // Raw seconds

View file

@ -173,17 +173,28 @@ class AuthToken {
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 {
if($expires > 0)
$this->cookieExpires = $expires;
else
$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 {
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);
}

View file

@ -87,7 +87,11 @@ function forum_perms_get_user(?int $forum, int $user): array {
$getPerms->bind('user_id_1', $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 {
@ -124,7 +128,11 @@ function forum_perms_get_role(?int $forum, int $role): array {
$getPerms->bind('forum_id', $forum);
$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 {

View file

@ -2,6 +2,7 @@
namespace Misuzu;
use InvalidArgumentException;
use Index\XArray;
// get rid of this garbage as soon as possible
@ -16,7 +17,7 @@ class Memoizer {
}
if(is_callable($find)) {
$item = array_find($this->collection, $find) ?? $create();
$item = XArray::first($this->collection, $find) ?? $create();
if(method_exists($item, 'getId'))
$this->collection[$item->getId()] = $item;
else

View file

@ -128,7 +128,9 @@ class NewsPost implements JsonSerializable {
return Parser::instance(Parser::MARKDOWN)->parseText($this->getText());
}
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 {
return Parser::instance(Parser::MARKDOWN)->parseText($this->getFirstParagraph());

View file

@ -23,7 +23,6 @@ final class TwigMisuzu extends AbstractExtension {
new TwigFilter('byte_symbol', 'byte_symbol'),
new TwigFilter('parse_text', fn(string $text, int $parser): string => Parser::instance($parser)->parseText($text)),
new TwigFilter('perms_check', 'perms_check'),
new TwigFilter('clamp', 'clamp'),
new TwigFilter('time_diff', [$this, 'timeDiff'], ['needs_environment' => true]),
];
}

View file

@ -4,6 +4,7 @@ namespace Misuzu\Users;
use DateTime;
use DateTimeZone;
use JsonSerializable;
use Index\XString;
use Index\Colour\Colour;
use Misuzu\DB;
use Misuzu\HasRankInterface;
@ -666,7 +667,7 @@ class User implements HasRankInterface, JsonSerializable {
}
public static function validatePassword(string $password): string {
if(unique_chars($password) < self::PASSWORD_UNIQUE)
if(XString::countUnique($password) < self::PASSWORD_UNIQUE)
return 'weak';
return '';

View file

@ -55,9 +55,10 @@ final class Zalgo {
public static function getString(array $array, int $length): string {
$string = '';
$rngMax = count($array) - 1;
for($i = 0; $i < $length; $i++)
$string .= array_rand_value($array);
$string .= $array[mt_rand(0, $rngMax)];
return $string;
}

View file

@ -322,7 +322,8 @@
{% if topic.topic_pages|default(0) > 1 %}
<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">
{{ i }}
</a>
@ -334,7 +335,8 @@
</div>
{% 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">
{{ i }}
</a>

View file

@ -1,62 +1,6 @@
<?php
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 {
if($bytes < 1)
return '0 B';
@ -125,30 +69,3 @@ function html_colour(int|null|Colour $colour, $attribs = '--user-colour'): strin
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;
}