diff --git a/app/API/Artist.php b/app/API/Artist.php index 07be464ce..645bf173a 100644 --- a/app/API/Artist.php +++ b/app/API/Artist.php @@ -19,7 +19,6 @@ class Artist extends AbstractAPI { if (!self::$db->has_results()) { json_error('Artist not found'); } - $artist = self::$db->next_record(MYSQLI_ASSOC, false); - return $artist; + return self::$db->next_record(MYSQLI_ASSOC, false); } } diff --git a/app/API/Forum.php b/app/API/Forum.php index 6865c6fec..86352838f 100644 --- a/app/API/Forum.php +++ b/app/API/Forum.php @@ -3,9 +3,6 @@ namespace Gazelle\API; class Forum extends AbstractAPI { - private $fid = null; - private $tid = null; - public function run() { if (!isset($_GET['topic_id'])) { json_error('Missing topic id'); @@ -27,7 +24,6 @@ class Forum extends AbstractAPI { if (!self::$db->has_results()) { json_error('Topic not found'); } - $thread = self::$db->next_record(MYSQLI_ASSOC, false); - return $thread; + return self::$db->next_record(MYSQLI_ASSOC, false); } } diff --git a/app/API/Torrent.php b/app/API/Torrent.php index 3d00ac763..cb16c584b 100644 --- a/app/API/Torrent.php +++ b/app/API/Torrent.php @@ -7,11 +7,9 @@ class Torrent extends AbstractAPI { switch ($_GET['req']) { case 'group': return $this->tgroup((int)($_GET['group_id'] ?? 0)); - break; default: case 'torrent': return $this->torrent((int)($_GET['torrent_id'] ?? 0)); - break; } } diff --git a/app/API/User.php b/app/API/User.php index ca0655161..643aee5d5 100644 --- a/app/API/User.php +++ b/app/API/User.php @@ -3,13 +3,13 @@ namespace Gazelle\API; class User extends AbstractAPI { - private $id = null; - private $username = null; - private $clear_tokens = false; + private int $id; + private string $username; + private bool $clear_tokens; public function run() { if (isset($_GET['user_id'])) { - $this->id = intval($_GET['user_id']); + $this->id = (int)$_GET['user_id']; } else if (isset($_GET['username'])) { $this->username = $_GET['username']; @@ -18,22 +18,13 @@ class User extends AbstractAPI { json_error("Need to supply either user_id or username"); } - if (isset($_GET['clear_tokens'])) { - $this->clear_tokens = true; - } + $this->clear_tokens = isset($_GET['clear_tokens']); - switch ($_GET['req']) { - case 'enable': - return $this->enableUser(); - break; - case 'disable': - return $this->disableUser(); - break; - default: - case 'stats': - return $this->getUser(); - break; - } + return match ($_GET['req']) { + 'enable' => $this->enableUser(), + 'disable' => $this->disableUser(), + default => $this->getUser(), + }; } private function getUser() { @@ -59,7 +50,7 @@ class User extends AbstractAPI { LEFT JOIN users_levels AS ul ON (ul.UserID = um.ID) LEFT JOIN user_bonus AS ub ON (ub.user_id = um.ID) WHERE - {$where}", ($this->id !== null) ? $this->id : $this->username); + {$where}", $this->id ?? $this->username); $user = self::$db->next_record(MYSQLI_ASSOC, ['IRCKey', 'Paranoia']); if (empty($user['Username'])) { @@ -121,7 +112,7 @@ class User extends AbstractAPI { INNER JOIN users_info AS ui ON (ui.UserID = um.ID) INNER JOIN user_flt AS uf ON (uf.user_id = um.ID) WHERE - {$where}", ($this->id !== null) ? $this->id : $this->username); + {$where}", $this->id ?? $this->username); // TODO: merge this and the version in takemoderate.php $UpdateSet = []; diff --git a/app/API/Wiki.php b/app/API/Wiki.php index 6520fff37..726acd74a 100644 --- a/app/API/Wiki.php +++ b/app/API/Wiki.php @@ -22,7 +22,6 @@ class Wiki extends AbstractAPI { if (!self::$db->has_results()) { json_error('Wiki article not found'); } - $article = self::$db->next_record(MYSQLI_ASSOC, false); - return $article; + return self::$db->next_record(MYSQLI_ASSOC, false); } } diff --git a/app/Applicant.php b/app/Applicant.php index e7812c806..384ce8003 100644 --- a/app/Applicant.php +++ b/app/Applicant.php @@ -12,12 +12,12 @@ class Applicant extends Base { protected $created; protected $modified; - const CACHE_KEY = 'applicant_%d'; - const CACHE_KEY_OPEN = 'applicant_list_open_%d'; - const CACHE_KEY_RESOLVED = 'applicant_list_resolved_%d'; - const CACHE_KEY_NEW_COUNT = 'applicant_new_count'; - const CACHE_KEY_NEW_REPLY = 'applicant_new_reply'; - const ENTRIES_PER_PAGE = 1000; // TODO: change to 50 and implement pagination + final const CACHE_KEY = 'applicant_%d'; + final const CACHE_KEY_OPEN = 'applicant_list_open_%d'; + final const CACHE_KEY_RESOLVED = 'applicant_list_resolved_%d'; + final const CACHE_KEY_NEW_COUNT = 'applicant_new_count'; + final const CACHE_KEY_NEW_REPLY = 'applicant_new_reply'; + final const ENTRIES_PER_PAGE = 1000; // TODO: change to 50 and implement pagination public function __construct(int $id) { $key = sprintf(self::CACHE_KEY, $id); @@ -42,7 +42,7 @@ class Applicant extends Base { $this->created = $data['Created']; $this->modified = $data['Modified']; $this->thread = new Thread($data['ThreadID']); - // If we are coming from createApplicant() we need to wipe the applicant list + // If we are coming from Manager\Applicatant::create() we need to wipe the applicant list $this->flushApplicantList(); } diff --git a/app/ApplicantRole.php b/app/ApplicantRole.php index bee44c02e..43de3d7a8 100644 --- a/app/ApplicantRole.php +++ b/app/ApplicantRole.php @@ -11,9 +11,9 @@ class ApplicantRole extends Base { protected $created; protected $modified; - const CACHE_KEY = 'approle_%d'; - const CACHE_KEY_ALL = 'approle_list_all'; - const CACHE_KEY_PUBLISHED = 'approle_list_published'; + final const CACHE_KEY = 'approle_%d'; + final const CACHE_KEY_ALL = 'approle_list_all'; + final const CACHE_KEY_PUBLISHED = 'approle_list_published'; public function __construct(int $id) { $key = sprintf(self::CACHE_KEY, $id); diff --git a/app/Artist.php b/app/Artist.php index ef3931380..e606484af 100644 --- a/app/Artist.php +++ b/app/Artist.php @@ -3,7 +3,7 @@ namespace Gazelle; class Artist extends Base { - const CACHE_REQUEST_ARTIST = 'artists_requests_%d'; + final const CACHE_REQUEST_ARTIST = 'artists_requests_%d'; protected const CACHE_PREFIX = 'artist_%d'; protected const DISCOGS_API_URL = 'https://api.discogs.com/artists/%d'; @@ -194,25 +194,15 @@ class Artist extends Base { ]; while ([$groupId, $role, $releaseTypeId] = self::$db->next_record(MYSQLI_NUM, false)) { - switch($role) { - case ARTIST_ARRANGER: - $sectionId = ARTIST_SECTION_ARRANGER; - break; - case ARTIST_PRODUCER: - $sectionId = ARTIST_SECTION_PRODUCER; - break; - case ARTIST_COMPOSER: - $sectionId = ARTIST_SECTION_COMPOSER; - break; - case ARTIST_REMIXER: - $sectionId = ARTIST_SECTION_REMIXER; - break; - case ARTIST_GUEST: - $sectionId = ARTIST_SECTION_GUEST; - break; - default: - $sectionId = $releaseTypeId; - } + $role = (int)$role; + $sectionId = match ($role) { + ARTIST_ARRANGER => ARTIST_SECTION_ARRANGER, + ARTIST_PRODUCER => ARTIST_SECTION_PRODUCER, + ARTIST_COMPOSER => ARTIST_SECTION_COMPOSER, + ARTIST_REMIXER => ARTIST_SECTION_REMIXER, + ARTIST_GUEST => ARTIST_SECTION_GUEST, + default => $releaseTypeId, + }; if (!isset($this->section[$sectionId])) { $this->section[$sectionId] = []; } @@ -359,9 +349,6 @@ class Artist extends Base { } /** - * @param int $userId - * @param string $name - * @param int $redirect * @return int|void */ public function addAlias(int $userId, string $name, int $redirect) { @@ -634,13 +621,9 @@ class Artist extends Base { } /* STATIC METHODS - for when you do not yet have an ID, e.g. during creation */ - /** * Collapse whitespace and directional markers, because people copypaste carelessly. * TODO: make stricter, e.g. on all whitespace characters or Unicode normalisation - * - * @param string $name - * @return string|null */ public static function sanitize(string $name): ?string { // \u200e is ‎ @@ -857,15 +840,14 @@ class Artist extends Base { // Now sort the artists by most relations first uksort($similar, fn ($a, $b) - => $similar[$b]['nrRelated'] <=> $similar[$a]['nrRelated'] - ?: $similar[$b]['score'] <=> $similar[$a]['score'] + => ($similar[$b]['nrRelated'] <=> $similar[$a]['nrRelated'] ?: $similar[$b]['score'] <=> $similar[$a]['score']) ?: $similar[$b]['artist_id'] <=> $similar[$a]['artist_id'] ); // Place the artists with the most relations first, and place // their relations near them, alternating on each side. - $xOrigin = (int)$width / 2; - $yOrigin = (int)$height / 2; + $xOrigin = $width / 2; + $yOrigin = $height / 2; $range = ($max === $min) ? $max : $max - $min; $placed = array_fill_keys(array_keys($similar), false); $seen = 0; @@ -886,7 +868,7 @@ class Artist extends Base { // Rotate the layout angles to fit this artist in, so that we can // pick the first and last angles off the layout list below. $move = (int)ceil(($relatedToPlace + 1) / 2); - $layout = array_merge(array_slice($layout, $move, NULL, true), array_slice($layout, 0, $move, true)); + $layout = [...array_slice($layout, $move, NULL, true), ...array_slice($layout, 0, $move, true)]; } if (!($relatedTotal > 0 && $seen > 1)) { $angle = array_shift($layout); @@ -927,7 +909,7 @@ class Artist extends Base { $distance = 0.9 - (($s['score'] - $min) * 0.4 / $range); $s['x'] = (int)(cos($angle) * $distance * $xOrigin) + $xOrigin; $s['y'] = (int)(sin($angle) * $distance * $yOrigin) + $yOrigin; - $s['proportion'] = pow($s['score'] / ($totalScore + 1), 1.0); + $s['proportion'] = ($s['score'] / ($totalScore + 1)) ** 1.0; // Place their related close by, first anti-clockwise (angle // increasing: array_shift(), next clockwise (angle decreasing: @@ -946,7 +928,7 @@ class Artist extends Base { $distance = 0.9 - (($similar[$r]['score'] - $min) * 0.45 / $range); $similar[$r]['x'] = (int)(cos($angle) * $distance * $xOrigin) + $xOrigin; $similar[$r]['y'] = (int)(sin($angle) * $distance * $yOrigin) + $yOrigin; - $similar[$r]['proportion'] = pow($similar[$r]['score'] / ($totalScore + 1), 1.0); + $similar[$r]['proportion'] = ($similar[$r]['score'] / ($totalScore + 1)) ** 1.0; } } diff --git a/app/ArtistRole/Request.php b/app/ArtistRole/Request.php index b0e231796..6ac91f6f3 100644 --- a/app/ArtistRole/Request.php +++ b/app/ArtistRole/Request.php @@ -44,7 +44,7 @@ class Request extends \Gazelle\ArtistRole { public function nameList(): array { $list = []; - foreach ($this->idList() as $role => $artistList) { + foreach ($this->idList() as $artistList) { foreach ($artistList as $artist) { $list[$artist['name']] = true; } diff --git a/app/BaseObject.php b/app/BaseObject.php index dfeea674c..7f17c0512 100644 --- a/app/BaseObject.php +++ b/app/BaseObject.php @@ -47,12 +47,8 @@ abstract class BaseObject extends Base { if (!$this->dirty()) { return false; } - $set = implode(', ', array_merge( - array_map(fn($f) => "$f = ?", array_keys($this->updateField)) - )); - $args = array_merge( - array_values($this->updateField), - ); + $set = implode(', ', [...array_map(fn($f) => "$f = ?", array_keys($this->updateField))]); + $args = [...array_values($this->updateField)]; $args[] = $this->id; self::$db->prepared_query( "UPDATE {$this->tableName()} SET $set WHERE {$this->pkName()} = ?", diff --git a/app/Better/AbstractBetter.php b/app/Better/AbstractBetter.php index e7d3fc095..5306e873c 100644 --- a/app/Better/AbstractBetter.php +++ b/app/Better/AbstractBetter.php @@ -3,8 +3,7 @@ namespace Gazelle\Better; abstract class AbstractBetter extends \Gazelle\Base { - - const CACHE_TOTAL = 'better_%s_total'; + final const CACHE_TOTAL = 'better_%s_total'; protected string $baseQuery; protected string $countBy; @@ -48,7 +47,7 @@ abstract class AbstractBetter extends \Gazelle\Base { } public function search(): ?string { - return isset($this->search) ? $this->search : null; + return $this->search ?? null; } public function addArtistUserSnatchJoin(): AbstractBetter { @@ -125,7 +124,7 @@ abstract class AbstractBetter extends \Gazelle\Base { } protected function totalCacheKey(): string { - $class = explode('\\', get_class($this)); + $class = explode('\\', static::class); return sprintf(self::CACHE_TOTAL, strtolower(array_pop($class))); } diff --git a/app/Blog.php b/app/Blog.php index 21eae9bb2..c1dc258cd 100644 --- a/app/Blog.php +++ b/app/Blog.php @@ -3,7 +3,7 @@ namespace Gazelle; class Blog extends BaseObject { - const CACHE_KEY = 'blog_%d'; + final const CACHE_KEY = 'blog_%d'; public function tableName(): string { return 'blog'; } diff --git a/app/BonusPool.php b/app/BonusPool.php index b3f9e1e45..c8bd786cd 100644 --- a/app/BonusPool.php +++ b/app/BonusPool.php @@ -3,7 +3,7 @@ namespace Gazelle; class BonusPool extends Base { - const CACHE_SENT = 'bonuspool_sent_%d'; + final const CACHE_SENT = 'bonuspool_sent_%d'; public function __construct ( protected readonly int $id, diff --git a/app/Cache.php b/app/Cache.php index 2b2cc6d9e..8857bcccd 100644 --- a/app/Cache.php +++ b/app/Cache.php @@ -27,7 +27,7 @@ class Cache extends \Memcached { /** * Torrent Group cache version */ - const GROUP_VERSION = 6; + final const GROUP_VERSION = 6; protected array $hit; protected array $delete; @@ -60,7 +60,7 @@ class Cache extends \Memcached { $ServerCheck = $ServerCheck || isset($ServerList["{$Server['host']}:11211"]); } if (!$ServerCheck) { - $Weight = (isset($Server['weight'])) ? $Server['weight'] : 0; + $Weight = $Server['weight'] ?? 0; $this->addServer($Server['host'], $Server['port'], $Weight); } } @@ -70,15 +70,17 @@ class Cache extends \Memcached { //---------- Caching functions ----------// // Wrapper for Memcache::set, with the zlib option removed and default duration of 30 days - public function cache_value($Key, $value, $Duration = 2592000) { + public function cache_value($key, $value, $Duration = 2_592_000): bool { $begin = microtime(true); - if (empty($Key)) { + if (empty($key)) { trigger_error("Cache insert failed for empty key"); } - if (!$this->set($Key, $value, $Duration)) { - trigger_error("Cache insert failed for key $Key:" . $this->getResultMessage()); + $result = $this->set($key, $value, $Duration); + if ($result === false) { + trigger_error("Cache insert failed for key $key:" . $this->getResultMessage()); } $this->elapsed += (microtime(true) - $begin) * 1000; + return $result; } public function get_value(string $key) { diff --git a/app/Collage.php b/app/Collage.php index 4a15cb207..602e87e80 100644 --- a/app/Collage.php +++ b/app/Collage.php @@ -10,9 +10,9 @@ class Collage extends BaseObject { * (artists or torrent groups). */ - const CACHE_KEY = 'collagev2_%d'; - const SUBS_KEY = 'collage_subs_user_%d'; - const SUBS_NEW_KEY = 'collage_subs_user_new_%d'; + final const CACHE_KEY = 'collagev2_%d'; + final const SUBS_KEY = 'collage_subs_user_%d'; + final const SUBS_NEW_KEY = 'collage_subs_user_new_%d'; protected bool $lockedForUser = false; protected array $userSubscriptions; @@ -153,8 +153,7 @@ class Collage extends BaseObject { } public function toggleSubscription(int $userId) { - $qid = self::$db->get_query_id(); - $delta = 0; + self::$db->get_query_id(); if (self::$db->scalar(" SELECT 1 FROM users_collage_subs @@ -178,18 +177,16 @@ class Collage extends BaseObject { ); $delta = 1; } - if ($delta !== 0) { - self::$db->prepared_query(" - UPDATE collages SET - Subscribers = greatest(0, Subscribers + ?) - WHERE ID = ? - ", $delta, $this->id - ); - self::$cache->delete_multi([ - sprintf(self::SUBS_KEY, $userId), - sprintf(self::SUBS_NEW_KEY, $userId), - ]); - } + self::$db->prepared_query(" + UPDATE collages SET + Subscribers = greatest(0, Subscribers + ?) + WHERE ID = ? + ", $delta, $this->id + ); + self::$cache->delete_multi([ + sprintf(self::SUBS_KEY, $userId), + sprintf(self::SUBS_NEW_KEY, $userId), + ]); $qid = self::$db->get_query_id(); return $this; } diff --git a/app/Collage/AbstractCollage.php b/app/Collage/AbstractCollage.php index 453f15162..cb2fb3f99 100644 --- a/app/Collage/AbstractCollage.php +++ b/app/Collage/AbstractCollage.php @@ -3,8 +3,6 @@ namespace Gazelle\Collage; abstract class AbstractCollage extends \Gazelle\Base { - protected \Gazelle\Collage $holder; - protected int $id; // hold a local copy of our ID to save time protected array $artists = []; protected array $contributors = []; @@ -15,9 +13,8 @@ abstract class AbstractCollage extends \Gazelle\Base { abstract public function load(): int; abstract protected function flushTarget(int $targetId): void; - public function __construct(\Gazelle\Collage $holder) { - $this->holder = $holder; - $this->id = $holder->id(); + public function __construct(protected \Gazelle\Collage $holder) { + $this->id = $holder->id(); } public function artistList(): array { @@ -151,9 +148,7 @@ abstract class AbstractCollage extends \Gazelle\Base { ); $userMap = self::$db->to_pair('cID', 'UserID'); $id = $this->id; - $args = array_merge(...array_map(function ($sort, $entryId) use ($id, $userMap) { - return [(int)$entryId, ($sort + 1) * 10, $id, $userMap[$entryId]]; - }, array_keys($series), $series)); + $args = array_merge(...array_map(fn($sort, $entryId) => [(int)$entryId, ($sort + 1) * 10, $id, $userMap[$entryId]], array_keys($series), $series)); self::$db->prepared_query(" INSERT INTO {$this->entryTable()} ({$this->entryColumn()}, Sort, CollageID, UserID) VALUES " . implode(', ', array_fill(0, count($series), '(?, ?, ?, ?)')) . " diff --git a/app/Collector.php b/app/Collector.php index 0bba9ae15..4e473d260 100644 --- a/app/Collector.php +++ b/app/Collector.php @@ -41,8 +41,8 @@ ORDER BY t.GroupID ASC, sequence DESC, tls.Seeders ASC */ abstract class Collector extends Base { - const CHUNK_SIZE = 100; - const ORDER_BY = ['t.RemasterTitle DESC', 'tls.Seeders ASC', 't.Size ASC']; + final const CHUNK_SIZE = 100; + final const ORDER_BY = ['t.RemasterTitle DESC', 'tls.Seeders ASC', 't.Size ASC']; protected $sql = ''; protected $args = []; @@ -69,7 +69,6 @@ abstract class Collector extends Base { protected readonly string $title, protected readonly int $orderBy, ) { - self::$cache->disableLocalCache(); // The internal cache is almost completely useless for this $this->startTime = microtime(true); $options = new \ZipStream\Option\Archive; @@ -99,40 +98,40 @@ abstract class Collector extends Base { continue; } $sql .= 'WHEN '; - switch ($Selection) { - case '00': $sql .= "t.Format = 'MP3' AND t.Encoding = 'V0 (VBR)'"; break; - case '01': $sql .= "t.Format = 'MP3' AND t.Encoding = 'APX (VBR)'"; break; - case '02': $sql .= "t.Format = 'MP3' AND t.Encoding = '256 (VBR)'"; break; - case '03': $sql .= "t.Format = 'MP3' AND t.Encoding = 'V1 (VBR)'"; break; - case '10': $sql .= "t.Format = 'MP3' AND t.Encoding = '224 (VBR)'"; break; - case '11': $sql .= "t.Format = 'MP3' AND t.Encoding = 'V2 (VBR)'"; break; - case '12': $sql .= "t.Format = 'MP3' AND t.Encoding = 'APS (VBR)'"; break; - case '13': $sql .= "t.Format = 'MP3' AND t.Encoding = '192 (VBR)'"; break; - case '20': $sql .= "t.Format = 'MP3' AND t.Encoding = '320'"; break; - case '21': $sql .= "t.Format = 'MP3' AND t.Encoding = '256'"; break; - case '22': $sql .= "t.Format = 'MP3' AND t.Encoding = '224'"; break; - case '23': $sql .= "t.Format = 'MP3' AND t.Encoding = '192'"; break; - case '24': $sql .= "t.Format = 'MP3' AND t.Encoding = '160'"; break; - case '25': $sql .= "t.Format = 'MP3' AND t.Encoding = '128'"; break; - case '26': $sql .= "t.Format = 'MP3' AND t.Encoding = '96'"; break; - case '27': $sql .= "t.Format = 'MP3' AND t.Encoding = '64'"; break; - case '30': $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'Vinyl'"; break; - case '31': $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'DVD'"; break; - case '32': $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'SACD'"; break; - case '33': $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'WEB'"; break; - case '34': $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1' AND LogScore = '100' AND HasCue = '1'"; break; - case '35': $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1' AND LogScore = '100'"; break; - case '36': $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1'"; break; - case '37': $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND t.Media = 'WEB'"; break; - case '38': $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless'"; break; - case '40': $sql .= "t.Format = 'DTS'"; break; - case '42': $sql .= "t.Format = 'AAC' AND t.Encoding = '320'"; break; - case '43': $sql .= "t.Format = 'AAC' AND t.Encoding = '256'"; break; - case '44': $sql .= "t.Format = 'AAC' AND t.Encoding = 'q5.5'"; break; - case '45': $sql .= "t.Format = 'AAC' AND t.Encoding = 'q5'"; break; - case '46': $sql .= "t.Format = 'AAC' AND t.Encoding = '192'"; break; - default: error(0); - } + match ($Selection) { + '00' => $sql .= "t.Format = 'MP3' AND t.Encoding = 'V0 (VBR)'", + '01' => $sql .= "t.Format = 'MP3' AND t.Encoding = 'APX (VBR)'", + '02' => $sql .= "t.Format = 'MP3' AND t.Encoding = '256 (VBR)'", + '03' => $sql .= "t.Format = 'MP3' AND t.Encoding = 'V1 (VBR)'", + '10' => $sql .= "t.Format = 'MP3' AND t.Encoding = '224 (VBR)'", + '11' => $sql .= "t.Format = 'MP3' AND t.Encoding = 'V2 (VBR)'", + '12' => $sql .= "t.Format = 'MP3' AND t.Encoding = 'APS (VBR)'", + '13' => $sql .= "t.Format = 'MP3' AND t.Encoding = '192 (VBR)'", + '20' => $sql .= "t.Format = 'MP3' AND t.Encoding = '320'", + '21' => $sql .= "t.Format = 'MP3' AND t.Encoding = '256'", + '22' => $sql .= "t.Format = 'MP3' AND t.Encoding = '224'", + '23' => $sql .= "t.Format = 'MP3' AND t.Encoding = '192'", + '24' => $sql .= "t.Format = 'MP3' AND t.Encoding = '160'", + '25' => $sql .= "t.Format = 'MP3' AND t.Encoding = '128'", + '26' => $sql .= "t.Format = 'MP3' AND t.Encoding = '96'", + '27' => $sql .= "t.Format = 'MP3' AND t.Encoding = '64'", + '30' => $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'Vinyl'", + '31' => $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'DVD'", + '32' => $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'SACD'", + '33' => $sql .= "t.Format = 'FLAC' AND t.Encoding = '24bit Lossless' AND t.Media = 'WEB'", + '34' => $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1' AND LogScore = '100' AND HasCue = '1'", + '35' => $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1' AND LogScore = '100'", + '36' => $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND HasLog = '1'", + '37' => $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless' AND t.Media = 'WEB'", + '38' => $sql .= "t.Format = 'FLAC' AND t.Encoding = 'Lossless'", + '40' => $sql .= "t.Format = 'DTS'", + '42' => $sql .= "t.Format = 'AAC' AND t.Encoding = '320'", + '43' => $sql .= "t.Format = 'AAC' AND t.Encoding = '256'", + '44' => $sql .= "t.Format = 'AAC' AND t.Encoding = 'q5.5'", + '45' => $sql .= "t.Format = 'AAC' AND t.Encoding = 'q5'", + '46' => $sql .= "t.Format = 'AAC' AND t.Encoding = '192'", + default => error(0), + }; $sql .= "THEN $Priority "; } $sql .= "ELSE 100 END AS sequence, "; @@ -245,7 +244,6 @@ abstract class Collector extends Base { */ public function emit() { $this->fill(); - $folder = safeFilename($this->title); $this->zip->addFile("README.txt", $this->summary()); if ($this->error) { $this->zip->addFile("ERRORS.txt", $this->errors()); diff --git a/app/Collector/Artist.php b/app/Collector/Artist.php index 5715eff38..7826d14de 100644 --- a/app/Collector/Artist.php +++ b/app/Collector/Artist.php @@ -3,7 +3,6 @@ namespace Gazelle\Collector; class Artist extends \Gazelle\Collector { - protected $artist; protected $roleList = []; @@ -37,7 +36,6 @@ class Artist extends \Gazelle\Collector { } public function fill() { - $filer = new \Gazelle\File\Torrent; $releaseMan = new \Gazelle\ReleaseType; while ([$Downloads, $GroupIDs] = $this->process('GroupID')) { if (is_null($Downloads)) { @@ -56,35 +54,17 @@ class Artist extends \Gazelle\Collector { $GroupID = $GroupIDs[$TorrentID]; $info =& $Downloads[$GroupID]; $info['Artist'] = \Artists::display_artists($Artists[$GroupID], false, false, false); - switch ($this->roleList[$GroupID]) { - case ARTIST_MAIN: - $ReleaseTypeName = $releaseMan->findNameById($info['ReleaseType']); - break; - case ARTIST_GUEST: - $ReleaseTypeName = 'Guest Appearance'; - break; - case ARTIST_REMIXER: - $ReleaseTypeName = 'Remixed By'; - break; - case ARTIST_COMPOSER: - $ReleaseTypeName = 'Composition'; - break; - case ARTIST_CONDUCTOR: - $ReleaseTypeName = 'Conducted By'; - break; - case ARTIST_DJ: - $ReleaseTypeName = 'DJ Mix'; - break; - case ARTIST_PRODUCER: - $ReleaseTypeName = 'Produced By'; - break; - case ARTIST_ARRANGER: - $ReleaseTypeName = 'Arranged By'; - break; - default: - $ReleaseTypeName = 'Other-' . $this->roleList[$GroupID]; - break; - } + $ReleaseTypeName = match ($this->roleList[$GroupID]) { + ARTIST_MAIN => $releaseMan->findNameById($info['ReleaseType']), + ARTIST_GUEST => 'Guest Appearance', + ARTIST_REMIXER => 'Remixed By', + ARTIST_COMPOSER => 'Composition', + ARTIST_CONDUCTOR => 'Conducted By', + ARTIST_DJ => 'DJ Mix', + ARTIST_PRODUCER => 'Produced By', + ARTIST_ARRANGER => 'Arranged By', + default => 'Other-' . $this->roleList[$GroupID], + }; $this->add($info, $ReleaseTypeName); } } diff --git a/app/Contest.php b/app/Contest.php index b92fe2ec2..8ea3c7a8d 100644 --- a/app/Contest.php +++ b/app/Contest.php @@ -3,9 +3,9 @@ namespace Gazelle; class Contest extends BaseObject { - const CACHE_CONTEST = 'contestv2_%d'; - const CACHE_STATS = 'contest_stats_%d'; - const CONTEST_LEADERBOARD_CACHE_KEY = 'contest_leaderboard_%d_%d'; + final const CACHE_CONTEST = 'contestv2_%d'; + final const CACHE_STATS = 'contest_stats_%d'; + final const CONTEST_LEADERBOARD_CACHE_KEY = 'contest_leaderboard_%d_%d'; protected array $stats; /* entries, users */ diff --git a/app/DB.php b/app/DB.php index 13b51f8b0..4fc50f2d7 100644 --- a/app/DB.php +++ b/app/DB.php @@ -3,7 +3,6 @@ namespace Gazelle; class DB extends Base { - /** * Skip foreign key checks * @param bool $relax true if foreign key checks should be skipped @@ -92,7 +91,7 @@ class DB extends Base { if (self::$db->affected_rows() == 0) { return [false, "condition selected 0 rows"]; } - } catch (DB\Mysql_DuplicateKeyException $e) { + } catch (DB\Mysql_DuplicateKeyException) { // do nothing, for some reason it was already deleted } diff --git a/app/DB/Mysql.php b/app/DB/Mysql.php index 99081c967..9301d5294 100644 --- a/app/DB/Mysql.php +++ b/app/DB/Mysql.php @@ -208,7 +208,7 @@ class Mysql { * or TRUE for other successful DML queries * or FALSE on failure. */ - public function execute(...$Parameters) { + public function execute(...$Parameters): \mysqli_result|bool { /** @var \mysqli_stmt $Statement */ $Statement = &$this->Statement; @@ -232,7 +232,7 @@ class Mysql { try { $Statement->execute(); return $Statement->get_result(); - } catch (\mysqli_sql_exception $e) { + } catch (\mysqli_sql_exception) { if (mysqli_error($this->LinkID) == 1062) { throw new Mysql_DuplicateKeyException; } @@ -253,9 +253,8 @@ class Mysql { * the two functions separately instead of this function. * * @param mixed ...$Parameters - * @return bool|\mysqli_result */ - public function prepared_query(string $Query, ...$Parameters) { + public function prepared_query(string $Query, mixed ...$Parameters): bool|\mysqli_result { $this->prepare($Query); return $this->execute(...$Parameters); } @@ -272,7 +271,7 @@ class Mysql { $Debug->analysis('Non-Fatal Deadlock:', $Query, 3600 * 24); trigger_error("Database deadlock, attempt $i"); - sleep($i * rand(2, 5)); // Wait longer as attempts increase + sleep($i * random_int(2, 5)); // Wait longer as attempts increase } $QueryEndTime = microtime(true); // Kills admin pages, and prevents Debug->analysis when the whole set exceeds 1 MB @@ -335,7 +334,7 @@ class Mysql { * @param mixed $Escape Boolean true/false for escaping entire/none of query * or can be an array of array keys for what columns to escape */ - public function fetch_record(...$Escape): ?array { + public function fetch_record(mixed ...$Escape): ?array { if (count($Escape) === 1 && $Escape[0] === true) { $Escape = true; } @@ -455,7 +454,7 @@ class Mysql { * @param mixed $args The values of the placeholders * @return array key=>value resultset or null */ - public function rowAssoc(string $sql, ...$args): ?array { + public function rowAssoc(string $sql, mixed ...$args): ?array { $qid = $this->get_query_id(); $this->prepared_query($sql, ...$args); $result = $this->next_record(MYSQLI_ASSOC, false); @@ -469,7 +468,7 @@ class Mysql { * Stashes the current query id so that this can be used within a block * that is looping over an active resultset. */ - public function scalar(string $sql, mixed ...$args): int|string|bool|null { + public function scalar(string $sql, mixed ...$args): int|float|string|bool|null { $qid = $this->get_query_id(); $this->prepared_query($sql, ...$args); $result = $this->has_results() ? $this->next_record(MYSQLI_NUM, false) : [null]; @@ -545,7 +544,7 @@ class Mysql { * @param boolean $Reverse reverses $Escape such that then it's an array of keys to escape * @return array mutated version of $Array with values escaped. */ - protected function display_array(array $Array, mixed $Escape = [], bool $Reverse = false): array { + protected function display_array(array $Array, bool|array $Escape = [], bool $Reverse = false): array { foreach ($Array as $Key => $Val) { if ((!is_array($Escape) && $Escape == true) || (!$Reverse && !in_array($Key, $Escape)) || ($Reverse && in_array($Key, $Escape))) { $Array[$Key] = display_str($Val); diff --git a/app/Debug.php b/app/Debug.php index 72c5b5e96..c0c340b27 100644 --- a/app/Debug.php +++ b/app/Debug.php @@ -26,7 +26,7 @@ class Debug { public function __construct(\Gazelle\Cache $cache, DB\Mysql $db) { if (self::$cpuTime === false) { $r = getrusage(); - self::$cpuTime = $r['ru_utime.tv_sec'] * 1000000 + $r['ru_utime.tv_usec']; + self::$cpuTime = $r['ru_utime.tv_sec'] * 1_000_000 + $r['ru_utime.tv_usec']; } self::$cache =& $cache; self::$db =& $db; @@ -34,7 +34,7 @@ class Debug { public function handle_errors() { error_reporting(E_WARNING | E_ERROR | E_PARSE); - set_error_handler([$this, 'php_error_handler']); + set_error_handler($this->php_error_handler(...)); return $this; } @@ -166,7 +166,7 @@ class Debug { public function get_cpu_time() { if (!defined('PHP_WINDOWS_VERSION_MAJOR')) { $RUsage = getrusage(); - self::$cpuTime = $RUsage['ru_utime.tv_sec'] * 1000000 + $RUsage['ru_utime.tv_usec'] - self::$cpuTime; + self::$cpuTime = $RUsage['ru_utime.tv_sec'] * 1_000_000 + $RUsage['ru_utime.tv_usec'] - self::$cpuTime; return self::$cpuTime; } return false; @@ -205,7 +205,7 @@ class Debug { } elseif (is_string($Val)) { $Return[$Key] .= "'$Val'"; } elseif (is_object($Val)) { - $Return[$Key] .= get_class($Val); + $Return[$Key] .= $Val::class; } elseif (is_array($Val)) { $Return[$Key] .= '['.$this->format_args($Val).']'; } @@ -214,7 +214,7 @@ class Debug { return implode(', ', $Return); } - public function php_error_handler($Level, $Error, $File, $Line) { + public function php_error_handler($Level, string $Error, $File, $Line) { //Who added this, it's still something to pay attention to... if (stripos('Undefined index', $Error) !== false) { //return true; @@ -333,7 +333,7 @@ class Debug { 'Page process time' => number_format($PageTime, 3).' s', ]; if ($CPUTime) { - $Perf['CPU time'] = number_format($CPUTime / 1000000, 3).' s'; + $Perf['CPU time'] = number_format($CPUTime / 1_000_000, 3).' s'; } $Perf['Script start'] = Time::sqlTime(self::$startTime); $Perf['Script end'] = Time::sqlTime(microtime(true)); diff --git a/app/Feed.php b/app/Feed.php index ec0545f85..9d3fc37d7 100644 --- a/app/Feed.php +++ b/app/Feed.php @@ -3,7 +3,6 @@ namespace Gazelle; class Feed extends Base { - function header(): string { header('Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0'); header('Pragma:'); @@ -48,7 +47,7 @@ class Feed extends Base { } function populate(string $key, string $item): int { - $list = self::$cache->get_value($key, true); + $list = self::$cache->get_value($key); if ($list === false) { $list = []; } diff --git a/app/File/RipLog.php b/app/File/RipLog.php index 450f26a00..ae6d02835 100644 --- a/app/File/RipLog.php +++ b/app/File/RipLog.php @@ -3,8 +3,8 @@ namespace Gazelle\File; class RipLog extends \Gazelle\File { - const STORAGE = STORAGE_PATH_RIPLOG; - const STORAGE_LEGACY = SERVER_ROOT_LIVE . '/logs'; + final const STORAGE = STORAGE_PATH_RIPLOG; + final const STORAGE_LEGACY = SERVER_ROOT_LIVE . '/logs'; /** * Move an existing rip log to the file storage location. diff --git a/app/File/RipLogHTML.php b/app/File/RipLogHTML.php index c937610fe..6f18fb6ec 100644 --- a/app/File/RipLogHTML.php +++ b/app/File/RipLogHTML.php @@ -3,7 +3,7 @@ namespace Gazelle\File; class RipLogHTML extends \Gazelle\File { - const STORAGE = STORAGE_PATH_RIPLOGHTML; + final const STORAGE = STORAGE_PATH_RIPLOGHTML; /** * Remove one or more HTML-ized rip logs of a torrent diff --git a/app/File/Torrent.php b/app/File/Torrent.php index adfe740d0..201c49dab 100644 --- a/app/File/Torrent.php +++ b/app/File/Torrent.php @@ -3,7 +3,7 @@ namespace Gazelle\File; class Torrent extends \Gazelle\File { - const STORAGE = STORAGE_PATH_TORRENT; + final const STORAGE = STORAGE_PATH_TORRENT; /** * Path of a torrent file diff --git a/app/Forum.php b/app/Forum.php index 0c5183a40..7756a64d0 100644 --- a/app/Forum.php +++ b/app/Forum.php @@ -3,10 +3,10 @@ namespace Gazelle; class Forum extends BaseObject { - const CACHE_TOC_FORUM = 'forum_tocv2_%d'; - const CACHE_FORUM = 'forum_%d'; - const CACHE_THREAD_INFO = 'thread_%d_info'; - const CACHE_CATALOG = 'thread_%d_catalogue_%d'; + final const CACHE_TOC_FORUM = 'forum_tocv2_%d'; + final const CACHE_FORUM = 'forum_%d'; + final const CACHE_THREAD_INFO = 'thread_%d_info'; + final const CACHE_CATALOG = 'thread_%d_catalogue_%d'; protected \Gazelle\DB\Pg $pg; @@ -41,7 +41,6 @@ class Forum extends BaseObject { // TODO: rewrite to use BaseObject::modify() public function modifyForum(array $args): bool { - $autolock = isset($_POST['autolock']) ? '1' : '0'; self::$db->prepared_query(" UPDATE forums SET Sort = ?, @@ -255,7 +254,6 @@ class Forum extends BaseObject { * The table of contents of a forum. Only the first page is cached, * the subsequent pages are regenerated on each pageview. * - * @return array * - int 'ID' Forum id * - string 'Title' Thread name "We will snatch your unsnatched FLACs" * - int 'AuthorID' User id of author @@ -325,8 +323,7 @@ class Forum extends BaseObject { ORDER BY f.Sort ", $user->id(), $user->id(), $this->id, ...$args ); - $departmentList = self::$db->to_array('forum_id', MYSQLI_ASSOC, false); - return $departmentList; + return self::$db->to_array('forum_id', MYSQLI_ASSOC, false); } public function userCatchup(int $userId) { @@ -345,7 +342,6 @@ class Forum extends BaseObject { /** * Return a list of which page the user has read up to * - * @return array * - int 'TopicID' The thread id * - int 'PostID' The post id * - int 'Page' The page number diff --git a/app/ForumCategory.php b/app/ForumCategory.php index 1a25d6b1a..57303534d 100644 --- a/app/ForumCategory.php +++ b/app/ForumCategory.php @@ -3,7 +3,7 @@ namespace Gazelle; class ForumCategory extends BaseObject { - const CACHE_KEY = 'forum_cat_%d'; + final const CACHE_KEY = 'forum_cat_%d'; protected array $info; diff --git a/app/ForumPoll.php b/app/ForumPoll.php index b912ab77f..0a71d5f0b 100644 --- a/app/ForumPoll.php +++ b/app/ForumPoll.php @@ -3,7 +3,7 @@ namespace Gazelle; class ForumPoll extends BaseObject { - const CACHE_KEY = 'forum_poll_%d'; + final const CACHE_KEY = 'forum_poll_%d'; public function flush(): ForumPoll { self::$cache->delete_value(sprintf(self::CACHE_KEY, $this->id)); @@ -226,10 +226,6 @@ class ForumPoll extends BaseObject { ", $this->id ); $affected += self::$db->affected_rows(); - $Featured = self::$db->scalar(" - SELECT Featured FROM forums_polls WHERE TopicID = ? - ", $this->id - ); self::$cache->cache_value('polls_featured', $this->id, 0); } diff --git a/app/ForumPost.php b/app/ForumPost.php index 095bdf96e..98902cce4 100644 --- a/app/ForumPost.php +++ b/app/ForumPost.php @@ -3,7 +3,7 @@ namespace Gazelle; class ForumPost extends BaseObject { - const CACHE_KEY = 'fpost_%d'; + final const CACHE_KEY = 'fpost_%d'; public function flush(): ForumPost { self::$cache->delete_value(sprintf(self::CACHE_KEY, $this->id)); diff --git a/app/ForumThread.php b/app/ForumThread.php index 2a07c9740..228335df3 100644 --- a/app/ForumThread.php +++ b/app/ForumThread.php @@ -3,8 +3,8 @@ namespace Gazelle; class ForumThread extends BaseObject { - const CACHE_KEY = 'fthread_%d'; - const CACHE_CATALOG = 'fthread_cat_%d_%d'; + final const CACHE_KEY = 'fthread_%d'; + final const CACHE_CATALOG = 'fthread_cat_%d_%d'; public function flush(): ForumThread { self::$cache->delete_value(sprintf(self::CACHE_KEY, $this->id)); diff --git a/app/Image.php b/app/Image.php index 6cfe81b03..3c55eca6d 100644 --- a/app/Image.php +++ b/app/Image.php @@ -26,26 +26,27 @@ class Image { } function display() { - switch($this->type) { - case IMAGETYPE_BMP: return imagebmp($this->image); - case IMAGETYPE_GIF: return imagegif($this->image); - case IMAGETYPE_JPEG: return imagejpeg($this->image, null, 90); - case IMAGETYPE_PNG: return imagepng($this->image); - case IMAGETYPE_WEBP: return imagewebp($this->image); - case IMAGETYPE_XBM: return imagexbm($this->image, null); - } + return match ($this->type) { + IMAGETYPE_BMP => imagebmp($this->image), + IMAGETYPE_GIF => imagegif($this->image), + IMAGETYPE_JPEG => imagejpeg($this->image, null, 90), + IMAGETYPE_PNG => imagepng($this->image), + IMAGETYPE_WEBP => imagewebp($this->image), + IMAGETYPE_XBM => imagexbm($this->image, null), + default => null, + }; } function type(): string { - switch($this->type) { - case IMAGETYPE_BMP: return 'bmp'; - case IMAGETYPE_GIF: return 'gif'; - case IMAGETYPE_JPEG: return 'jpg'; - case IMAGETYPE_PNG: return 'png'; - case IMAGETYPE_WEBP: return 'webp'; - case IMAGETYPE_XBM: return 'xpm'; - default: return 'error'; - } + return match ($this->type) { + IMAGETYPE_BMP => 'bmp', + IMAGETYPE_GIF => 'gif', + IMAGETYPE_JPEG => 'jpg', + IMAGETYPE_PNG => 'png', + IMAGETYPE_WEBP => 'webp', + IMAGETYPE_XBM => 'xpm', + default => 'error', + }; } public function error(): bool { diff --git a/app/Inbox.php b/app/Inbox.php index 22ded4ae8..23abb690c 100644 --- a/app/Inbox.php +++ b/app/Inbox.php @@ -39,7 +39,7 @@ class Inbox extends BaseUser { } public function searchTerm(): ?string { - return isset($this->searchTerm) ? $this->searchTerm : null; + return $this->searchTerm ?? null; } public function showUnreadFirst(): bool { @@ -92,34 +92,24 @@ class Inbox extends BaseUser { $cond[] = "cu.InInbox = '1'"; } if (isset($this->searchField) && isset($this->searchTerm) && !empty($this->searchTerm)) { - switch($this->searchField) { - case 'subject': - $cond[] = "c.Subject LIKE concat('%', ?, '%')"; - break; - case 'user': - $cond[] = 'um.Username = ?'; - break; - case 'message': - $cond[] = "pm.Body LIKE concat('%', ?, '%')"; - break; - default: - throw new \UnexpectedValueException($this->searchField); - break; - } + $cond[] = match ($this->searchField) { + 'subject' => "c.Subject LIKE concat('%', ?, '%')", + 'user' => 'um.Username = ?', + 'message' => "pm.Body LIKE concat('%', ?, '%')", + default => '1 = 0', + }; $args[] = $this->searchTerm; } if (isset($this->filter)) { switch($this->filter) { - case 'all': - break; case 'system': $cond[] = "cu2.UserID IS NULL"; break; case 'user': $cond[] = "cu2.UserID IS NOT NULL"; break; + case 'all': default: - throw new \UnexpectedValueException($this->filter); break; } } diff --git a/app/Json.php b/app/Json.php index c8d6cc672..5a7e9e61c 100644 --- a/app/Json.php +++ b/app/Json.php @@ -64,7 +64,7 @@ abstract class Json extends Base { ), $this->mode ); - } catch (\JsonException $e) { + } catch (\JsonException) { $this->failure("JSON encoding failed, look for malformed UTF-8 encoding"); } } diff --git a/app/Json/AddLog.php b/app/Json/AddLog.php index 29ee2766b..a9608c4c2 100644 --- a/app/Json/AddLog.php +++ b/app/Json/AddLog.php @@ -16,6 +16,7 @@ class AddLog extends \Gazelle\Json { ) {} public function payload(): ?array { + $logfiles = []; if ($this->user->id() !== $this->torrent->uploaderId() && !$this->user->permitted('admin_add_log')) { $this->failure('Not the torrent owner or moderator'); return null; diff --git a/app/Json/Artist.php b/app/Json/Artist.php index a678d5402..b8265680a 100644 --- a/app/Json/Artist.php +++ b/app/Json/Artist.php @@ -34,7 +34,7 @@ class Artist extends \Gazelle\Json { continue; } $artists = $tgroup->artistRole()->legacyList(); - $artists = isset($artists[1]) ? $artists[1] : null; + $artists = $artists[1] ?? null; $Found = $this->search_array($artists, 'id', $artistId); if ($this->releasesOnly && empty($Found)) { continue; diff --git a/app/Json/Inbox.php b/app/Json/Inbox.php index 2af5ee7f5..9a37d2840 100644 --- a/app/Json/Inbox.php +++ b/app/Json/Inbox.php @@ -111,9 +111,9 @@ class Inbox extends \Gazelle\Json { 'senderId' => $senderId, 'username' => $senderId ? $user[$senderId]->username() : 'System', 'avatar' => $senderId ? $user[$senderId]->avatar() : null, - 'warned' => $senderId ? $user[$senderId]->isWarned() : false, - 'enabled' => $senderId ? $user[$senderId]->isEnabled() : false, - 'donor' => $senderId ? (new \Gazelle\User\Privilege($user[$senderId]))->isDonor() : false, + 'warned' => $senderId && $user[$senderId]->isWarned(), + 'enabled' => $senderId && $user[$senderId]->isEnabled(), + 'donor' => $senderId && (new \Gazelle\User\Privilege($user[$senderId]))->isDonor(), 'date' => $actionDate, ]; self::$db->set_query_id($qid); diff --git a/app/Json/RipLog.php b/app/Json/RipLog.php index 26be4e266..dd791484a 100644 --- a/app/Json/RipLog.php +++ b/app/Json/RipLog.php @@ -12,7 +12,7 @@ class RipLog extends \Gazelle\Json { try { $logFile = (new \Gazelle\File\RipLog)->get([$this->torrentId, $this->logId]); $ripLog = new \Gazelle\RipLog($this->torrentId, $this->logId); - } catch (\Gazelle\Exception\ResourceNotFoundException $e) { + } catch (\Gazelle\Exception\ResourceNotFoundException) { return []; } diff --git a/app/Json/User.php b/app/Json/User.php index 58bb26a3d..824291fbe 100644 --- a/app/Json/User.php +++ b/app/Json/User.php @@ -21,7 +21,7 @@ class User extends \Gazelle\Json { $stats = $user->stats(); $forumPosts = $stats->forumPostTotal(); $releaseVotes = (new Vote($user))->userTotal(Vote::UPVOTE|Vote::DOWNVOTE); - $uploaded = $this->valueOrNull($user->downloadedSize(), 'uploaded'); + $uploaded = $this->valueOrNull($user->uploadedSize(), 'uploaded'); $downloaded = $this->valueOrNull($user->downloadedSize(), 'downloaded'); $uploads = $this->valueOrNull($stats->uploadTotal(), 'uploads+'); $artistsAdded = $this->valueOrNull($stats->artistAddedTotal(), 'artistsadded'); @@ -77,7 +77,7 @@ class User extends \Gazelle\Json { is_null($uploaded) || is_null($downloaded) => null, !$downloaded => 0.0, - default => (float)round($uploaded / $downloaded, 2, PHP_ROUND_HALF_DOWN), + default => round($uploaded / $downloaded, 2, PHP_ROUND_HALF_DOWN), }, ], 'ranks' => [ diff --git a/app/Log.php b/app/Log.php index a735df9fd..9c380fd4b 100644 --- a/app/Log.php +++ b/app/Log.php @@ -21,8 +21,6 @@ class Log extends Base { /** * Write a group entry * - * @param int $groupId - * @param int $userId * @param string $message */ public function group(int $groupId, int $userId, $message) { @@ -40,9 +38,6 @@ class Log extends Base { /** * Write a torrent entry * - * @param int $groupId - * @param int $torrentId - * @param int $userId * @param string $message */ public function torrent(int $groupId, int $torrentId, int $userId, $message) { diff --git a/app/Login.php b/app/Login.php index 931f95277..54001d9e2 100644 --- a/app/Login.php +++ b/app/Login.php @@ -3,12 +3,11 @@ namespace Gazelle; class Login extends Base { - - public const NO_ERROR = 0; - public const ERR_USERNAME = 1; - public const ERR_PASSWORD = 2; - public const ERR_CREDENTIALS = 3; - public const ERR_UNCONFIRMED = 4; + final public const NO_ERROR = 0; + final public const ERR_USERNAME = 1; + final public const ERR_PASSWORD = 2; + final public const ERR_CREDENTIALS = 3; + final public const ERR_UNCONFIRMED = 4; protected int $error = self::NO_ERROR; protected bool $persistent = false; diff --git a/app/Manager/Applicant.php b/app/Manager/Applicant.php index 09d3c09d3..5e650f22b 100644 --- a/app/Manager/Applicant.php +++ b/app/Manager/Applicant.php @@ -3,13 +3,13 @@ namespace Gazelle\Manager; class Applicant extends \Gazelle\Base { - const ID_KEY = 'zz_appl_%d'; - const CACHE_KEY = 'applicant_%d'; - const CACHE_KEY_OPEN = 'applicant_list_open_%d'; - const CACHE_KEY_RESOLVED = 'applicant_list_resolved_%d'; - const CACHE_KEY_NEW_COUNT = 'applicant_new_count'; - const CACHE_KEY_NEW_REPLY = 'applicant_new_reply'; - const ENTRIES_PER_PAGE = 1000; // TODO: change to 50 and implement pagination + final const ID_KEY = 'zz_appl_%d'; + final const CACHE_KEY = 'applicant_%d'; + final const CACHE_KEY_OPEN = 'applicant_list_open_%d'; + final const CACHE_KEY_RESOLVED = 'applicant_list_resolved_%d'; + final const CACHE_KEY_NEW_COUNT = 'applicant_new_count'; + final const CACHE_KEY_NEW_REPLY = 'applicant_new_reply'; + final const ENTRIES_PER_PAGE = 1000; // TODO: change to 50 and implement pagination public function findById(int $applicantId): ?\Gazelle\Applicant { $key = sprintf(self::ID_KEY, $applicantId); @@ -26,7 +26,7 @@ class Applicant extends \Gazelle\Base { return $id ? new \Gazelle\Applicant($id) : null; } - public function createApplicant(int $userId, int $roleId, string $body) { + public function create(int $userId, int $roleId, string $body) { self::$db->prepared_query(" INSERT INTO applicant (RoleID, UserID, Body, ThreadID) @@ -35,7 +35,7 @@ class Applicant extends \Gazelle\Base { (new Thread())->createThread('staff-role')->id() ); self::$cache->delete_value(self::CACHE_KEY_NEW_COUNT); - return new \Gazelle\Applicant(self::$db->inserted_id()); + return $this->findById(self::$db->inserted_id()); } /** diff --git a/app/Manager/ApplicantRole.php b/app/Manager/ApplicantRole.php index f8b13f9fa..c466f8c28 100644 --- a/app/Manager/ApplicantRole.php +++ b/app/Manager/ApplicantRole.php @@ -3,9 +3,9 @@ namespace Gazelle\Manager; class ApplicantRole extends \Gazelle\Base { - const ID_KEY = 'zz_applr_%d'; - const CACHE_KEY_ALL = 'approle_list_all'; - const CACHE_KEY_PUBLISHED = 'approle_list_published'; + final const ID_KEY = 'zz_applr_%d'; + final const CACHE_KEY_ALL = 'approle_list_all'; + final const CACHE_KEY_PUBLISHED = 'approle_list_published'; public function findById(int $roleId): ?\Gazelle\ApplicantRole { $key = sprintf(self::ID_KEY, $roleId); @@ -29,6 +29,7 @@ class ApplicantRole extends \Gazelle\Base { VALUES (?, ?, ?, ?) ", $title, $description, $published ? 1 : 0, $userId ); + self::$cache->deleteMulti([self::CACHE_KEY_ALL, self::CACHE_KEY_PUBLISHED]); return $this->findById(self::$db->inserted_id()); } @@ -56,7 +57,7 @@ class ApplicantRole extends \Gazelle\Base { } public function title(int $roleId): ?string { - $role = array_filter($this->list(true), function ($r) use ($roleId) { return $r['role_id'] == $roleId;}); + $role = array_filter($this->list(true), fn ($r) => $r['role_id'] == $roleId); return current($role)['title'] ?? null; } } diff --git a/app/Manager/AutoEnable.php b/app/Manager/AutoEnable.php index 65b3baa81..67b5ee8ef 100644 --- a/app/Manager/AutoEnable.php +++ b/app/Manager/AutoEnable.php @@ -3,12 +3,11 @@ namespace Gazelle\Manager; class AutoEnable extends \Gazelle\BaseManager { - // Outcomes - const PENDING = 0; - const APPROVED = 1; - const DENIED = 2; - const DISCARDED = 3; + final const PENDING = 0; + final const APPROVED = 1; + final const DENIED = 2; + final const DISCARDED = 3; // search for the admin toolbox protected array $where = []; @@ -17,7 +16,7 @@ class AutoEnable extends \Gazelle\BaseManager { protected array $args = []; // Cache key to store the number of enable requests - const CACHE_TOTAL_OPEN = 'num_enable_requests'; + final const CACHE_TOTAL_OPEN = 'num_enable_requests'; public function findById(int $enableId): ?\Gazelle\User\AutoEnable { [$id, $userId] = self::$db->row(" diff --git a/app/Manager/Blog.php b/app/Manager/Blog.php index 6e1c78ffa..533d6d2f4 100644 --- a/app/Manager/Blog.php +++ b/app/Manager/Blog.php @@ -3,8 +3,8 @@ namespace Gazelle\Manager; class Blog extends \Gazelle\BaseManager { - const CACHE_KEY = 'blog'; - const ID_KEY = 'zz_blog_%d'; + final const CACHE_KEY = 'blog'; + final const ID_KEY = 'zz_blog_%d'; public function flush(): Blog { self::$cache->delete_multi(['feed_blog', self::CACHE_KEY]); diff --git a/app/Manager/Bonus.php b/app/Manager/Bonus.php index b4eefeea8..dff629069 100644 --- a/app/Manager/Bonus.php +++ b/app/Manager/Bonus.php @@ -3,8 +3,8 @@ namespace Gazelle\Manager; class Bonus extends \Gazelle\Base { - const CACHE_ITEM = 'bonus_item'; - const CACHE_OPEN_POOL = 'bonus_pool'; // also defined in \Gazelle\Bonus + final const CACHE_ITEM = 'bonus_item'; + final const CACHE_OPEN_POOL = 'bonus_pool'; // also defined in \Gazelle\Bonus protected array $items; diff --git a/app/Manager/Category.php b/app/Manager/Category.php index 3d17a56f6..6c6768648 100644 --- a/app/Manager/Category.php +++ b/app/Manager/Category.php @@ -3,8 +3,8 @@ namespace Gazelle\Manager; class Category extends \Gazelle\Base { - const NAME_KEY = 'cat_name'; - const REPORT_KEY = 'cat_report'; + final const NAME_KEY = 'cat_name'; + final const REPORT_KEY = 'cat_report'; protected array $info = []; diff --git a/app/Manager/ClientWhitelist.php b/app/Manager/ClientWhitelist.php index 05f93ca80..52a30947b 100644 --- a/app/Manager/ClientWhitelist.php +++ b/app/Manager/ClientWhitelist.php @@ -3,7 +3,7 @@ namespace Gazelle\Manager; class ClientWhitelist extends \Gazelle\Base { - const CACHE_KEY = 'whitelisted_clients'; + final const CACHE_KEY = 'whitelisted_clients'; /** * Get the peer ID of client diff --git a/app/Manager/Comment.php b/app/Manager/Comment.php index af3c85cd5..49a844890 100644 --- a/app/Manager/Comment.php +++ b/app/Manager/Comment.php @@ -3,21 +3,16 @@ namespace Gazelle\Manager; class Comment extends \Gazelle\BaseManager { - const CATALOG = '%s_comments_%d_cat_%d'; + final const CATALOG = '%s_comments_%d_cat_%d'; protected function className(string $page): string { - switch ($page) { - case 'artist': - return '\\Gazelle\\Comment\\Artist'; - case 'collages': - return '\\Gazelle\\Comment\\Collage'; - case 'requests': - return '\\Gazelle\\Comment\\Request'; - case 'torrents': - return '\\Gazelle\\Comment\\Torrent'; - default: - throw new \Gazelle\Exception\InvalidCommentPageException($page); - } + return match ($page) { + 'artist' => \Gazelle\Comment\Artist::class, + 'collages' => \Gazelle\Comment\Collage::class, + 'requests' => \Gazelle\Comment\Request::class, + 'torrents' => \Gazelle\Comment\Torrent::class, + default => error("no comments for " . display_str($page)), + }; } public function findById(int $postId): ?\Gazelle\Comment\AbstractComment { @@ -103,8 +98,6 @@ class Comment extends \Gazelle\BaseManager { /** * Remove all comments on $page/$pageId (handle quote notifications and subscriptions as well) - * @param string $page - * @param int $pageId * @return boolean removal successful (or there was nothing to remove) */ public function remove(string $page, int $pageId) { diff --git a/app/Manager/Donation.php b/app/Manager/Donation.php index 3314f80be..12a16f822 100644 --- a/app/Manager/Donation.php +++ b/app/Manager/Donation.php @@ -5,34 +5,34 @@ namespace Gazelle\Manager; class Donation extends \Gazelle\Base { public function moderatorAdjust(\Gazelle\User $user, int $Rank, int $TotalRank, string $Reason, int $who) { $this->donate($user, [ - "Source" => "Modify Values", - "Rank" => (int)$Rank, - "TotalRank" => (int)$TotalRank, - "SendPM" => false, - "Reason" => $Reason, - "Who" => $who, + "Source" => "Modify Values", + "Rank" => $Rank, + "TotalRank" => $TotalRank, + "SendPM" => false, + "Reason" => $Reason, + "Who" => $who, ]); } public function moderatorDonate(\Gazelle\User $user, string $amount, string $Currency, string $Reason, int $who) { $this->donate($user, [ - "Source" => 'Add Points', - "Amount" => $amount, + "Source" => 'Add Points', + "Amount" => $amount, "Currency" => $Currency, - "SendPM" => true, - "Reason" => $Reason, - "Who" => $who, + "SendPM" => true, + "Reason" => $Reason, + "Who" => $who, ]); } public function regularDonate(\Gazelle\User $user, string $DonationAmount, string $Source, string $Reason, $Currency = "EUR") { $this->donate($user, [ - "Source" => $Source, - "Amount" => $DonationAmount, + "Source" => $Source, + "Amount" => $DonationAmount, "Currency" => $Currency, - "SendPM" => true, - "Reason" => $Reason, - "Who" => $user->id(), + "SendPM" => true, + "Reason" => $Reason, + "Who" => $user->id(), ]); } diff --git a/app/Manager/Forum.php b/app/Manager/Forum.php index b54ddcf97..d995c1005 100644 --- a/app/Manager/Forum.php +++ b/app/Manager/Forum.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Forum extends \Gazelle\BaseManager { - protected const CACHE_TOC_MAIN = 'forum_toc_main'; protected const CACHE_LIST = 'forum_list'; protected const CACHE_TRANSITION = 'forum_transition'; @@ -82,7 +81,6 @@ class Forum extends \Gazelle\BaseManager { /** * The forum table of contents (the main /forums.php view) * - * @return array * - string category name "Community" * containing an array of (one per forum): * - int 'ID' Forum id @@ -155,7 +153,7 @@ class Forum extends \Gazelle\BaseManager { } else { $lastReadPage = null; $lastReadPost = null; - $catchup = $f['LastPostTime'] ? $user->forumCatchupEpoch() >= strtotime($f['LastPostTime']) : false; + $catchup = $f['LastPostTime'] && $user->forumCatchupEpoch() >= strtotime($f['LastPostTime']); $isRead = false; } @@ -169,7 +167,7 @@ class Forum extends \Gazelle\BaseManager { 'category_id' => $f['categoryId'], 'cut_title' => shortenString($f['Title'] ?? '', 50, true), 'description' => $f['ID'] == DONOR_FORUM - ? DONOR_FORUM_DESCRIPTION[rand(0, count(DONOR_FORUM_DESCRIPTION) - 1)] + ? DONOR_FORUM_DESCRIPTION[random_int(0, count(DONOR_FORUM_DESCRIPTION) - 1)] : $f['Description'], 'forum' => $forum, 'forum_id' => $f['ID'], @@ -241,6 +239,7 @@ class Forum extends \Gazelle\BaseManager { } public function forumTransitionList(\Gazelle\User $user) { + $info = []; $items = self::$cache->get_value(self::CACHE_TRANSITION); if (!$items) { $queryId = self::$db->get_query_id(); @@ -267,8 +266,8 @@ class Forum extends \Gazelle\BaseManager { $info['EffectiveClass'] = $user->effectiveClass(); $info['ExtraClasses'] = array_keys((new \Gazelle\User\Privilege($user))->secondaryClassList()); $info['Permissions'] = array_keys($user->info()['Permission']); - $info['ExtraClassesOff'] = array_flip(array_map(fn($i) => -$i, $info['ExtraClasses'])); - $info['PermissionsOff'] = array_flip(array_map(fn($i) => "-$i", array_keys($user->info()['Permission']))); + $info['ExtraClassesOff'] = array_flip(array_map(fn ($i) => -$i, $info['ExtraClasses'])); + $info['PermissionsOff'] = array_flip(array_map(fn ($i) => "-$i", array_keys($user->info()['Permission']))); return array_filter($items, function ($item) use ($info, $userId) { if (count(array_intersect_key($item['permission_levels'], $info['ExtraClassesOff'])) > 0) { @@ -305,7 +304,7 @@ class Forum extends \Gazelle\BaseManager { public function threadTransitionList(\Gazelle\User $user, int $forumId): array { return array_filter($this->forumTransitionList($user), - function ($t) use ($forumId) {return $t['source'] === $forumId;} + fn ($t) => $t['source'] === $forumId ); } diff --git a/app/Manager/ForumCategory.php b/app/Manager/ForumCategory.php index e0e451023..ab3dc69de 100644 --- a/app/Manager/ForumCategory.php +++ b/app/Manager/ForumCategory.php @@ -3,7 +3,7 @@ namespace Gazelle\Manager; class ForumCategory extends \Gazelle\BaseManager { - const LIST_KEY = 'forum_cat'; + final const LIST_KEY = 'forum_cat'; protected const ID_KEY = 'zz_fc_%d'; public function findById(int $fcatId): ?\Gazelle\ForumCategory { diff --git a/app/Manager/ForumThread.php b/app/Manager/ForumThread.php index 9f0b6838f..c1d4250de 100644 --- a/app/Manager/ForumThread.php +++ b/app/Manager/ForumThread.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class ForumThread extends \Gazelle\BaseManager { - protected const ID_KEY = 'zz_ft_%d'; /** @@ -48,7 +47,7 @@ class ForumThread extends \Gazelle\BaseManager { ", $forum->id(), $title, $userId, $userId ); $thread = $this->findById(self::$db->inserted_id()); - $postId = $thread->addPost($userId, $body); + $thread->addPost($userId, $body); $db->relaxConstraints(false); (new \Gazelle\Stats\User($userId))->increment('forum_thread_total'); $forum->flush(); diff --git a/app/Manager/IPv4.php b/app/Manager/IPv4.php index 78cb5bc76..1da7c8f92 100644 --- a/app/Manager/IPv4.php +++ b/app/Manager/IPv4.php @@ -3,8 +3,7 @@ namespace Gazelle\Manager; class IPv4 extends \Gazelle\Base { - - const CACHE_KEY = 'ipv4_bans_'; + final const CACHE_KEY = 'ipv4_bans_'; protected string $filterNotes; protected string $filterIpaddr; diff --git a/app/Manager/News.php b/app/Manager/News.php index 46bb7045e..19cf72654 100644 --- a/app/Manager/News.php +++ b/app/Manager/News.php @@ -3,7 +3,7 @@ namespace Gazelle\Manager; class News extends \Gazelle\Base { - const CACHE_KEY = 'news'; + final const CACHE_KEY = 'news'; /** * Create a news article @@ -108,7 +108,6 @@ class News extends \Gazelle\Base { */ public function latestId(): int { return $this->latest()['id']; - return $newsId; } /** diff --git a/app/Manager/Notification.php b/app/Manager/Notification.php index d4be514aa..380496438 100644 --- a/app/Manager/Notification.php +++ b/app/Manager/Notification.php @@ -4,16 +4,16 @@ namespace Gazelle\Manager; class Notification extends \Gazelle\Base { // Option types - const OPT_PUSH = 3; - const OPT_POPUP_PUSH = 4; - const OPT_TRADITIONAL_PUSH = 5; + final const OPT_PUSH = 3; + final const OPT_POPUP_PUSH = 4; + final const OPT_TRADITIONAL_PUSH = 5; // Types. These names must correspond to column names in users_notifications_settings - const NEWS = 'News'; - const BLOG = 'Blog'; - const INBOX = 'Inbox'; - const QUOTES = 'Quotes'; - const GLOBALNOTICE = 'Global'; + final const NEWS = 'News'; + final const BLOG = 'Blog'; + final const INBOX = 'Inbox'; + final const QUOTES = 'Quotes'; + final const GLOBALNOTICE = 'Global'; /** * Send a push notification to a user diff --git a/app/Manager/Payment.php b/app/Manager/Payment.php index 97235cc96..7cbbc9e22 100644 --- a/app/Manager/Payment.php +++ b/app/Manager/Payment.php @@ -5,9 +5,9 @@ namespace Gazelle\Manager; use \Gazelle\Exception\PaymentFetchForexException; class Payment extends \Gazelle\Base { - const LIST_KEY = 'payment_list'; - const RENT_KEY = 'payment_monthly_rental'; - const DUE_KEY = 'payment_due'; + final const LIST_KEY = 'payment_list'; + final const RENT_KEY = 'payment_monthly_rental'; + final const DUE_KEY = 'payment_due'; public function flush(): Payment { self::$cache->delete_multi([self::LIST_KEY, self::DUE_KEY, self::RENT_KEY]); diff --git a/app/Manager/Privilege.php b/app/Manager/Privilege.php index 7a7b39ad5..58a2ee57f 100644 --- a/app/Manager/Privilege.php +++ b/app/Manager/Privilege.php @@ -132,7 +132,6 @@ class Privilege extends \Gazelle\BaseManager { * The list of defined privileges. The `can` field * in the returned array acts as a sparse matrix. * - * @return array * - name (Short name of privilege) * - description (Longer description of privilege) * - orphan (Is this a privileges that no longer exists) diff --git a/app/Manager/Recovery.php b/app/Manager/Recovery.php index 6e31919fb..f209a4158 100644 --- a/app/Manager/Recovery.php +++ b/app/Manager/Recovery.php @@ -5,7 +5,6 @@ namespace Gazelle\Manager; use Gazelle\Util\Mail; class Recovery extends \Gazelle\Base { - public function findById(int $id): array { self::$db->prepared_query($this->candidateSql() . " WHERE m.ID = ? GROUP BY m.ID @@ -44,7 +43,7 @@ class Recovery extends \Gazelle\Base { if (count($parts) != 2) { return null; } - list($lhs, $rhs) = $parts; + [$lhs, $rhs] = $parts; if ($rhs == 'gmail.com') { $lhs = str_replace('.', '', $lhs); } @@ -98,7 +97,7 @@ class Recovery extends \Gazelle\Base { if ($file['size'] > 10 * 1024 * 1024) { return [false, "File was too large, please make sure it is less than 10MB in size."]; } - $filename = sha1(RECOVERY_SALT . mt_rand(0, 10000000). sha1_file($file['tmp_name'])); + $filename = sha1(RECOVERY_SALT . random_int(0, 10_000_000). sha1_file($file['tmp_name'])); $destination = sprintf('%s/%s/%s/%s/%s', RECOVERY_PATH, substr($filename, 0, 1), substr($filename, 1, 1), substr($filename, 2, 1), $filename ); @@ -134,48 +133,36 @@ class Recovery extends \Gazelle\Base { return self::$db->affected_rows(); } - public function total(string $state, int $admin_id): int { - switch (strtoupper($state)) { - case 'CLAIMED': - return self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ? and admin_user_id = ?", $state, $admin_id); - break; - case 'PENDING': - return self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ? and (admin_user_id is null or admin_user_id != ?)", $state, $admin_id); - break; - default: - return self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ?", strtoupper($state)); - break; - } - return 0; + public function total(string $state, int $admin_id): int + { + return match (strtoupper($state)) { + 'CLAIMED' => self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ? and admin_user_id = ?", $state, $admin_id), + 'PENDING' => self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ? and (admin_user_id is null or admin_user_id != ?)", $state, $admin_id), + default => self::$db->scalar("SELECT count(*) FROM recovery WHERE state = ?", strtoupper($state)), + }; } public function page(int $limit, int $offset, string $state, int $admin_id): array { $sql_header = 'SELECT recovery_id, username, token, email, announce, created_dt, updated_dt, state FROM recovery'; $sql_footer = 'ORDER BY updated_dt DESC LIMIT ? OFFSET ?'; - switch (strtoupper($state)) { - case 'CLAIMED': - self::$db->prepared_query("$sql_header + match (strtoupper($state)) { + 'CLAIMED' => self::$db->prepared_query("$sql_header WHERE admin_user_id = ? $sql_footer ", $admin_id, $limit, $offset - ); - break; - case 'PENDING': - self::$db->prepared_query("$sql_header + ), + 'PENDING' => self::$db->prepared_query("$sql_header WHERE admin_user_id IS NULL AND state = ? $sql_footer ", $state, $limit, $offset - ); - break; - default: - self::$db->prepared_query("$sql_header + ), + default => self::$db->prepared_query("$sql_header WHERE state = ? $sql_footer ", $state, $limit, $offset - ); - break; - } + ), + }; return self::$db->to_array(); } @@ -481,16 +468,16 @@ class Recovery extends \Gazelle\Base { self::$db->prepared_query($sql, RECOVERY_BUFFER_REASSIGN_LIMIT); $rescale = [ - 'member' => 10.0 * pow(1024, 3), - 'poweruser' => 25.0 * pow(1024, 3), - 'elite' => 100.0 * pow(1024, 3), - 'torrentmaster' => 500.0 * pow(1024, 3), - 'powertm' => 500.0 * pow(1024, 3), - 'elitetm' => 500.0 * pow(1024, 3) + 'member' => 10.0 * 1024 ** 3, + 'poweruser' => 25.0 * 1024 ** 3, + 'elite' => 100.0 * 1024 ** 3, + 'torrentmaster' => 500.0 * 1024 ** 3, + 'powertm' => 500.0 * 1024 ** 3, + 'elitetm' => 500.0 * 1024 ** 3 ]; $results = self::$db->to_array(); - foreach ($results as list($username, $siteUserId, $prevUserId, $uploaded, $downloaded, $bounty, $nr_torrents, $irc_userclass, $final)) { + foreach ($results as [$username, $siteUserId, $prevUserId, $uploaded, $downloaded, $bounty, $nr_torrents, $irc_userclass, $final]) { /* close the gate */ self::$db->prepared_query(sprintf(" UPDATE %s.user_recovery_mapping diff --git a/app/Manager/Referral.php b/app/Manager/Referral.php index 3033ca34a..2f0f2f7c2 100644 --- a/app/Manager/Referral.php +++ b/app/Manager/Referral.php @@ -8,16 +8,16 @@ use Gazelle\Util\Proxy; class Referral extends \Gazelle\Base { private $accounts; - private $proxy; + private readonly \Gazelle\Util\Proxy $proxy; public $readOnly; - const CACHE_ACCOUNTS = 'referral_accounts'; - const CACHE_BOUNCER = 'bouncer_status'; + final const CACHE_ACCOUNTS = 'referral_accounts'; + final const CACHE_BOUNCER = 'bouncer_status'; // Do not change the ordering in this array after launch. - const ACCOUNT_TYPES = ['Gazelle (API)', 'Gazelle Games', 'Tentacles', 'Luminance', 'Gazelle (HTML)', 'PTP']; + final const ACCOUNT_TYPES = ['Gazelle (API)', 'Gazelle Games', 'Tentacles', 'Luminance', 'Gazelle (HTML)', 'PTP']; // Accounts which use the user ID instead of username. - const ID_TYPES = [3, 4, 5]; + final const ID_TYPES = [3, 4, 5]; public function __construct() { $this->accounts = self::$cache->get_value(self::CACHE_ACCOUNTS); @@ -77,7 +77,7 @@ class Referral extends \Gazelle\Base { public function getActiveAccounts() { return array_filter($this->accounts, - function ($i) { return $i['Active'] == '1' && !$this->readOnly; }); + fn($i) => $i['Active'] == '1' && !$this->readOnly); } public function getAccount($id) { @@ -278,24 +278,15 @@ class Referral extends \Gazelle\Base { ); } - public function validateCookie($acc) { - switch ($acc["Type"]) { - case 0: - return $this->validateGazelleCookie($acc); - break; - case 1: - return true; - break; - case 2: - return $this->validateTentacleCookie($acc); - break; - case 3: - case 4: - case 5: - return $this->validateLuminanceCookie($acc); - break; - } - return false; + public function validateCookie($acc) + { + return match ($acc["Type"]) { + 0 => $this->validateGazelleCookie($acc), + 1 => true, + 2 => $this->validateTentacleCookie($acc), + 3, 4, 5 => $this->validateLuminanceCookie($acc), + default => false, + }; } private function validateGazelleCookie($acc) { @@ -317,28 +308,17 @@ class Referral extends \Gazelle\Base { return str_contains($result["response"], "authkey"); } - public function loginAccount(&$acc) { - switch ($acc["Type"]) { - case 0: - return $this->loginGazelleAccount($acc); - break; - case 1: - return true; - break; - case 2: - return $this->loginTentacleAccount($acc); - break; - case 3: - return $this->loginLuminanceAccount($acc); - break; - case 4: - return $this->loginGazelleHTMLAccount($acc); - break; - case 5: - return $this->loginPTPAccount($acc); - break; - } - return false; + public function loginAccount(&$acc) + { + return match ($acc["Type"]) { + 0 => $this->loginGazelleAccount($acc), + 1 => true, + 2 => $this->loginTentacleAccount($acc), + 3 => $this->loginLuminanceAccount($acc), + 4 => $this->loginGazelleHTMLAccount($acc), + 5 => $this->loginPTPAccount($acc), + default => false, + }; } private function loginGazelleAccount(&$acc) { @@ -440,28 +420,17 @@ class Referral extends \Gazelle\Base { return $result["status"] == 200; } - public function verifyAccount($acc, $user, $key) { - switch ($acc["Type"]) { - case 0: - return $this->verifyGazelleAccount($acc, $user, $key); - break; - case 1: - return $this->verifyGGNAccount($acc, $user, $key); - break; - case 2: - return $this->verifyTentacleAccount($acc, $user, $key); - break; - case 3: - return $this->verifyLuminanceAccount($acc, $user, $key); - break; - case 4: - return $this->verifyGazelleHTMLAccount($acc, $user, $key); - break; - case 5: - return $this->verifyPTPAccount($acc, $user, $key); - break; - } - return "Unrecognised account type"; + public function verifyAccount($acc, $user, $key) + { + return match ($acc["Type"]) { + 0 => $this->verifyGazelleAccount($acc, $user, $key), + 1 => $this->verifyGGNAccount($acc, $user, $key), + 2 => $this->verifyTentacleAccount($acc, $user, $key), + 3 => $this->verifyLuminanceAccount($acc, $user, $key), + 4 => $this->verifyGazelleHTMLAccount($acc, $user, $key), + 5 => $this->verifyPTPAccount($acc, $user, $key), + default => "Unrecognised account type", + }; } private function verifyGazelleAccount($acc, $user, $key) { diff --git a/app/Manager/SiteLog.php b/app/Manager/SiteLog.php index cbf31fc94..13ab1dcea 100644 --- a/app/Manager/SiteLog.php +++ b/app/Manager/SiteLog.php @@ -131,7 +131,6 @@ class SiteLog extends \Gazelle\Base { break; case 'by': $userId = 0; - $user = ''; $URL = ''; if ($messageParts[$i + 1] == 'user') { $i++; @@ -141,7 +140,7 @@ class SiteLog extends \Gazelle\Base { $URL = "user $userId (".substr($messageParts[++$i], 1, -1).')'; } elseif (in_array($messageParts[$i - 1], ['deleted', 'uploaded', 'edited', 'created', 'recovered'])) { $username = $messageParts[++$i]; - if (substr($username, -1) == ':') { + if (str_ends_with($username, ':')) { $username = substr($username, 0, -1); $colon = true; } diff --git a/app/Manager/SiteOption.php b/app/Manager/SiteOption.php index d95c0a264..5185eea33 100644 --- a/app/Manager/SiteOption.php +++ b/app/Manager/SiteOption.php @@ -3,8 +3,7 @@ namespace Gazelle\Manager; class SiteOption extends \Gazelle\Base { - - const CACHE_KEY = 'site_option_%s'; + final const CACHE_KEY = 'site_option_%s'; public function findValueByName(string $name): string { $key = sprintf(self::CACHE_KEY, $name); @@ -48,7 +47,7 @@ class SiteOption extends \Gazelle\Base { VALUES (?, ?, ?) ', $name, $value, $comment ); - } catch (\Gazelle\DB\Mysql_DuplicateKeyException $e) { + } catch (\Gazelle\DB\Mysql_DuplicateKeyException) { return null; } self::$cache->cache_value(sprintf(self::CACHE_KEY, $name), $value); diff --git a/app/Manager/StaffBlog.php b/app/Manager/StaffBlog.php index 78cde8946..20115d9af 100644 --- a/app/Manager/StaffBlog.php +++ b/app/Manager/StaffBlog.php @@ -79,7 +79,7 @@ class StaffBlog extends \Gazelle\Base { ORDER BY Time DESC "); $list = self::$db->to_array(false, MYSQLI_ASSOC, false); - self::$cache->cache_value(self::CACHE_KEY, $list, 1209600); + self::$cache->cache_value(self::CACHE_KEY, $list, 1_209_600); } return $list; } diff --git a/app/Manager/Subscription.php b/app/Manager/Subscription.php index b14c98d9e..8c7e12ade 100644 --- a/app/Manager/Subscription.php +++ b/app/Manager/Subscription.php @@ -35,7 +35,7 @@ class Subscription extends \Gazelle\Base { ); $list = self::$db->collect('UserID', false); - $userMan = new User; + new User; foreach ($list as $userId) { (new \Gazelle\User\Quote(new \Gazelle\User($userId)))->flush(); } diff --git a/app/Manager/TGroup.php b/app/Manager/TGroup.php index 7b0fff202..a64ee96b6 100644 --- a/app/Manager/TGroup.php +++ b/app/Manager/TGroup.php @@ -7,8 +7,8 @@ class TGroup extends \Gazelle\BaseManager { protected const CACHE_KEY_FEATURED = 'featured_%d'; protected const VOTE_SIMILAR = 'vote_similar_albums_%d'; - const FEATURED_AOTM = 0; - const FEATURED_SHOWCASE = 1; + final const FEATURED_AOTM = 0; + final const FEATURED_SHOWCASE = 1; protected \Gazelle\User $viewer; @@ -86,7 +86,7 @@ class TGroup extends \Gazelle\BaseManager { public function create( int $categoryId, - int $releaseType, + ?int $releaseType, string $name, string $description, int $year, @@ -98,7 +98,7 @@ class TGroup extends \Gazelle\BaseManager { self::$db->prepared_query(" INSERT INTO torrents_group (CategoryID, Name, WikiBody, Year, RecordLabel, CatalogueNumber, WikiImage, ReleaseType, VanityHouse) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ", $categoryId, $name, $description, $year, $recordLabel, $catalogueNumber, $image, $releaseType, (int)$showcase ); $id = self::$db->inserted_id(); diff --git a/app/Manager/Tag.php b/app/Manager/Tag.php index 4599b2ff3..304039073 100644 --- a/app/Manager/Tag.php +++ b/app/Manager/Tag.php @@ -3,7 +3,6 @@ namespace Gazelle\Manager; class Tag extends \Gazelle\BaseManager { - protected const ID_KEY = 'zz_tag_%d'; public function findById(int $tagId): ?\Gazelle\Tag { @@ -89,7 +88,6 @@ class Tag extends \Gazelle\BaseManager { /** * Create a tag. If the tag already exists its usage is incremented. * - * @param string $name * @param int $userId The id of the user creating the tag. */ public function create(string $name, int $userId): int { @@ -120,7 +118,6 @@ class Tag extends \Gazelle\BaseManager { /** * Make a tag official * - * @param string $name * @param int $userId Who is doing the officializing/ * @return int $tagId id of the officialized tag. */ diff --git a/app/Manager/Torrent.php b/app/Manager/Torrent.php index d86f9794e..ffc3dfcac 100644 --- a/app/Manager/Torrent.php +++ b/app/Manager/Torrent.php @@ -5,17 +5,17 @@ namespace Gazelle\Manager; class Torrent extends \Gazelle\BaseManager { protected const ID_KEY = 'zz_t_%d'; - const CACHE_KEY_LATEST_UPLOADS = 'latest_uploads_%d'; - const CACHE_KEY_PEERLIST_TOTAL = 'peerlist_total_%d'; - const CACHE_KEY_PEERLIST_PAGE = 'peerlist_page_%d_%d'; - const CACHE_FOLDERNAME = 'foldername_%s'; - const FOLDER_SALT = "v1\x01"; + final const CACHE_KEY_LATEST_UPLOADS = 'latest_uploads_%d'; + final const CACHE_KEY_PEERLIST_TOTAL = 'peerlist_total_%d'; + final const CACHE_KEY_PEERLIST_PAGE = 'peerlist_page_%d_%d'; + final const CACHE_FOLDERNAME = 'foldername_%s'; + final const FOLDER_SALT = "v1\x01"; - const SNATCHED_UPDATE_INTERVAL = 3600; // How often we want to update users' snatch lists - const SNATCHED_UPDATE_AFTERDL = 300; // How long after a torrent download we want to update a user's snatch lists + final const SNATCHED_UPDATE_INTERVAL = 3600; // How often we want to update users' snatch lists + final const SNATCHED_UPDATE_AFTERDL = 300; // How long after a torrent download we want to update a user's snatch lists - const ARTIST_DISPLAY_TEXT = 1; - const ARTIST_DISPLAY_HTML = 2; + final const ARTIST_DISPLAY_TEXT = 1; + final const ARTIST_DISPLAY_HTML = 2; protected \Gazelle\User $viewer; @@ -412,7 +412,7 @@ class Torrent extends \Gazelle\BaseManager { $groupLog = new \Gazelle\Log; $tracker = new \Gazelle\Tracker; - foreach ($Torrents as list($TorrentID, $GroupID, $InfoHash)) { + foreach ($Torrents as [$TorrentID, $GroupID, $InfoHash]) { $tracker->update_tracker('update_torrent', ['info_hash' => rawurlencode($InfoHash), 'freetorrent' => $leechLevel]); self::$cache->delete_value("torrent_download_$TorrentID"); $groupLog->torrent($GroupID, $TorrentID, $user->id(), "marked as freeleech type $reason") @@ -423,7 +423,6 @@ class Torrent extends \Gazelle\BaseManager { } public function updatePeerlists(): array { - self::$cache->disableLocalCache(); self::$db->prepared_query(" DELETE FROM xbt_files_users WHERE mtime < unix_timestamp(NOW() - INTERVAL ? SECOND) diff --git a/app/Manager/Torrent/ReportType.php b/app/Manager/Torrent/ReportType.php index d89d0a21a..5a189c58a 100644 --- a/app/Manager/Torrent/ReportType.php +++ b/app/Manager/Torrent/ReportType.php @@ -3,9 +3,9 @@ namespace Gazelle\Manager\Torrent; class ReportType extends \Gazelle\Base { - const ID_KEY = 'zz_trt_%d'; - const NAME_KEY = 'zz_trtn_%s'; - const TYPE_KEY = 'zz_trtt_%s'; + final const ID_KEY = 'zz_trt_%d'; + final const NAME_KEY = 'zz_trtn_%s'; + final const TYPE_KEY = 'zz_trtt_%s'; public function findById(int $reportTypeId): ?\Gazelle\Torrent\ReportType { $key = sprintf(self::ID_KEY, $reportTypeId); diff --git a/app/Manager/User.php b/app/Manager/User.php index b6d811e2e..45afefa6f 100644 --- a/app/Manager/User.php +++ b/app/Manager/User.php @@ -9,16 +9,16 @@ class User extends \Gazelle\BaseManager { protected const ID_KEY = 'zz_u_%d'; protected const USERNAME_KEY = 'zz_unam_%s'; - public const DISABLE_MANUAL = 1; - public const DISABLE_TOR = 2; - public const DISABLE_INACTIVITY = 3; - public const DISABLE_TREEBAN = 4; + final public const DISABLE_MANUAL = 1; + final public const DISABLE_TOR = 2; + final public const DISABLE_INACTIVITY = 3; + final public const DISABLE_TREEBAN = 4; /** * Get a User object based on a magic field (id or @name) */ public function find($name): ?\Gazelle\User { - if (substr($name, 0, 1) === '@') { + if (str_starts_with($name, '@')) { return $this->findByUsername(substr($name, 1)); } elseif ((int)$name > 0) { return $this->findById((int)$name); @@ -318,7 +318,7 @@ class User extends \Gazelle\BaseManager { } self::$cache->cache_value('idstaff', $staff, 3600); } - $userMan = new \Gazelle\Manager\User; + new \Gazelle\Manager\User; foreach ($staff as &$group) { $group = array_map(fn ($userId) => $this->findById($userId), $group); } @@ -1248,8 +1248,7 @@ class User extends \Gazelle\BaseManager { WHERE um.RequiredRatio != 0.00 AND uls.Downloaded < 5 * 1024 * 1024 * 1024 "); - $affected += self::$db->affected_rows(); - return $affected; + return $affected + self::$db->affected_rows(); } public function addMassTokens(int $amount, bool $allowLeechDisabled): int { @@ -1340,7 +1339,7 @@ class User extends \Gazelle\BaseManager { } public function triggerRatioWatch(\Gazelle\Tracker $tracker, \Gazelle\Schedule\Task $task = null): int { - $userQuery = self::$db->prepared_query(" + self::$db->prepared_query(" SELECT um.ID, um.torrent_pass FROM users_info AS ui INNER JOIN users_main AS um ON (um.ID = ui.UserID) diff --git a/app/Manager/XBT.php b/app/Manager/XBT.php index 9b5a53fc4..f23539a74 100644 --- a/app/Manager/XBT.php +++ b/app/Manager/XBT.php @@ -3,12 +3,12 @@ namespace Gazelle\Manager; class XBT extends \Gazelle\Base { - const CACHE_KEY = 'xbt_rate_%s'; + final const CACHE_KEY = 'xbt_rate_%s'; /* Coinbase quotes have a 1% fee, but we lose more in tumbling, so whatever. * Coinbase never realised that BTC collides with Bhutan, XBT is the ISO-4217 code. */ - const FX_QUOTE_URL = 'https://api.coinbase.com/v2/prices/BTC-%s/buy'; + final const FX_QUOTE_URL = 'https://api.coinbase.com/v2/prices/BTC-%s/buy'; /* Fetch the current XBT rate for a given currency code (ISO 4217) * diff --git a/app/Notification/Filter.php b/app/Notification/Filter.php index 623dba5e7..c2a5318dc 100644 --- a/app/Notification/Filter.php +++ b/app/Notification/Filter.php @@ -94,7 +94,6 @@ class Filter extends \Gazelle\Base { case 'media': $arg = '|' . implode('|', $this->field[$field]) . '|'; return $arg === '||' ? '' : $arg; - break; } return null; } diff --git a/app/Notification/Torrent.php b/app/Notification/Torrent.php index 8af61a17c..71ab97a88 100644 --- a/app/Notification/Torrent.php +++ b/app/Notification/Torrent.php @@ -18,6 +18,8 @@ class Torrent extends \Gazelle\Base { } public function setFilter(int $filterId) { + $cond = []; + $args = []; $cond[] = 'unf.ID = ?'; $args[] = $filterId; return $this; diff --git a/app/Notification/Upload.php b/app/Notification/Upload.php index 3f052afaf..76971ecf7 100644 --- a/app/Notification/Upload.php +++ b/app/Notification/Upload.php @@ -47,8 +47,8 @@ class Upload extends \Gazelle\Base { if (!empty($guestName)) { $this->cond[] = "unf.ExcludeVA = '0'"; } - $all = array_merge($mainName, $guestName); - $this->cond[] = "(" . implode(' OR ', array_merge(["unf.Artists = ''"], array_fill(0, count($all), "unf.Artists LIKE concat('%|', ?, '|%')"))) . ")"; + $all = [...$mainName, ...$guestName]; + $this->cond[] = "(" . implode(' OR ', [...["unf.Artists = ''"], ...array_fill(0, count($all), "unf.Artists LIKE concat('%|', ?, '|%')")]) . ")"; $this->args = array_merge($this->args, $all); } return $this; diff --git a/app/ReleaseType.php b/app/ReleaseType.php index 56b078012..5847129a6 100644 --- a/app/ReleaseType.php +++ b/app/ReleaseType.php @@ -49,20 +49,13 @@ class ReleaseType extends Base { public function sectionTitle(int $id): string { $title = $this->extendedList()[$id]; - switch ($title) { - case 'Anthology': - return 'Anthologies'; - case 'DJ Mix': - return 'DJ Mixes'; - case 'Remix': - return 'Remixes'; - case 'Compositions': - case 'Guest Appearances': - case 'Produced By': - case 'Remixed By': - return $title; - default: - return "{$title}s"; - } + return match ($title) { + 'Anthology' => 'Anthologies', + 'DJ Mix' => 'DJ Mixes', + 'Remix' => 'Remixes', + 'Compositions', 'Guest Appearances', 'Produced By', 'Remixed By' + => $title, + default => "{$title}s", + }; } } diff --git a/app/Request.php b/app/Request.php index 9dbb63559..55d1069f3 100644 --- a/app/Request.php +++ b/app/Request.php @@ -437,7 +437,7 @@ class Request extends BaseObject { ); $raw = self::$db->to_array(); $list = []; - foreach ($raw as list($artistId, $artistName, $role)) { + foreach ($raw as [$artistId, $artistName, $role]) { $list[$role][] = ['id' => $artistId, 'name' => $artistName]; } self::$cache->cache_value($key, $list, 0); diff --git a/app/Router.php b/app/Router.php index 9cb74e132..d319f448a 100644 --- a/app/Router.php +++ b/app/Router.php @@ -17,8 +17,8 @@ use Gazelle\Exception\RouterException; * GET request will not. */ class Router { - private $authorize = ['GET' => false, 'POST' => true]; - private $routes = ['GET' => [], 'POST' => []]; + private array $authorize = ['GET' => false, 'POST' => true]; + private array $routes = ['GET' => [], 'POST' => []]; /** * Router constructor. @@ -28,13 +28,7 @@ class Router { protected readonly string $auth_key = '' ) {} - /** - * @param string|array $methods - * @param string $action - * @param string $path - * @param bool $authorize - */ - public function addRoute($methods, string $action, string $path, bool $authorize = false) { + public function addRoute(string|array $methods, string $action, string $path, bool $authorize = false) { if (is_array($methods)) { foreach ($methods as $method) { $this->addRoute($method, $action, $path, $authorize); @@ -75,7 +69,6 @@ class Router { } /** - * @param string $action * @return string path to file to load * @throws RouterException */ diff --git a/app/Schedule/Scheduler.php b/app/Schedule/Scheduler.php index 8dbf27bf7..16046b36a 100644 --- a/app/Schedule/Scheduler.php +++ b/app/Schedule/Scheduler.php @@ -5,7 +5,7 @@ namespace Gazelle\Schedule; use \Gazelle\Util\Irc; class Scheduler extends \Gazelle\Base { - const CACHE_TASKS = 'scheduled_tasks'; + final const CACHE_TASKS = 'scheduled_tasks'; public function getTask(int $id) { $tasks = $this->getTasks(); @@ -28,9 +28,7 @@ class Scheduler extends \Gazelle\Base { public function getInsaneTasks() { return count(array_filter($this->getTasks(), - function($v) { - return !$v['is_sane']; - } + fn($v) => !$v['is_sane'] )); } @@ -198,9 +196,7 @@ class Scheduler extends \Gazelle\Base { $result[] = [ 'name' => $name, 'data' => array_map( - function ($v) use ($id, $key, $time) { - return [$time ? strtotime($v[$key]) * 1000 : $v[$key], (int)$v[$id]]; - }, + fn($v) => [$time ? strtotime($v[$key]) * 1000 : $v[$key], (int)$v[$id]], $data ) ]; @@ -306,7 +302,7 @@ class Scheduler extends \Gazelle\Base { $phinxScript = realpath(__DIR__ . '/../../phinx.php'); $pendingMigrations = array_filter(json_decode(shell_exec($phinxBinary . ' status -c ' . $phinxScript . ' --format=json | tail -n 1'), true)['migrations'], - function($value) { return count($value) > 0 && $value['migration_status'] === 'down'; }); + fn($value) => count($value) > 0 && $value['migration_status'] === 'down'); if (count($pendingMigrations)) { Irc::sendMessage(LAB_CHAN, 'Pending migrations found, scheduler cannot continue'); diff --git a/app/Schedule/Task.php b/app/Schedule/Task.php index d0314369b..cd85cd479 100644 --- a/app/Schedule/Task.php +++ b/app/Schedule/Task.php @@ -29,7 +29,7 @@ abstract class Task extends \Gazelle\Base { public function end(bool $sane): int { $elapsed = (microtime(true) - $this->startTime) * 1000; - $errorCount = count(array_filter($this->events, function ($event) { return $event->severity === 'error'; })); + $errorCount = count(array_filter($this->events, fn($event) => $event->severity === 'error')); self::$db->prepared_query(' UPDATE periodic_task_history SET status = ?, diff --git a/app/Schedule/Tasks/Freeleech.php b/app/Schedule/Tasks/Freeleech.php index 401ee3f69..714a277fe 100644 --- a/app/Schedule/Tasks/Freeleech.php +++ b/app/Schedule/Tasks/Freeleech.php @@ -24,7 +24,7 @@ class Freeleech extends \Gazelle\Schedule\Task AND Time < now() - INTERVAL 7 HOUR"); self::$db->set_query_id($qId); - while (list($groupID) = self::$db->next_record()) { + while ([$groupID] = self::$db->next_record()) { self::$cache->delete_value("torrents_details_$groupID"); self::$cache->delete_value("torrent_group_$groupID"); } diff --git a/app/Schedule/Tasks/NotifyNonseedingUploaders.php b/app/Schedule/Tasks/NotifyNonseedingUploaders.php index f633bc09e..742549b20 100644 --- a/app/Schedule/Tasks/NotifyNonseedingUploaders.php +++ b/app/Schedule/Tasks/NotifyNonseedingUploaders.php @@ -30,7 +30,7 @@ class NotifyNonseedingUploaders extends \Gazelle\Schedule\Task $inactivityExceptionsMade = []; foreach ($torrentIDs as $torrentID) { - list($id, $groupID, $name, $format, $encoding, $userID) = $torrentID; + [$id, $groupID, $name, $format, $encoding, $userID] = $torrentID; if (array_key_exists($userID, $inactivityExceptionsMade) && (time() < $inactivityExceptionsMade[$userID])) { // don't notify exceptions diff --git a/app/Schedule/Tasks/RemoveExpiredWarnings.php b/app/Schedule/Tasks/RemoveExpiredWarnings.php index a3552e9f8..151126627 100644 --- a/app/Schedule/Tasks/RemoveExpiredWarnings.php +++ b/app/Schedule/Tasks/RemoveExpiredWarnings.php @@ -19,7 +19,7 @@ class RemoveExpiredWarnings extends \Gazelle\Schedule\Task "); self::$db->set_query_id($queryId); - while (list($userID) = self::$db->next_record()) { + while ([$userID] = self::$db->next_record()) { self::$cache->delete_value("u_$userID"); $this->debug("Expiring warning for $userID", $userID); $this->processed++; diff --git a/app/Search/Email.php b/app/Search/Email.php index 90fc9de39..c99659c15 100644 --- a/app/Search/Email.php +++ b/app/Search/Email.php @@ -3,14 +3,14 @@ namespace Gazelle\Search; class Email extends \Gazelle\Base { - public const ASC = 0; - public const DESC = 1; + final public const ASC = 0; + final public const DESC = 1; - public const EMAIL = 0; - public const USER = 1; - public const JOINED = 2; - public const CHANGED = 3; - public const IP = 4; + final public const EMAIL = 0; + final public const USER = 1; + final public const JOINED = 2; + final public const CHANGED = 3; + final public const IP = 4; protected string $name; protected int $column = 0; diff --git a/app/Search/Forum.php b/app/Search/Forum.php index 50581b0ed..c5a9a6b9c 100644 --- a/app/Search/Forum.php +++ b/app/Search/Forum.php @@ -3,7 +3,6 @@ namespace Gazelle\Search; class Forum extends \Gazelle\BaseUser { - protected array $permittedForums = []; protected array $forbiddenForums = []; protected array $selectedForums = []; @@ -219,7 +218,7 @@ class Forum extends \Gazelle\BaseUser { protected function configure(): array { $cond = array_merge($this->forumCond, $this->threadCond, $this->isBodySearch() ? $this->postCond : []); $args = array_merge($this->forumArgs, $this->threadArgs, $this->isBodySearch() ? $this->postArgs : []); - $userContext = isset($this->viewer) ? $this->viewer : $this->user; + $userContext = $this->viewer ?? $this->user; if (!($this->permittedForums || $this->selectedForums)) { // any forum they have access to due to their class $cond[] = 'f.MinClassRead <= ?'; diff --git a/app/Search/IPv4.php b/app/Search/IPv4.php index f1ed2afae..071b1ab0b 100644 --- a/app/Search/IPv4.php +++ b/app/Search/IPv4.php @@ -3,13 +3,13 @@ namespace Gazelle\Search; class IPv4 extends \Gazelle\Base { - public const ASC = 0; - public const DESC = 1; + final public const ASC = 0; + final public const DESC = 1; - public const START = 0; - public const END = 1; - public const IP = 2; - public const TOTAL = 3; + final public const START = 0; + final public const END = 1; + final public const IP = 2; + final public const TOTAL = 3; /** * Take a freeform slab of text and search for dotted quads. diff --git a/app/Search/Request.php b/app/Search/Request.php index baff7c53a..913efda59 100644 --- a/app/Search/Request.php +++ b/app/Search/Request.php @@ -106,6 +106,7 @@ class Request extends \Gazelle\Base { } public function setMedia(array $mediaList, bool $strict): Request { + $format = []; if (in_array(count($mediaList), [0, count(MEDIA)])) { return $this; } @@ -198,7 +199,7 @@ class Request extends \Gazelle\Base { $queryTerm = $include; if (isset($this->negate) && $exclude) { - $queryTerm = array_merge($queryTerm, $exclude); + $queryTerm = [...$queryTerm, ...$exclude]; } if ($queryTerm) { $this->sphinxq->where_match(implode(' ', $queryTerm), '*', false); @@ -288,11 +289,11 @@ class Request extends \Gazelle\Base { } public function list(): array { - return isset($this->list) ? $this->list : []; + return $this->list ?? []; } public function total(): int { - return isset($this->total) ? $this->total : 0; + return $this->total ?? 0; } public function encodingList(): array { @@ -308,18 +309,18 @@ class Request extends \Gazelle\Base { } public function releaseTypeList(): array { - return isset($this->releaseTypeList) ? $this->releaseTypeList : []; + return $this->releaseTypeList ?? []; } public function tagList(): string { - return isset($this->tagList) ? $this->tagList : ''; + return $this->tagList ?? ''; } public function text(): string { - return isset($this->text) ? $this->text : 'Requests'; + return $this->text ?? 'Requests'; } public function title(): string { - return isset($this->title) ? $this->title : 'Requests'; + return $this->title ?? 'Requests'; } } diff --git a/app/Search/Torrent.php b/app/Search/Torrent.php index ef99c2fc7..38ba36d22 100644 --- a/app/Search/Torrent.php +++ b/app/Search/Torrent.php @@ -3,10 +3,10 @@ namespace Gazelle\Search; class Torrent { - const TAGS_ANY = 0; - const TAGS_ALL = 1; - const SPH_BOOL_AND = ' '; - const SPH_BOOL_OR = ' | '; + final const TAGS_ANY = 0; + final const TAGS_ALL = 1; + final const SPH_BOOL_AND = ' '; + final const SPH_BOOL_OR = ' | '; /** * Map of sort mode => attribute name for ungrouped torrent page @@ -23,7 +23,7 @@ class Torrent { /** * Map of sort mode => attribute name for grouped torrent page */ - private static $SortOrdersGrouped = [ + private static array $SortOrdersGrouped = [ 'year' => 'year', 'time' => 'id', 'size' => 'maxsize', @@ -35,7 +35,7 @@ class Torrent { /** * Map of sort mode => aggregate expression required for some grouped sort orders */ - private static $AggregateExp = [ + private static array $AggregateExp = [ 'size' => 'MAX(size) AS maxsize', 'seeders' => 'SUM(seeders) AS sumseeders', 'leechers' => 'SUM(leechers) AS sumleechers', @@ -44,7 +44,7 @@ class Torrent { /** * Map of attribute name => global variable name with list of values that can be used for filtering */ - private static $Attributes = [ + private static array $Attributes = [ 'filter_cat' => false, 'releasetype' => 'ReleaseTypes', 'freetorrent' => false, @@ -57,7 +57,7 @@ class Torrent { /** * List of fields that can be used for fulltext searches */ - private static $Fields = [ + private static array $Fields = [ 'artistname' => 1, 'cataloguenumber' => 1, 'description' => 1, @@ -77,7 +77,7 @@ class Torrent { /** * List of torrent-specific fields that can be used for filtering */ - private static $TorrentFields = [ + private static array $TorrentFields = [ 'description' => 1, 'encoding' => 1, 'filelist' => 1, @@ -91,13 +91,13 @@ class Torrent { /** * Some form field names don't match the ones in the index */ - private static $FormsToFields = [ + private static array $FormsToFields = [ 'searchstr' => '(groupname,artistname,yearfulltext)']; /** * Specify the operator type to use for fields. Empty key sets the default */ - private static $FieldOperators = [ + private static array $FieldOperators = [ '' => self::SPH_BOOL_AND, 'encoding' => self::SPH_BOOL_OR, 'format' => self::SPH_BOOL_OR, @@ -106,7 +106,7 @@ class Torrent { /** * Specify the separator character to use for fields. Empty key sets the default */ - private static $FieldSeparators = [ + private static array $FieldSeparators = [ '' => ' ', 'encoding' => '|', 'format' => '|', @@ -116,20 +116,20 @@ class Torrent { /** * Primary SphinxqlQuery object used to get group IDs or torrent IDs for ungrouped searches */ - private $SphQL; + private readonly \SphinxqlQuery $SphQL; /** * Second SphinxqlQuery object used to get torrent IDs if torrent-specific fulltext filters are used */ - private $SphQLTor; + private ?\SphinxqlQuery $SphQLTor = null; /** * Ordered result array or false if query resulted in an error */ - private $SphResults; + private bool|array|null $SphResults = null; private int $Page; - private int $PageSize; + private readonly int $PageSize; private int $NumResults = 0; private array $Groups = []; @@ -175,7 +175,7 @@ class Torrent { */ private array $UsedTorrentFields = []; - private bool $GroupResults; + private readonly bool $GroupResults; /** * Initialize and configure a Search\Torrent object @@ -352,7 +352,7 @@ class Torrent { * @param string $Attribute Name of the attribute to filter against * @param mixed $Value The filter's condition for a match */ - private function process_attribute($Attribute, $Value) { + private function process_attribute($Attribute, mixed $Value) { if ($Value === '') { return; } @@ -413,8 +413,8 @@ class Torrent { break; case 'releasetype': - $id = (new \Gazelle\ReleaseType)->findIdByName($Value); - if ($id !== false) { + $id = (int)$Value; + if (!is_null((new \Gazelle\ReleaseType)->findNameById($id))) { $this->SphQL->where('ReleaseType', $id); } break; @@ -424,8 +424,8 @@ class Torrent { // Check if the submitted value can be converted to a valid one $ValidValuesVarname = self::$Attributes[$Attribute]; // This code is incomprehensible, I would like to kill the original dev - global $$ValidValuesVarname; - $ValidValues = array_map('strtolower', $$ValidValuesVarname); + global ${$ValidValuesVarname}; + $ValidValues = array_map('strtolower', ${$ValidValuesVarname}); if (($Value = array_search(strtolower($Value), $ValidValues)) === false) { // Force the query to return 0 results if value is still invalid $Value = max(array_keys($ValidValues)) + 1; @@ -596,7 +596,7 @@ class Torrent { if ($Word === '' || $Word === '-') { return; } - if ($Word[0] === '!' && strlen($Word) >= 2 && strpos($Word, '!', 1) === false) { + if ($Word[0] === '!' && strlen($Word) >= 2 && !str_contains(substr($Word, 1), '!')) { $this->Terms[$Field]['exclude'][] = $Word; } else { $this->Terms[$Field]['include'][] = $Word; @@ -616,7 +616,7 @@ class Torrent { * @return string Unprocessed search terms */ public function get_terms($Type) { - return isset($this->RawTerms[$Type]) ? $this->RawTerms[$Type] : ''; + return $this->RawTerms[$Type] ?? ''; } /** diff --git a/app/Search/Transcode.php b/app/Search/Transcode.php index 024f14c1b..fbfd34d64 100644 --- a/app/Search/Transcode.php +++ b/app/Search/Transcode.php @@ -135,6 +135,8 @@ class Transcode extends \Gazelle\Base { } public function list(int $limit, int $offset): array { + $sql = null; + $args = null; $key = sprintf(self::CACHE_KEY, match ($this->mode ?? self::MODE_ANY) { self::MODE_SEEDING => 'seed', @@ -148,13 +150,11 @@ class Transcode extends \Gazelle\Base { ); $list = self::$cache->get_value($key); $list = false; - if (isset($this->search) || $list === false) { - [$sql, $args] = $this->queryList($limit, $offset); - self::$db->prepared_query($sql, ...$args); - $list = self::$db->to_array(false, MYSQLI_ASSOC, false); - if (!isset($this->search)) { - self::$cache->cache_value($key, $list, 3600); - } + [$sql, $args] = $this->queryList($limit, $offset); + self::$db->prepared_query($sql, ...$args); + $list = self::$db->to_array(false, MYSQLI_ASSOC, false); + if (!isset($this->search)) { + self::$cache->cache_value($key, $list, 3600); } foreach ($list as &$row) { $row['torrent'] = $this->torMan->findById($row['source']); @@ -173,6 +173,8 @@ class Transcode extends \Gazelle\Base { } public function total(): array { + $sql = null; + $args = null; $key = sprintf(self::CACHE_KEY, match ($this->mode ?? self::MODE_ANY) { self::MODE_SEEDING => 'total_seed', @@ -186,12 +188,10 @@ class Transcode extends \Gazelle\Base { ); $total = self::$cache->get_value($key); $total = false; - if (isset($this->search) || $total === false) { - [$sql, $args] = $this->queryTotal(); - $total = self::$db->rowAssoc($sql, ...$args); - if (!isset($this->search)) { - self::$cache->cache_value($key, $total, 3600); - } + [$sql, $args] = $this->queryTotal(); + $total = self::$db->rowAssoc($sql, ...$args); + if (!isset($this->search)) { + self::$cache->cache_value($key, $total, 3600); } return $total; } diff --git a/app/SiteInfo.php b/app/SiteInfo.php index a11125f56..97041787b 100644 --- a/app/SiteInfo.php +++ b/app/SiteInfo.php @@ -5,7 +5,6 @@ namespace Gazelle; use Gazelle\Util\Time; class SiteInfo extends Base { - public function gitBranch() { return trim(shell_exec('git rev-parse --abbrev-ref HEAD')); } @@ -55,7 +54,7 @@ class SiteInfo extends Base { shell_exec("$phinxBinary status -c $phinxScript --format=json|tail -n 1"), true )['migrations'], - function($v) { return count($v) > 0; } + fn($v) => count($v) > 0 ) ]; } @@ -89,7 +88,7 @@ class SiteInfo extends Base { } $info = json_decode(shell_exec("composer info -d $root --format=json 2>/dev/null"), true); - foreach ($info['installed'] as $name => $p) { + foreach ($info['installed'] as $p) { if (!isset($packages[$p['name']])) { $packages[$p['name']] = [ 'name' => $p['name'], diff --git a/app/Staff.php b/app/Staff.php index 75218b628..caa0e8e65 100644 --- a/app/Staff.php +++ b/app/Staff.php @@ -3,7 +3,6 @@ namespace Gazelle; class Staff extends BaseUser { - public function id() { return $this->user->id(); } @@ -16,7 +15,7 @@ class Staff extends BaseUser { WHERE UserID = ? ', $this->user->id() ) ?? 0; - self::$cache->cache_value('staff_blog_read_' . $this->user->id(), $readTime, 1209600); + self::$cache->cache_value('staff_blog_read_' . $this->user->id(), $readTime, 1_209_600); } if (($blogTime = self::$cache->get_value('staff_blog_latest_time')) === false) { $blogTime = self::$db->scalar(' @@ -24,7 +23,7 @@ class Staff extends BaseUser { FROM staff_blog ' ) ?? 0; - self::$cache->cache_value('staff_blog_latest_time', $blogTime, 1209600); + self::$cache->cache_value('staff_blog_latest_time', $blogTime, 1_209_600); } return $readTime < $blogTime; } diff --git a/app/StaffPM.php b/app/StaffPM.php index 9d647e897..4aa0a6e11 100644 --- a/app/StaffPM.php +++ b/app/StaffPM.php @@ -25,7 +25,7 @@ class StaffPM extends BaseObject { if (isset($this->info) && !empty($this->info)) { return $this->info; } - $info = self::$db->rowAssoc(" + $this->info = self::$db->rowAssoc(" SELECT spm.Subject AS subject, spm.UserID AS user_id, spm.Level AS class_level, @@ -40,7 +40,6 @@ class StaffPM extends BaseObject { WHERE spm.ID = ? ", $this->id ); - $this->info = $info; return $this->info; } @@ -166,13 +165,14 @@ class StaffPM extends BaseObject { return $affected; } - protected function modifyStatus(User $user, string $status): int { + protected function modifyStatus(User $user, string $status, ?int $resolver): int { self::$db->prepared_query(" UPDATE staff_pm_conversations SET Date = now(), - Status = ? + Status = ?, + ResolverID = ? WHERE ID = ? - ", $status, $this->id + ", $status, $resolver, $this->id ); $affected = self::$db->affected_rows(); $this->flush(); @@ -181,11 +181,11 @@ class StaffPM extends BaseObject { } public function resolve(User $user): int { - return $this->modifyStatus($user, 'Resolved'); + return $this->modifyStatus($user, 'Resolved', $user->id()); } public function unresolve(User $user): int { - return $this->modifyStatus($user, 'Unanswered'); + return $this->modifyStatus($user, 'Unanswered', null); } public function thread(): array { diff --git a/app/Stats/Bonus.php b/app/Stats/Bonus.php index a397c9f36..baebb952e 100644 --- a/app/Stats/Bonus.php +++ b/app/Stats/Bonus.php @@ -3,7 +3,6 @@ namespace Gazelle\Stats; class Bonus extends \Gazelle\Base { - /** * Get the total purchases of all items * @@ -64,20 +63,11 @@ class Bonus extends \Gazelle\Base { * @return array of array of [title, total] aggregated over interval range */ public function accrualRange(string $interval, int $offset, int $length): array { - switch ($interval) { - case 'SECOND': - case 'MINUTE': - case 'HOUR': - $table = 'users_stats_daily'; - break; - case 'DAY': - case 'WEEK': - $table = 'users_stats_monthly'; - break; - default: - $table = 'users_stats_yearly'; - break; - } + $table = match ($interval) { + 'SECOND', 'MINUTE', 'HOUR' => 'users_stats_daily', + 'DAY', 'WEEK' => 'users_stats_monthly', + default => 'users_stats_yearly', + }; return self::$db->rowAssoc(" SELECT us.Time AS `date`, sum(us.BonusPoints) AS total diff --git a/app/Stats/Collage.php b/app/Stats/Collage.php index 4d381fa25..b107fe799 100644 --- a/app/Stats/Collage.php +++ b/app/Stats/Collage.php @@ -8,7 +8,7 @@ class Collage extends \Gazelle\Base { $count = self::$db->scalar(" SELECT count(*) FROM collages WHERE Deleted = '0' "); - self::$cache->cache_value('stats_collages', $count, 43200 + rand(0, 300)); + self::$cache->cache_value('stats_collages', $count, 43200 + random_int(0, 300)); } return $count; } diff --git a/app/Stats/Economic.php b/app/Stats/Economic.php index ff9297972..d765ab936 100644 --- a/app/Stats/Economic.php +++ b/app/Stats/Economic.php @@ -3,8 +3,7 @@ namespace Gazelle\Stats; class Economic extends \Gazelle\Base { - - const CACHE_KEY = 'stats_economic'; + final const CACHE_KEY = 'stats_economic'; protected array $info; diff --git a/app/Stats/Request.php b/app/Stats/Request.php index 09a5f74cc..03ad80b94 100644 --- a/app/Stats/Request.php +++ b/app/Stats/Request.php @@ -15,7 +15,7 @@ class Request extends \Gazelle\Base { sum(if(FillerID > 0, 1, 0)) AS filled FROM requests "); - self::$cache->cache_value(self::CACHE_KEY, $info, 3600 * 3 + rand(0, 1800)); // three hours plus fuzz + self::$cache->cache_value(self::CACHE_KEY, $info, 3600 * 3 + random_int(0, 1800)); // three hours plus fuzz $this->info = $info; } return $info; diff --git a/app/Stats/Torrent.php b/app/Stats/Torrent.php index a04c28ee1..08c7d762d 100644 --- a/app/Stats/Torrent.php +++ b/app/Stats/Torrent.php @@ -5,10 +5,10 @@ namespace Gazelle\Stats; class Torrent extends \Gazelle\Base { protected array $info; - const CACHE_KEY = 'stat_global_torrent'; - const PEER_KEY = 'stat_global_peer'; - const TORRENT_FLOW = 'stat_tflow'; - const CATEGORY_TOTAL = 'stat_tcat'; + final const CACHE_KEY = 'stat_global_torrent'; + final const PEER_KEY = 'stat_global_peer'; + final const TORRENT_FLOW = 'stat_tflow'; + final const CATEGORY_TOTAL = 'stat_tcat'; public function torrentTotal() { return $this->info()['torrent-total']; } public function totalFiles() { return $this->info()['total-files']; } @@ -188,7 +188,7 @@ class Torrent extends \Gazelle\Base { $total = self::$db->scalar(" SELECT count(*) FROM torrents_group WHERE CategoryID = 1 "); - self::$cache->cache_value('stats_album_count', $total, 7200 + rand(0, 300)); + self::$cache->cache_value('stats_album_count', $total, 7200 + random_int(0, 300)); } return $total; } @@ -202,7 +202,7 @@ class Torrent extends \Gazelle\Base { $total = self::$db->scalar(" SELECT count(*) FROM artists_group "); - self::$cache->cache_value('stats_artist_count', $total, 7200 + rand(0, 300)); + self::$cache->cache_value('stats_artist_count', $total, 7200 + random_int(0, 300)); } return $total; } @@ -223,7 +223,7 @@ class Torrent extends \Gazelle\Base { (Media in ('BD', 'DVD', 'Soundboard', 'WEB', 'Vinyl')) ) "); - self::$cache->cache_value('stats_perfect_total', $total, 7200 + rand(0, 300)); + self::$cache->cache_value('stats_perfect_total', $total, 7200 + random_int(0, 300)); } return $total; } diff --git a/app/Stats/Users.php b/app/Stats/Users.php index 9ba332340..a1d8a6660 100644 --- a/app/Stats/Users.php +++ b/app/Stats/Users.php @@ -174,7 +174,7 @@ class Users extends \Gazelle\Base { } for ($i = $CountryMin; $i <= $CountryMax; $i++) { - $LogIncrements[] = \Format::human_format(pow(2, $i)); + $LogIncrements[] = \Format::human_format(2 ** $i); } self::$cache->cache_value('geodistribution', [$Countries, $Rank, $CountryUsers, $CountryMax, $CountryMin, $LogIncrements], 86400 * 3); } @@ -197,7 +197,7 @@ class Users extends \Gazelle\Base { WHERE active = 1 ") ?? ['seeder_total' => 0, 'leecher_total' => 0] ); - self::$cache->cache_value('stat_xbt_fu', $stat, 3600 + rand(0, 120)); + self::$cache->cache_value('stat_xbt_fu', $stat, 3600 + random_int(0, 120)); } $this->info['xbt_files_users'] = $stat; } @@ -224,7 +224,7 @@ class Users extends \Gazelle\Base { $total = self::$cache->get_value('stats_snatch'); if ($total === false) { $total = (int)self::$db->scalar("SELECT count(*) FROM xbt_snatched"); - self::$cache->cache_value('stats_snatch', $total, 3600 + rand(0, 12)); + self::$cache->cache_value('stats_snatch', $total, 3600 + random_int(0, 12)); } $this->info['snatch'] = $total; } @@ -284,7 +284,7 @@ class Users extends \Gazelle\Base { AND ula.last_access > now() - INTERVAL 1 MONTH ") ?? ['active_day' => 0, 'active_week' => 0, 'active_month' => 0] ); - self::$cache->cache_value('stats_user_active', $active, 7200 + rand(0, 300)); + self::$cache->cache_value('stats_user_active', $active, 7200 + random_int(0, 300)); } $this->info['active'] = $active; } diff --git a/app/TGroup.php b/app/TGroup.php index 33729e569..a1c97872e 100644 --- a/app/TGroup.php +++ b/app/TGroup.php @@ -3,15 +3,15 @@ namespace Gazelle; class TGroup extends BaseObject { - const CACHE_KEY = 'tg_%d'; - const CACHE_TLIST_KEY = 'tlist_%d'; - const CACHE_COVERART_KEY = 'tg_cover_%d'; - const USER_RECENT_SNATCH = 'u_recent_snatch_%d'; - const USER_RECENT_UPLOAD = 'u_recent_up_%d'; - const CACHE_REQUEST_TGROUP = 'req_tg_%d'; + final const CACHE_KEY = 'tg_%d'; + final const CACHE_TLIST_KEY = 'tlist_%d'; + final const CACHE_COVERART_KEY = 'tg_cover_%d'; + final const USER_RECENT_SNATCH = 'u_recent_snatch_%d'; + final const USER_RECENT_UPLOAD = 'u_recent_up_%d'; + final const CACHE_REQUEST_TGROUP = 'req_tg_%d'; - const ARTIST_DISPLAY_TEXT = 1; - const ARTIST_DISPLAY_HTML = 2; + final const ARTIST_DISPLAY_TEXT = 1; + final const ARTIST_DISPLAY_HTML = 2; protected int $revisionId = 0; protected bool $showFallbackImage = true; @@ -115,6 +115,16 @@ class TGroup extends BaseObject { return $this; } + public function touch(): TGroup { + self::$db->prepared_query(' + UPDATE torrents_group SET + Time = now() + WHERE ID = ? + ', $this->id + ); + return $this; + } + public function setViewer(User $viewer): TGroup { $this->viewer = $viewer; return $this; diff --git a/app/Top10/Torrent.php b/app/Top10/Torrent.php index 44159cf93..b851d6179 100644 --- a/app/Top10/Torrent.php +++ b/app/Top10/Torrent.php @@ -34,13 +34,9 @@ class Torrent extends \Gazelle\Base { $where[] = ["parameters" => null, "where" => "tls.Seeders > 0"]; - $whereFilter = function($value) { - return $value["where"] ?? null; - }; + $whereFilter = fn($value) => $value["where"] ?? null; - $parameterFilter = function($value) { - return $value["parameters"] ?? null; - }; + $parameterFilter = fn($value) => $value["parameters"] ?? null; $filteredWhere = array_filter(array_map($whereFilter, $where)); $parameters = $this->flatten(array_filter(array_map($parameterFilter, $where))); @@ -62,7 +58,7 @@ class Torrent extends \Gazelle\Base { $innerQuery .= " WHERE " . implode(" AND ", $filteredWhere); $innerQuery = $innerQuery . (isset($getParameters['groups']) && $getParameters['groups'] == 'show' ? ' GROUP BY g.ID ' : ''); - $orderBy = 'ORDER BY ' . $this->orderBy($details) . ' DESC'; + $orderBy = $this->orderBy($details); $query = sprintf($this->baseQuery, $innerQuery, @@ -87,47 +83,29 @@ class Torrent extends \Gazelle\Base { } private function orderBy($details) { - switch($details) { - case 'snatched': - return 'tls.Snatched'; - break; - case 'seeded': - return 'tls.Seeders'; - break; - case 'data': - return 'Data'; - break; - default: - return '(tls.Seeders + tls.Leechers)'; - break; - } + return match ($details) { + 'snatched' => 'tls.Snatched', + 'seeded' => 'tls.Seeders', + 'data' => 'Data', + default => '(tls.Seeders + tls.Leechers)', + }; } private function detailsWhere($detailsParameters) { - switch($detailsParameters) { - case 'day': - return ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 DAY"]; - break; - case 'week': - return ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 WEEK"]; - break; - case 'month': - return ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 MONTH"]; - break; - case 'year': - return ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 YEAR"]; - break; - default: - return []; - break; - } + return match ($detailsParameters) { + 'day' => ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 DAY"], + 'week' => ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 WEEK"], + 'month' => ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 MONTH"], + 'year' => ["parameters" => null, "where" => "t.Time > now() - INTERVAL 1 YEAR"], + default => [], + }; } private function excludedArtistClause($artistParameter) { if (!empty($artistParameter)) { $artists = preg_split('/\r\n|\r|\n/', trim($artistParameter)); - $artistPrepare = function($artist) { return trim($artist); }; + $artistPrepare = fn($artist) => trim($artist); $artists = array_map($artistPrepare, $artists); $sql = " @@ -167,7 +145,7 @@ class Torrent extends \Gazelle\Base { private function tagWhere($getParameters, $any = false) { if (!empty($getParameters)) { $tags = explode(',', trim($getParameters)); - $replace = function($tag) { return preg_replace('/[^a-z0-9.]/', '', $tag); }; + $replace = fn($tag) => preg_replace('/[^a-z0-9.]/', '', $tag); $tags = array_map($replace, $tags); $tags = array_filter($tags); @@ -196,7 +174,7 @@ class Torrent extends \Gazelle\Base { return $return; } - private $baseQuery = " + private string $baseQuery = " SELECT t.ID, g.ID, diff --git a/app/Top10/User.php b/app/Top10/User.php index f91655512..10bcf3298 100644 --- a/app/Top10/User.php +++ b/app/Top10/User.php @@ -3,18 +3,17 @@ namespace Gazelle\Top10; class User extends \Gazelle\Base { - - public const UPLOADERS = 'uploaders'; - public const DOWNLOADERS = 'downloaders'; - public const UPLOADS = 'uploads'; - public const REQUEST_VOTES = 'request_votes'; - public const REQUEST_FILLS = 'request_fills'; - public const UPLOAD_SPEED = 'upload_speed'; - public const DOWNLOAD_SPEED = 'download_speed'; + final public const UPLOADERS = 'uploaders'; + final public const DOWNLOADERS = 'downloaders'; + final public const UPLOADS = 'uploads'; + final public const REQUEST_VOTES = 'request_votes'; + final public const REQUEST_FILLS = 'request_fills'; + final public const UPLOAD_SPEED = 'upload_speed'; + final public const DOWNLOAD_SPEED = 'download_speed'; private const CACHE_KEY = 'topusers_%s_%d'; - private $sortMap = [ + private array $sortMap = [ self::UPLOADERS => 'uploaded', self::DOWNLOADERS => 'downloaded', self::UPLOADS => 'num_uploads', diff --git a/app/Torrent.php b/app/Torrent.php index 15691793f..03a3f7900 100644 --- a/app/Torrent.php +++ b/app/Torrent.php @@ -3,13 +3,13 @@ namespace Gazelle; class Torrent extends TorrentAbstract { - const CACHE_LOCK = 'torrent_lock_%d'; - const CACHE_KEY_PEERLIST_TOTAL = 'peerlist_total_%d'; - const CACHE_KEY_PEERLIST_PAGE = 'peerlist_page_%d_%d'; - const CACHE_REPORTLIST = 't_rpt2_%s_%d'; - const USER_RECENT_UPLOAD = 'u_recent_up_%d'; + final const CACHE_LOCK = 'torrent_lock_%d'; + final const CACHE_KEY_PEERLIST_TOTAL = 'peerlist_total_%d'; + final const CACHE_KEY_PEERLIST_PAGE = 'peerlist_page_%d_%d'; + final const CACHE_REPORTLIST = 't_rpt2_%s_%d'; + final const USER_RECENT_UPLOAD = 'u_recent_up_%d'; - const SNATCHED_UPDATE_INTERVAL = 3600; // How often we want to update users' snatch lists + final const SNATCHED_UPDATE_INTERVAL = 3600; // How often we want to update users' snatch lists protected $tokenCache; protected $updateTime; @@ -447,7 +447,7 @@ class Torrent extends TorrentAbstract { */ public function remove(int $userId, string $reason, int $trackerReason = -1): array { $qid = self::$db->get_query_id(); - $info = $this->info(); + $this->info(); if ($this->id > MAX_PREV_TORRENT_ID) { (new \Gazelle\User\Bonus($this->uploader()))->removePointsForUpload($this); } @@ -459,9 +459,6 @@ class Torrent extends TorrentAbstract { return [false, $message]; } [$ok, $message] = $manager->softDelete(SQLDB, 'torrents', [['ID', $this->id]]); - if (!$ok) { - return [false, $message]; - } $infohash = $this->infohash(); $manager->relaxConstraints(false); (new \Gazelle\Tracker)->update_tracker('delete_torrent', [ diff --git a/app/Torrent/ReportType.php b/app/Torrent/ReportType.php index 8c4a4fb34..603f14907 100644 --- a/app/Torrent/ReportType.php +++ b/app/Torrent/ReportType.php @@ -3,7 +3,7 @@ namespace Gazelle\Torrent; class ReportType extends \Gazelle\BaseObject { - const CACHE_KEY = 'trepcfg_%d'; + final const CACHE_KEY = 'trepcfg_%d'; protected array $info; protected array $changeSet; diff --git a/app/TorrentAbstract.php b/app/TorrentAbstract.php index 41eb2cc07..0b4e8c8c0 100644 --- a/app/TorrentAbstract.php +++ b/app/TorrentAbstract.php @@ -3,7 +3,7 @@ namespace Gazelle; abstract class TorrentAbstract extends BaseObject { - const CACHE_KEY = 't_%d'; + public const CACHE_KEY = 't_%d'; protected TGroup $tgroup; protected User $viewer; @@ -151,8 +151,8 @@ abstract class TorrentAbstract extends BaseObject { } if ($this->isRemastered()) { $edition = [ - $this->remasterRecordLabel() ?? $tgroup->recordLabel(), - $this->remasterCatalogueNumber() ?? $tgroup->catalogueNumber(), + $this->remasterRecordLabel(), + $this->remasterCatalogueNumber(), $this->remasterTitle(), ]; } elseif ($tgroup->recordLabel() || $tgroup->catalogueNumber()) { @@ -191,7 +191,7 @@ abstract class TorrentAbstract extends BaseObject { 'ext' => $match[1] ?? null, 'size' => (int)$match[2] ?? 0, // transform leading blanks into hard blanks so that it shows up in HTML - 'name' => preg_replace_callback('/^(\s+)/', function ($s) { return str_repeat(' ', strlen($s[1])); }, $match[3] ?? ''), + 'name' => preg_replace_callback('/^(\s+)/', fn($s) => str_repeat(' ', strlen($s[1])), $match[3] ?? ''), ]; } return [ diff --git a/app/TorrentDeleted.php b/app/TorrentDeleted.php index aef9c3f95..268dacd2b 100644 --- a/app/TorrentDeleted.php +++ b/app/TorrentDeleted.php @@ -3,7 +3,7 @@ namespace Gazelle; class TorrentDeleted extends TorrentAbstract { - const CACHE_KEY = 'tdel_%d'; + final const CACHE_KEY = 'tdel_%d'; public function location(): string { return "log.php?search=Torrent+" . $this->id; } public function tableName(): string { return 'deleted_torrents'; } diff --git a/app/TorrentLog.php b/app/TorrentLog.php index edfa52c8e..98a3a827b 100644 --- a/app/TorrentLog.php +++ b/app/TorrentLog.php @@ -59,7 +59,7 @@ class TorrentLog extends BaseObject { } public function adjustment(string $key): string { - return isset($this->info()['adjustment_list'][$key]) ? $this->info()['adjustment_list'][$key] : ''; + return $this->info()['adjustment_list'][$key] ?? ''; } public function adjustmentTrack(string $key): int { diff --git a/app/Tracker.php b/app/Tracker.php index 9f555e959..bd31226f3 100644 --- a/app/Tracker.php +++ b/app/Tracker.php @@ -19,8 +19,8 @@ namespace Gazelle; use Gazelle\Util\Irc; class Tracker { - const STATS_MAIN = 0; - const STATS_USER = 1; + final const STATS_MAIN = 0; + final const STATS_USER = 1; protected static $Requests = []; @@ -66,7 +66,7 @@ class Tracker { * * @return array|false (0 => $Leeching, 1 => $Seeding) or false if request failed */ - public function global_peer_count() { + public function global_peer_count(): array|false { $Stats = $this->get_stats(self::STATS_MAIN); if (isset($Stats['leechers tracked']) && isset($Stats['seeders tracked'])) { $Leechers = $Stats['leechers tracked']; @@ -83,7 +83,7 @@ class Tracker { * @param string $TorrentPass The user's pass key * @return false|array (0 => $Leeching, 1 => $Seeding) or false if the request failed */ - public function user_peer_count(string $TorrentPass) { + public function user_peer_count(string $TorrentPass): false|array { $Stats = $this->get_stats(self::STATS_USER, ['key' => $TorrentPass]); if ($Stats === false) { return false; @@ -114,7 +114,7 @@ class Tracker { * @param false|array $Params Parameters required by stats type * @return array with stats in named keys or empty if the request failed */ - private function get_stats($Type, $Params = false): array { + private function get_stats($Type, false|array $Params = false): array { if (DISABLE_TRACKER) { return []; } @@ -132,7 +132,7 @@ class Tracker { } $Stats = []; foreach (explode("\n", $Response) as $Stat) { - list($Val, $Key) = explode(" ", $Stat, 2); + [$Val, $Key] = explode(" ", $Stat, 2); $Stats[$Key] = $Val; } return $Stats; @@ -146,7 +146,7 @@ class Tracker { * @param bool $Err Variable to use as storage for the error string if the request fails * @return false|string tracker response message or false if the request failed */ - private function send_request($Get, $MaxAttempts = 1, &$Err = false) { + private function send_request($Get, $MaxAttempts = 1, &$Err = false): false|string { if (DISABLE_TRACKER) { return false; } diff --git a/app/User.php b/app/User.php index f1e306169..4f8b417a9 100644 --- a/app/User.php +++ b/app/User.php @@ -6,15 +6,15 @@ use Gazelle\Util\Irc; use Gazelle\Util\Mail; class User extends BaseObject { - const CACHE_KEY = 'u2_%d'; - const CACHE_SNATCH_TIME = 'users_snatched_%d_time'; - const CACHE_NOTIFY = 'u_notify_%d'; - const USER_RECENT_SNATCH = 'u_recent_snatch_%d'; - const USER_RECENT_UPLOAD = 'u_recent_up_%d'; + final const CACHE_KEY = 'u2_%d'; + final const CACHE_SNATCH_TIME = 'users_snatched_%d_time'; + final const CACHE_NOTIFY = 'u_notify_%d'; + final const USER_RECENT_SNATCH = 'u_recent_snatch_%d'; + final const USER_RECENT_UPLOAD = 'u_recent_up_%d'; - const SNATCHED_UPDATE_AFTERDL = 300; // How long after a torrent download we want to update a user's snatch lists + final const SNATCHED_UPDATE_AFTERDL = 300; // How long after a torrent download we want to update a user's snatch lists - const DISCOGS_API_URL = 'https://api.discogs.com/artists/%d'; + final const DISCOGS_API_URL = 'https://api.discogs.com/artists/%d'; protected bool $forceCacheFlush = false; protected int $lastReadForum; @@ -789,7 +789,6 @@ class User extends BaseObject { * Checks whether user has autocomplete enabled * * @param string $Type Where the is the input requested (search, other) - * @return boolean */ public function hasAutocomplete($Type): bool { $autoComplete = $this->option('AutoComplete'); @@ -837,8 +836,6 @@ class User extends BaseObject { /** * Checks whether user has any overrides to a forum * - * @param int $forumId - * @param int $forumMinClassLevel * @return bool has access */ public function forumAccess(int $forumId, int $forumMinClassLevel): bool { @@ -849,7 +846,6 @@ class User extends BaseObject { /** * Checks whether user has the permission to create a forum. * - * @param \Gazelle\Forum $forum * @return boolean true if user has permission */ public function createAccess(Forum $forum): bool { @@ -859,7 +855,6 @@ class User extends BaseObject { /** * Checks whether user has the permission to read a forum. * - * @param \Gazelle\Forum $forum * @return boolean true if user has permission */ public function readAccess(Forum $forum): bool { @@ -869,7 +864,6 @@ class User extends BaseObject { /** * Checks whether user has the permission to write to a forum. * - * @param \Gazelle\Forum $forum * @return boolean true if user has permission */ public function writeAccess(Forum $forum): bool { @@ -879,7 +873,6 @@ class User extends BaseObject { /** * Checks whether the user is up to date on the forum * - * @param \Gazelle\Forum $forum * @return bool the user is up to date */ public function hasReadLastPost(Forum $forum): bool { @@ -890,8 +883,6 @@ class User extends BaseObject { /** * What is the last post this user has read in a thread? - * - * @param int $threadId */ public function lastReadInThread(int $threadId): int { if (!isset($this->lastRead)) { @@ -1327,7 +1318,7 @@ class User extends BaseObject { ', $this->id ); $filters = self::$db->to_pair('ID', 'Label', false); - self::$cache->cache_value($key, $filters, 2592000); + self::$cache->cache_value($key, $filters, 2_592_000); } return $filters; } @@ -1426,7 +1417,6 @@ class User extends BaseObject { $info['Artists'] = str_ireplace("|$alias|", '|', $info['Artists']); } } - $change = 0; if ($info['Artists'] === '||') { self::$db->prepared_query(" DELETE FROM users_notify_filters @@ -1829,7 +1819,6 @@ class User extends BaseObject { /** * Generates a check list of release types, ordered by the user or default - * @param array $releaseType */ public function releaseOrder(array $releaseType) { if (empty($this->option('SortHide'))) { @@ -1971,9 +1960,7 @@ class User extends BaseObject { public function buffer(): array { $class = $this->primaryClass(); - $demotion = array_filter((new Manager\User)->demotionCriteria(), function ($v) use ($class) { - return in_array($class, $v['From']); - }); + $demotion = array_filter((new Manager\User)->demotionCriteria(), fn($v) => in_array($class, $v['From'])); $criteria = end($demotion); $effectiveUpload = $this->uploadedSize() + $this->stats()->requestBountySize(); @@ -2553,8 +2540,6 @@ class User extends BaseObject { /** * Update donor rewards - * - * @param array $field */ public function updateReward(array $field) { $Rank = $this->donorRank(); @@ -2632,7 +2617,7 @@ class User extends BaseObject { VALUES (?, " . placeholders($insert) . ") ON DUPLICATE KEY UPDATE " . implode(', ', array_map(fn($c) => "$c = ?", $insert)), - $UserID, ...array_merge($args, $args) + $UserID, ...[...$args, ...$args] ); } self::$db->set_query_id($QueryID); diff --git a/app/User/AutoEnable.php b/app/User/AutoEnable.php index 60007a69b..976c862b3 100644 --- a/app/User/AutoEnable.php +++ b/app/User/AutoEnable.php @@ -6,11 +6,8 @@ use Gazelle\Util\Mail; use Gazelle\Util\Time; class AutoEnable extends \Gazelle\BaseUser { - // Cache key to store the number of enable requests - const CACHE_TOTAL_OPEN = 'num_enable_requests'; - - protected int $id; + final const CACHE_TOTAL_OPEN = 'num_enable_requests'; protected array $info; /** @@ -20,9 +17,8 @@ class AutoEnable extends \Gazelle\BaseUser { * via the Gazelle\Manager\AutoEnable::find*() methods will take * care of this for you. */ - public function __construct(int $id, \Gazelle\User $user) { + public function __construct(protected int $id, \Gazelle\User $user) { parent::__construct($user); - $this->id = $id; } public function id(): int { diff --git a/app/User/Bonus.php b/app/User/Bonus.php index 2364ad513..e86a8ddc1 100644 --- a/app/User/Bonus.php +++ b/app/User/Bonus.php @@ -3,10 +3,10 @@ namespace Gazelle\User; class Bonus extends \Gazelle\BaseUser { - const CACHE_PURCHASE = 'bonus_purchase_%d'; - const CACHE_SUMMARY = 'bonus_summary_%d'; - const CACHE_HISTORY = 'bonus_history_%d_%d'; - const CACHE_POOL_HISTORY = 'bonus_pool_history_%d'; + final const CACHE_PURCHASE = 'bonus_purchase_%d'; + final const CACHE_SUMMARY = 'bonus_summary_%d'; + final const CACHE_HISTORY = 'bonus_history_%d_%d'; + final const CACHE_POOL_HISTORY = 'bonus_pool_history_%d'; public function flush(): Bonus { $this->user->flush(); @@ -68,7 +68,7 @@ class Bonus extends \Gazelle\BaseUser { public function getEffectivePrice(string $label): int { $item = $this->items()[$label]; if (preg_match('/^collage-\d$/', $label)) { - return $item['Price'] * pow(2, $this->user->paidPersonalCollages()); + return $item['Price'] * 2 ** $this->user->paidPersonalCollages(); } return $this->user->effectiveClass() >= $item['FreeClass'] ? 0 : (int)$item['Price']; } @@ -284,7 +284,7 @@ class Bonus extends \Gazelle\BaseUser { VALUES (?, (SELECT ID FROM user_attr WHERE Name = ?)) ", $this->user->id(), 'feature-seedbox' ); - } catch (\Gazelle\DB\Mysql_DuplicateKeyException $e) { + } catch (\Gazelle\DB\Mysql_DuplicateKeyException) { // no point in buying a second time self::$db->rollback(); return false; diff --git a/app/User/Bookmark.php b/app/User/Bookmark.php index baaa6f97a..516e933c0 100644 --- a/app/User/Bookmark.php +++ b/app/User/Bookmark.php @@ -90,8 +90,7 @@ class Bookmark extends \Gazelle\BaseUser { $key = "bookmarks_group_ids_" . $this->user->id(); $bookmarkList = self::$cache->get_value($key); $bookmarkList = false; - if ($bookmarkList === false) { - self::$db->prepared_query(" + self::$db->prepared_query(" SELECT GroupID AS tgroup_id, Sort AS sequence, `Time` AS created @@ -99,10 +98,9 @@ class Bookmark extends \Gazelle\BaseUser { WHERE UserID = ? ORDER BY Sort, `Time` ", $this->user->id() - ); - $bookmarkList = self::$db->to_array(false, MYSQLI_ASSOC, false); - self::$cache->cache_value($key, $bookmarkList, 3600); - } + ); + $bookmarkList = self::$db->to_array(false, MYSQLI_ASSOC, false); + self::$cache->cache_value($key, $bookmarkList, 3600); return $bookmarkList; } diff --git a/app/User/InviteTree.php b/app/User/InviteTree.php index d1050bb3d..5c32d8a82 100644 --- a/app/User/InviteTree.php +++ b/app/User/InviteTree.php @@ -186,7 +186,7 @@ class InviteTree extends \Gazelle\Base { 'download_top' => 0, ]; $classSummary = []; - foreach ($inviteeList as list($inviteeId, $position, $depth)) { + foreach ($inviteeList as [$inviteeId, $position, $depth]) { $invitee = $userMan->findById($inviteeId); if (is_null($invitee)) { continue; diff --git a/app/User/Notification.php b/app/User/Notification.php index be7cba847..3a3077d01 100644 --- a/app/User/Notification.php +++ b/app/User/Notification.php @@ -5,12 +5,12 @@ namespace Gazelle\User; class Notification extends \Gazelle\BaseUser { protected const CACHE_KEY = 'u_notif_%d'; - const DISPLAY_DISABLED = 0; - const DISPLAY_POPUP = 1; - const DISPLAY_TRADITIONAL = 2; - const DISPLAY_PUSH = 3; - const DISPLAY_POPUP_PUSH = 4; - const DISPLAY_TRADITIONAL_PUSH = 5; + final const DISPLAY_DISABLED = 0; + final const DISPLAY_POPUP = 1; + final const DISPLAY_TRADITIONAL = 2; + final const DISPLAY_PUSH = 3; + final const DISPLAY_POPUP_PUSH = 4; + final const DISPLAY_TRADITIONAL_PUSH = 5; protected array $alert; protected array $config; @@ -42,9 +42,8 @@ class Notification extends \Gazelle\BaseUser { } $key = sprintf(self::CACHE_KEY, $this->user->id()); $config = self::$cache->get_value($key); - $config = false; // TODO allow caching - if ($config == false) { - $config = self::$db->rowAssoc(" + // TODO allow caching + $config = self::$db->rowAssoc(" SELECT Blog AS Blog, Collages AS Collage, Inbox AS Inbox, @@ -56,18 +55,16 @@ class Notification extends \Gazelle\BaseUser { FROM users_notifications_settings AS n WHERE n.UserID = ? ", $this->user->id() - ) ?? [ - 'Blog' => 0, - 'Collages' => 0, - 'Inbox' => 0, - 'News' => 0, - 'Quotes' => 0, - 'StaffPM' => 0, - 'Subscriptions' => 0, - 'Torrents' => 0, - ]; - self::$cache->cache_value($key, $config, 0); - } + ) ?? [ + 'Blog' => 0, + 'Collages' => 0, + 'Inbox' => 0, + 'News' => 0, + 'Quotes' => 0, + 'StaffPM' => 0, + 'Subscriptions' => 0, + 'Torrents' => 0, + ]; self::$cache->cache_value($key, $config, 0); $this->config = $config; return $this->config; } diff --git a/app/User/Notification/AbstractNotification.php b/app/User/Notification/AbstractNotification.php index 401553ef8..d1d42d8ae 100644 --- a/app/User/Notification/AbstractNotification.php +++ b/app/User/Notification/AbstractNotification.php @@ -3,7 +3,6 @@ namespace Gazelle\User\Notification; abstract class AbstractNotification extends \Gazelle\BaseUser { - protected int $context; // id of a table row protected string $display; protected string $title; @@ -14,7 +13,7 @@ abstract class AbstractNotification extends \Gazelle\BaseUser { abstract public function load(): bool; public function context(): int { - return isset($this->context) ? $this->context : 0; + return $this->context ?? 0; } public function setDisplay(string $display): AbstractNotification { @@ -31,7 +30,7 @@ abstract class AbstractNotification extends \Gazelle\BaseUser { } public function type(): string { - $path = explode('\\', get_class($this)); + $path = explode('\\', static::class); return end($path); // silence "Only variables should be passed by reference" } diff --git a/app/User/Notification/GlobalNotification.php b/app/User/Notification/GlobalNotification.php index 447076cfe..10fbea06c 100644 --- a/app/User/Notification/GlobalNotification.php +++ b/app/User/Notification/GlobalNotification.php @@ -10,7 +10,7 @@ class GlobalNotification extends AbstractNotification { protected string $className; public function className(): string { - return isset($this->className) ? $this->className : 'error'; + return $this->className ?? 'error'; } public function clear(): int { diff --git a/app/User/Notification/Quote.php b/app/User/Notification/Quote.php index 99e214fd8..39d5debaa 100644 --- a/app/User/Notification/Quote.php +++ b/app/User/Notification/Quote.php @@ -3,7 +3,6 @@ namespace Gazelle\User\Notification; class Quote extends AbstractNotification { - public function className(): string { return 'confirmation'; } @@ -25,10 +24,6 @@ class Quote extends AbstractNotification { /** * Parse a post/comment body for quotes and notify all quoted users that have quote notifications enabled. * - * @param string $body - * @param int $postId - * @param string $page - * @param int $pageId * @return int Number of users notified */ public function create(\Gazelle\Manager\User $userMan, string $body, int $postId, string $page, int $pageId): int { diff --git a/app/User/NotificationSearch.php b/app/User/NotificationSearch.php index 8cd0468f4..473c7dfbc 100644 --- a/app/User/NotificationSearch.php +++ b/app/User/NotificationSearch.php @@ -44,7 +44,7 @@ class NotificationSearch extends \Gazelle\BaseUser { } public function filterId(): ?int { - return isset($this->filterId) ? $this->filterId : null; + return $this->filterId ?? null; } public function pageSql(): string { diff --git a/app/User/Privilege.php b/app/User/Privilege.php index 11af2a5cd..421f552da 100644 --- a/app/User/Privilege.php +++ b/app/User/Privilege.php @@ -3,13 +3,12 @@ namespace Gazelle\User; class Privilege extends \Gazelle\BaseUser { - - const CACHE_KEY = 'u_priv_%d'; + final const CACHE_KEY = 'u_priv_%d'; protected array $info; public function info(): array { - if (!empty($this->info)) { + if (isset($this->info) && !empty($this->info)) { return $this->info; } $id = $this->user->id(); diff --git a/app/User/Quote.php b/app/User/Quote.php index 025a42f9b..c758b4839 100644 --- a/app/User/Quote.php +++ b/app/User/Quote.php @@ -3,8 +3,7 @@ namespace Gazelle\User; class Quote extends \Gazelle\BaseUser { - - const UNREAD_QUOTE_KEY = 'u_unread_%d'; + final const UNREAD_QUOTE_KEY = 'u_unread_%d'; protected bool $showAll = false; @@ -173,9 +172,9 @@ class Quote extends \Gazelle\BaseUser { $quoteList = self::$db->to_array(false, MYSQLI_ASSOC, false); $page = []; - $forumMan = new \Gazelle\Manager\Forum; + new \Gazelle\Manager\Forum; $postMan = new \Gazelle\Manager\ForumPost; - $releaseType = new \Gazelle\ReleaseType; + new \Gazelle\ReleaseType; $reqMan = new \Gazelle\Manager\Request; $tgMan = new \Gazelle\Manager\TGroup; diff --git a/app/User/Seedbox.php b/app/User/Seedbox.php index d534d62f7..da0cbe1a6 100644 --- a/app/User/Seedbox.php +++ b/app/User/Seedbox.php @@ -3,11 +3,10 @@ namespace Gazelle\User; class Seedbox extends \Gazelle\BaseUser { - protected const SUMMARY_KEY = 'seedbox_summary_'; - public const VIEW_BY_NAME = 0; - public const VIEW_BY_PATH = 1; + final public const VIEW_BY_NAME = 0; + final public const VIEW_BY_PATH = 1; protected \Hashids\Hashids $hashid; protected array $host = []; @@ -174,7 +173,7 @@ class Seedbox extends \Gazelle\BaseUser { */ public function updateNames(array $update): int { $n = 0; - $hostlist = $this->hostList(); + $this->hostList(); foreach ($update as $seedbox) { $name = $seedbox['name']; if ($name == '') { @@ -194,7 +193,7 @@ class Seedbox extends \Gazelle\BaseUser { AND user_seedbox_id = ? ", mb_substr($name, 0, 100), $this->user->id(), $this->hashid->decode($seedbox['id'])[0] ); - } catch (\Gazelle\DB\Mysql_DuplicateKeyException $e) { + } catch (\Gazelle\DB\Mysql_DuplicateKeyException) { // do nothing } finally { $n += self::$db->affected_rows(); @@ -221,7 +220,7 @@ class Seedbox extends \Gazelle\BaseUser { DELETE FROM user_seedbox WHERE user_id = ? AND user_seedbox_id in (" . placeholders($remove) . ") - ", $this->user->id(), ...array_map(function ($id) use ($h) {return $h->decode($id)[0];}, $remove) + ", $this->user->id(), ...array_map(fn($id) => $h->decode($id)[0], $remove) ); $affected = self::$db->affected_rows(); $this->flush()->build(); diff --git a/app/User/Snatch.php b/app/User/Snatch.php index 42c63b4f8..f31772d03 100644 --- a/app/User/Snatch.php +++ b/app/User/Snatch.php @@ -15,14 +15,13 @@ use \Gazelle\Util\CacheVector; */ class Snatch extends \Gazelle\BaseUser { - // A power-of-2 size, to be balanced against how many rows a query on xbt_snatched could return - const RANGE = 17; - const RANGE_BIT = 2 ** self::RANGE; + final const RANGE = 17; + final const RANGE_BIT = 2 ** self::RANGE; // base the cache name of the size strategy - const CACHE_KEY = 'u_snatch_' . self::RANGE . '_%d_%d'; - const CACHE_EXPIRY = 2700; + final const CACHE_KEY = 'u_snatch_' . self::RANGE . '_%d_%d'; + final const CACHE_EXPIRY = 2700; protected array $snatchVec = []; @@ -37,7 +36,6 @@ class Snatch extends \Gazelle\BaseUser { $offset = (int)floor($torrentId / self::RANGE_BIT); if (!isset($this->snatchVec[$offset])) { $vector = new CacheVector(sprintf(self::CACHE_KEY, $this->user->id(), $offset), self::RANGE_BIT / 8, self::CACHE_EXPIRY); - $total = -1; if ($vector->isEmpty()) { // the vector contents might have been cached, but if not, only we know how to initialize it $this->load($offset, $vector); diff --git a/app/User/Stylesheet.php b/app/User/Stylesheet.php index 77398fbc4..aded51083 100644 --- a/app/User/Stylesheet.php +++ b/app/User/Stylesheet.php @@ -3,7 +3,6 @@ namespace Gazelle\User; class Stylesheet extends \Gazelle\BaseUser { - protected const CACHE_KEY = 'u_ss2_%d'; protected array $info; @@ -80,7 +79,7 @@ class Stylesheet extends \Gazelle\BaseUser { . base_convert(filemtime(SERVER_ROOT . '/sass/' . preg_replace('/\.css$/', '.scss', $this->cssName())), 10, 36); } $info = parse_url($url); - if (substr($info['path'], -4) === '.css' + if (str_ends_with($info['path'], '.css') && (($info['query'] ?? '') . ($info['fragment'] ?? '')) === '' && $info['host'] === SITE_HOST && file_exists(SERVER_ROOT . $info['path'])) { diff --git a/app/User/Subscription.php b/app/User/Subscription.php index d8a11638f..c964e757b 100644 --- a/app/User/Subscription.php +++ b/app/User/Subscription.php @@ -176,7 +176,7 @@ class Subscription extends \Gazelle\BaseUser { */ public function isSubscribedComments(string $page, int $pageId): bool { return !empty(array_filter($this->commentSubscriptions(), - function ($s) use ($page, $pageId) { return $s[0] === $page && $s[1] == $pageId; }) + fn($s) => $s[0] === $page && $s[1] == $pageId) ); } diff --git a/app/User/Vote.php b/app/User/Vote.php index bd4c0bc0b..450d9765e 100644 --- a/app/User/Vote.php +++ b/app/User/Vote.php @@ -3,12 +3,12 @@ namespace Gazelle\User; class Vote extends \Gazelle\BaseUser { - const Z_VAL = 1.281728756502709; // original - const Z_VAL_90 = 1.6448536251336989; // p-value .90 - const Z_VAL_95 = 1.959963986120195; // .95 + final const Z_VAL = 1.281728756502709; // original + final const Z_VAL_90 = 1.6448536251336989; // p-value .90 + final const Z_VAL_95 = 1.959963986120195; // .95 - public const UPVOTE = 1; - public const DOWNVOTE = 2; + final public const UPVOTE = 1; + final public const DOWNVOTE = 2; protected const VOTE_USER_KEY = 'vote_user_%d'; protected const VOTE_PAIR_KEY = 'vote_pair_%d'; @@ -405,7 +405,6 @@ class Vote extends \Gazelle\BaseUser { if (!isset($this->userVote[$tgroupId])) { return [false, 'not-voted']; } - $up = $this->userVote[$tgroupId] === 1 ? 1 : 0; self::$db->begin_transaction(); self::$db->prepared_query(" diff --git a/app/UserCreator.php b/app/UserCreator.php index f3a14de4f..fb0100974 100644 --- a/app/UserCreator.php +++ b/app/UserCreator.php @@ -227,7 +227,6 @@ class UserCreator extends Base { /** * Set the initial admin comment. Not mandatory for creation - * @param string $adminComment */ public function setAdminComment(string $adminComment) { $this->adminComment[] = trim($adminComment); @@ -240,8 +239,6 @@ class UserCreator extends Base { * the email will be taken from the invitation. (Corollary: if an * invitation was used, calling this method afterwards will override * the invitation email). - * - * @param string $email */ public function setEmail(string $email) { $this->email[] = trim($email); @@ -263,7 +260,6 @@ class UserCreator extends Base { /** * Set the invite key (only required if this is a creation via an invitation) - * @param string $inviteKey */ public function setInviteKey(string $inviteKey) { $this->inviteKey = trim($inviteKey); @@ -272,7 +268,6 @@ class UserCreator extends Base { /** * Set the user IPv4 address. - * @param string $ipaddr */ public function setIpaddr(string $ipaddr) { $this->ipaddr = trim($ipaddr); @@ -281,7 +276,6 @@ class UserCreator extends Base { /** * Set the password. Will be hashed before being stored. - * @param string $password */ public function setPassword(#[\SensitiveParameter] string $password) { $this->passHash = self::hashPassword($password); @@ -290,7 +284,6 @@ class UserCreator extends Base { /** * Set the username. - * @param string $username */ public function setUsername(string $username) { if (preg_match('/^' . str_replace('/', '', USERNAME_REGEXP) . '$/', trim($username), $match)) { diff --git a/app/UserRank.php b/app/UserRank.php index 676db707a..8b432de80 100644 --- a/app/UserRank.php +++ b/app/UserRank.php @@ -48,12 +48,10 @@ namespace Gazelle; */ class UserRank extends Base { - - protected \Gazelle\UserRank\Configuration $config; protected array $rank; protected float $score = 0.0; - const PREFIX = 'percentiles_'; // Prefix for memcache keys, to make life easier + final const PREFIX = 'percentiles_'; // Prefix for memcache keys, to make life easier public function score(): ?int { return is_nan($this->score) ? null : (int)round($this->score, 0); @@ -63,8 +61,7 @@ class UserRank extends Base { return $this->rank[$dimension]; } - public function __construct(\Gazelle\UserRank\Configuration $config, array $dimension) { - $this->config = $config; + public function __construct(protected \Gazelle\UserRank\Configuration $config, array $dimension) { $definition = $this->config->definition(); $dimension['uploaded'] -= STARTING_UPLOAD; diff --git a/app/UserRank/AbstractUserRank.php b/app/UserRank/AbstractUserRank.php index 8165b5469..1bc2f763c 100644 --- a/app/UserRank/AbstractUserRank.php +++ b/app/UserRank/AbstractUserRank.php @@ -10,7 +10,6 @@ namespace Gazelle\UserRank; */ abstract class AbstractUserRank extends \Gazelle\Base { - abstract public function cacheKey(): string; abstract public function selector(): string; @@ -116,7 +115,7 @@ abstract class AbstractUserRank extends \Gazelle\Base { $table = array_reverse($table, true); // add some fuzz to the expiry time, so all the tables don't expire at once - self::$cache->cache_value($this->cacheKey(), $table, 86400 + rand(0, 3600)); + self::$cache->cache_value($this->cacheKey(), $table, 86400 + random_int(0, 3600)); return $table; } diff --git a/app/Util/CacheMultiFlush.php b/app/Util/CacheMultiFlush.php index 33bf7cbb4..929cd63e1 100644 --- a/app/Util/CacheMultiFlush.php +++ b/app/Util/CacheMultiFlush.php @@ -28,7 +28,7 @@ class CacheMultiFlush extends \Gazelle\Base { $list = self::$db->collect(0); $flush = []; foreach ($shape as $s) { - $flush = array_merge($flush, array_map(function ($id) use ($s) {return sprintf($s, $id);}, $list)); + $flush = array_merge($flush, array_map(fn($id) => sprintf($s, $id), $list)); } self::$cache->delete_multi($flush); $flushed += count($flush); diff --git a/app/Util/Dominator.php b/app/Util/Dominator.php index 8c3de4263..ff07123fd 100644 --- a/app/Util/Dominator.php +++ b/app/Util/Dominator.php @@ -20,7 +20,6 @@ class Dominator extends \Gazelle\Base { foreach (self::$click as $id => $code) { $js .= "\$('$id').click(function () {" . "$code});\n"; } - $js .= '})'; - return $js; + return $js . '})'; } } diff --git a/app/Util/ImageProxy.php b/app/Util/ImageProxy.php index 28fbed4e9..da22363ac 100644 --- a/app/Util/ImageProxy.php +++ b/app/Util/ImageProxy.php @@ -17,11 +17,10 @@ class ImageProxy { /** * Checks if a link's host is (not) good, otherwise displays an error. * @param string $url Link to an image - * @return string|null */ public function badHost(string $url): ?string { foreach (IMAGE_HOST_BANNED as $host) { - if (stripos($url, $host) !== false) { + if (stripos($url, (string) $host) !== false) { return $host; } } @@ -35,7 +34,7 @@ class ImageProxy { * @param bool|number $UserID - user ID for avatars and donor icons * @return string */ - public function process($url, $check = false, $UserID = false) { + public function process($url, bool|string $check = false, $UserID = false) { if (empty($url) || !$this->viewer->permitted('site_proxy_images')) { return $url; } diff --git a/app/Util/LastFM.php b/app/Util/LastFM.php index a288a7207..24cd1e955 100644 --- a/app/Util/LastFM.php +++ b/app/Util/LastFM.php @@ -3,7 +3,6 @@ namespace Gazelle\Util; class LastFM extends \Gazelle\Base { - protected const LASTFM_API_URL = 'http://ws.audioscrobbler.com/2.0/?method='; public function artistEventList($ArtistID, $Artist, $Limit = 15) { @@ -23,6 +22,7 @@ class LastFM extends \Gazelle\Base { } public function userInfo(\Gazelle\User $user): ?array { + $Reponse = []; $lastfmName = $this->username($user->id()); if (is_null($lastfmName)) { return null; @@ -145,6 +145,7 @@ class LastFM extends \Gazelle\Base { } protected function fetch(string $Method, array $Args) { + $curl = null; if (!LASTFM_API_KEY) { return false; } @@ -155,18 +156,16 @@ class LastFM extends \Gazelle\Base { return false; } $Url = self::LASTFM_API_URL . $Method; - if (is_array($Args)) { - foreach ($Args as $Key => $Value) { - $Url .= "&$Key=" . urlencode($Value); - } - $Url .= "&format=json&api_key=" . LASTFM_API_KEY; - $curl = new Curl; - if ($curl->fetch($Url)) { - return json_decode($curl->result(), true); - } else { - self::$cache->cache_value($RecentFailsKey, $RecentFails + 1, 1800); - return false; - } + foreach ($Args as $Key => $Value) { + $Url .= "&$Key=" . urlencode($Value); + } + $Url .= "&format=json&api_key=" . LASTFM_API_KEY; + $curl = new Curl; + if ($curl->fetch($Url)) { + return json_decode($curl->result(), true); + } else { + self::$cache->cache_value($RecentFailsKey, $RecentFails + 1, 1800); + return false; } } } diff --git a/app/Util/Mail.php b/app/Util/Mail.php index b212d9a03..79c610f37 100644 --- a/app/Util/Mail.php +++ b/app/Util/Mail.php @@ -14,8 +14,6 @@ class Mail { * Send an email. * * @param string $to Recipient address - * @param string $subject - * @param string $body */ public function send(string $to, string $subject, string $body) { $from = $this->from . '@' . SITE_HOST; diff --git a/app/Util/Proxy.php b/app/Util/Proxy.php index 3e43325a1..17ee97f2d 100644 --- a/app/Util/Proxy.php +++ b/app/Util/Proxy.php @@ -21,9 +21,8 @@ class Proxy { curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']); curl_setopt($curl, CURLOPT_POSTFIELDS, self::urlEncode($data)); $result = curl_exec($curl); - $json = json_decode(Crypto::decrypt(self::urlDecode($result), $this->key), true); - return $json; + return json_decode(Crypto::decrypt(self::urlDecode($result), $this->key), true); } public static function urlEncode($data) { diff --git a/app/Util/SortableTableHeader.php b/app/Util/SortableTableHeader.php index 6a4f07aba..80e72395b 100644 --- a/app/Util/SortableTableHeader.php +++ b/app/Util/SortableTableHeader.php @@ -7,18 +7,12 @@ use Format; class SortableTableHeader { private const SORT_DIRS = ['asc' => 'desc', 'desc' => 'asc', '' => '']; - /** @var array */ - private $labelMap; - /** @var string */ private $currentSortKey; /** @var string */ private $currentSortDir; - /** @var array */ - private $arrowMap; - /** * SortableTableHeader constructor. * Label map array is structured like this example: @@ -36,23 +30,18 @@ class SortableTableHeader { * ] * Items missing a 'text' value cannot be output. * - * @param string $defaultSortKey - * @param array $labelMap * @param array $arrowMap sort direction => symbol to output - * @param array $request */ public function __construct( string $defaultSortKey, - array $labelMap, - array $arrowMap = ['asc' => '↓', 'desc' => '↑', '' => ''], + private readonly array $labelMap, + private readonly array $arrowMap = ['asc' => '↓', 'desc' => '↑', '' => ''], array $request = [] ) { if ($request === []) { // Since we can't have expressions as default values in the param list... $request = $_GET; } - - $this->labelMap = $labelMap; $this->currentSortKey = (!empty($request['order']) && isset($labelMap[$request['order']])) ? $request['order'] : $defaultSortKey; @@ -60,7 +49,6 @@ class SortableTableHeader { (empty($request['sort']) || $request['sort'] === $this->current()['defaultSort']) ? $this->current()['defaultSort'] : self::SORT_DIRS[$this->current()['defaultSort']]; - $this->arrowMap = $arrowMap; } public function emit($outputKey) { diff --git a/app/Util/Text.php b/app/Util/Text.php index 02fe3ef8b..c871533cf 100644 --- a/app/Util/Text.php +++ b/app/Util/Text.php @@ -3,38 +3,6 @@ namespace Gazelle\Util; class Text { - /** - * Determine if the $haystack starts with $needle - * - * @param string $haystack String to search in - * @param string $needle String to search for - * @param boolean $case_insensitive flag to ignore case of the $haystack and $needle - * @return boolean True if $Needle is a prefix of $Haystack - */ - public static function startsWith($haystack, $needle, $case_insensitive = false) { - if($case_insensitive) { - $haystack = strtolower($haystack); - $needle = strtolower($needle); - } - return substr($haystack, 0, strlen($needle)) === $needle; - } - - /** - * Determine if the $haystack ends with $needle - * - * @param string $haystack String to search in - * @param string $needle String to search for - * @param boolean $case_insensitive flag to ignore case of the $haystack and $needle - * @return boolean True if $Needle is a suffix of $Haystack - */ - public static function endsWith($haystack, $needle, $case_insensitive = false) { - if($case_insensitive) { - $haystack = strtolower($haystack); - $needle = strtolower($needle); - } - return ($needle !== null && strlen($needle) === 0) || substr($haystack, -strlen($needle)) === $needle; - } - public static function base64UrlEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } diff --git a/app/Util/Time.php b/app/Util/Time.php index ac5f5e17f..a9c60240b 100644 --- a/app/Util/Time.php +++ b/app/Util/Time.php @@ -8,11 +8,8 @@ class Time { * is an integer, we assume that's the nubmer of seconds you wish to subtract, otherwise * it's a string of a timestamp that we convert to a UNIX timestamp and then do a subtraction. * If the passed in $timestamp does not convert properly or is null, return false (error). - * - * @param string|int $timestamp - * @return false|int */ - public static function timeAgo($timestamp) { + public static function timeAgo(string|int $timestamp): false|int { if ($timestamp === null) { return false; } @@ -51,11 +48,11 @@ class Time { $hideAgo = true; } - $years = floor($time / 31556926); // seconds in one year - $remain = $time - $years * 31556926; + $years = floor($time / 31_556_926); // seconds in one year + $remain = $time - $years * 31_556_926; - $months = floor($remain / 2629744); // seconds in one month - $remain = $remain - $months * 2629744; + $months = floor($remain / 2_629_744); // seconds in one month + $remain = $remain - $months * 2_629_744; $weeks = floor($remain / 604800); // seconds in one week $remain = $remain - $weeks * 604800; @@ -66,10 +63,7 @@ class Time { $hours=floor($remain / 3600); // seconds in one hour $remain = $remain - $hours * 3600; - $minutes = floor($remain / 60); // seconds in one minute - $remain = $remain - $minutes * 60; - - $seconds = $remain; + $minutes = floor($remain / 60); $return = ''; @@ -222,8 +216,6 @@ class Time { /** * Converts a numeric amount of seconds (though we round down via floor for all levels) into a more human readeable * string representing the number of weeks, days, hours, minutes, seconds. - * - * @return string */ public static function convertSeconds(int $seconds): string { if ($seconds <= 0) { @@ -273,11 +265,8 @@ class Time { /** * Utility function to generate a timestamp to insert into the database, given some offset - * - * @param int $offset - * @return false|string */ - public static function offset(int $offset) { + public static function offset(int $offset): false|string { return date('Y-m-d H:i:s', time() + $offset); } @@ -293,12 +282,12 @@ class Time { if (count($date_time) != 2) { return false; } - list($date, $time) = $date_time; + [$date, $time] = $date_time; $split_time = explode(':', $time); if (count($split_time) != 3) { return false; } - list($hour, $minute, $second) = $split_time; + [$hour, $minute, $second] = $split_time; if ($hour != 0 && !(is_number($hour) && $hour < 24 && $hour >= 0)) { return false; } @@ -312,7 +301,7 @@ class Time { if (count($split_date) != 3) { return false; } - list($year, $month, $day) = $split_date; + [$year, $month, $day] = $split_date; return checkDate($month, $day, $year); } diff --git a/app/Util/Twig.php b/app/Util/Twig.php index 97778aeb9..113aaaa8d 100644 --- a/app/Util/Twig.php +++ b/app/Util/Twig.php @@ -18,44 +18,32 @@ class Twig { $twig->addFilter(new \Twig\TwigFilter( 'article', - function ($word) { - return preg_match('/^[aeiou]/i', $word) ? 'an' : 'a'; - } + fn($word) => preg_match('/^[aeiou]/i', $word) ? 'an' : 'a' )); $twig->addFilter(new \Twig\TwigFilter( 'b64', - function (string $binary) { - return base64_encode($binary); - } + fn(string $binary) => base64_encode($binary) )); $twig->addFilter(new \Twig\TwigFilter( 'badge_list', - function (\Gazelle\User $user) { - return (new \Gazelle\User\Privilege($user))->badgeList(); - } + fn(\Gazelle\User $user) => (new \Gazelle\User\Privilege($user))->badgeList() )); $twig->addFilter(new \Twig\TwigFilter( 'bb_format', - function ($text, $outputToc = true) { - return new \Twig\Markup(\Text::full_format($text, $outputToc), 'UTF-8'); - } + fn($text, $outputToc = true) => new \Twig\Markup(\Text::full_format($text, $outputToc), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'checked', - function ($isChecked) { - return new \Twig\Markup($isChecked ? ' checked="checked"' : '', 'UTF-8'); - } + fn($isChecked) => new \Twig\Markup($isChecked ? ' checked="checked"' : '', 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'column', - function (\Gazelle\Util\SortableTableHeader $header, string $name) { - return new \Twig\Markup($header->emit($name), 'UTF-8'); - } + fn(\Gazelle\Util\SortableTableHeader $header, string $name) => new \Twig\Markup($header->emit($name), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( @@ -79,89 +67,65 @@ class Twig { $twig->addFilter(new \Twig\TwigFilter( 'octet_size', - function ($size, array $option = []) { - return \Format::get_size($size, empty($option) ? 2 : $option[0]); - }, + fn($size, array $option = []) => \Format::get_size($size, empty($option) ? 2 : $option[0]), ['is_variadic' => true] )); $twig->addFilter(new \Twig\TwigFilter( 'plural', - function ($number, $plural = 's') { - return plural($number, $plural); - } + fn($number, $plural = 's') => plural($number, $plural) )); $twig->addFilter(new \Twig\TwigFilter( 'repeat', - function ($text, $number) { - return str_repeat($text, $number); - } + fn($text, $number) => str_repeat($text, $number) )); $twig->addFilter(new \Twig\TwigFilter( 'shorten', - function (string $text, int $length) { - return new \Twig\Markup(shortenString($text, $length), 'UTF-8'); - } + fn(string $text, int $length) => new \Twig\Markup(shortenString($text, $length), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'time_diff', - function ($time, $levels = 2) { - return new \Twig\Markup(time_diff($time, $levels), 'UTF-8'); - } + fn($time, $levels = 2) => new \Twig\Markup(time_diff($time, $levels), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'time_interval', - function (int $seconds) { - return new \Twig\Markup(Time::convertSeconds($seconds), 'UTF-8'); - } + fn(int $seconds) => new \Twig\Markup(Time::convertSeconds($seconds), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'token_count', - function ($size) { - return (int)ceil((int)$size / BYTES_PER_FREELEECH_TOKEN); - } + fn($size) => (int)ceil((int)$size / BYTES_PER_FREELEECH_TOKEN) )); $twig->addFilter(new \Twig\TwigFilter( 'truth', - function (bool $truth) { - return $truth ? "\xe2\x9c\x85" : "\xe2\x9d\x8c"; - } + fn(bool $truth) => $truth ? "\xe2\x9c\x85" : "\xe2\x9d\x8c" )); $twig->addFilter(new \Twig\TwigFilter( 'ucfirst', - function ($text) { - return new \Twig\Markup(ucfirst($text), 'UTF-8'); - } + fn($text) => new \Twig\Markup(ucfirst($text), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'ucfirstall', - function ($text) { - return new \Twig\Markup(ucfirst( - implode(' ', array_map(fn($w) => ucfirst($w), explode(' ', $text))) - ), 'UTF-8'); - } + fn($text) => new \Twig\Markup(ucfirst( + implode(' ', array_map(fn($w) => ucfirst($w), explode(' ', $text))) + ), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'user_url', - function ($userId) { - return new \Twig\Markup(\Users::format_username($userId, false, false, false), 'UTF-8'); - } + fn($userId) => new \Twig\Markup(\Users::format_username($userId, false, false, false), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( 'user_full', - function ($userId) { - return new \Twig\Markup(\Users::format_username($userId, true, true, true, true), 'UTF-8'); - } + fn($userId) => new \Twig\Markup(\Users::format_username($userId, true, true, true, true), 'UTF-8') )); $twig->addFilter(new \Twig\TwigFilter( @@ -186,19 +150,15 @@ class Twig { } )); - $twig->addFunction(new \Twig\TwigFunction('header', function ($title, $options = '') { - return new \Twig\Markup( - \View::show_header($title, $options), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('header', fn($title, $options = '') => new \Twig\Markup( + \View::show_header($title, $options), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('footer', function ($options = []) { - return new \Twig\Markup( - \View::show_footer($options), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('footer', fn($options = []) => new \Twig\Markup( + \View::show_footer($options), + 'UTF-8' + ))); $twig->addFunction(new \Twig\TwigFunction('donor_icon', function($icon, $userId) { global $Viewer; @@ -208,104 +168,89 @@ class Twig { ); })); - $twig->addFunction(new \Twig\TwigFunction('ipaddr', function (string $ipaddr) { - return new \Twig\Markup( - "$ipaddr S' - , 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('ipaddr', fn(string $ipaddr) => new \Twig\Markup( + "$ipaddr S' + , 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('mtime', function($filename) { - return new \Twig\Markup( - base_convert(filemtime(SERVER_ROOT . '/public/static/' . $filename), 10, 36), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('mtime', fn($filename) => new \Twig\Markup( + base_convert(filemtime(SERVER_ROOT . '/public/static/' . $filename), 10, 36), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('mtime_css', function($filename) { - return new \Twig\Markup( - base_convert(filemtime(SERVER_ROOT . '/sass/' . preg_replace('/\.css$/', '.scss', $filename)), 10, 36), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('mtime_css', fn($filename) => new \Twig\Markup( + base_convert(filemtime(SERVER_ROOT . '/sass/' . preg_replace('/\.css$/', '.scss', $filename)), 10, 36), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('privilege', function ($default, $config, $key) { - return new \Twig\Markup( - ($default - ? sprintf( - ' ', - "default_$key", (isset($default[$key]) && $default[$key] ? ' checked="checked"' : '') - ) - : '' + $twig->addFunction(new \Twig\TwigFunction('privilege', fn($default, $config, $key) => new \Twig\Markup( + ($default + ? sprintf( + ' ', + "default_$key", (isset($default[$key]) && $default[$key] ? ' checked="checked"' : '') ) - . sprintf( - ' 
', - "perm_$key", $key, (empty($config[$key]) ? '' : ' checked="checked"'), $key, $key, - \Gazelle\Manager\Privilege::privilegeList()[$key] ?? "!unknown($key)!" - ), - 'UTF-8' - ); - })); + : '' + ) + . sprintf( + ' 
', + "perm_$key", $key, (empty($config[$key]) ? '' : ' checked="checked"'), $key, $key, + \Gazelle\Manager\Privilege::privilegeList()[$key] ?? "!unknown($key)!" + ), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('ratio', function ($up, $down) { - return new \Twig\Markup( - \Format::get_ratio_html($up, $down), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('ratio', fn($up, $down) => new \Twig\Markup( + \Format::get_ratio_html($up, $down), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('resolveCountryIpv4', function ($addr) { - return new \Twig\Markup( - (function ($ip) { - static $cache = []; - if (!isset($cache[$ip])) { - $Class = strtr($ip, '.', '-'); - $cache[$ip] = 'Resolving CC...' - . ''; - } - return $cache[$ip]; - })($addr), - 'UTF-8' - ); - })); + . '});' + . ''; + } + return $cache[$ip]; + })($addr), + 'UTF-8' + ))); - $twig->addFunction(new \Twig\TwigFunction('resolveIpv4', function ($addr) { - return new \Twig\Markup( - (function ($ip) { - if (!$ip) { - $ip = '127.0.0.1'; - } - static $cache = []; - if (!isset($cache[$ip])) { - $class = strtr($ip, '.', '-'); - $cache[$ip] = 'Resolving host' . "\xE2\x80\xA6" . '"; - } - return $cache[$ip]; - })($addr), - 'UTF-8' - ); - })); + $twig->addFunction(new \Twig\TwigFunction('resolveIpv4', fn($addr) => new \Twig\Markup( + (function ($ip) { + if (!$ip) { + $ip = '127.0.0.1'; + } + static $cache = []; + if (!isset($cache[$ip])) { + $class = strtr($ip, '.', '-'); + $cache[$ip] = 'Resolving host' . "\xE2\x80\xA6" . '"; + } + return $cache[$ip]; + })($addr), + 'UTF-8' + ))); - $twig->addTest(new \Twig\TwigTest('donor', function ($user) { - return get_class($user) === 'Gazelle\\User' && (new \Gazelle\User\Privilege($user))->isDonor(); - })); + $twig->addFunction(new \Twig\TwigFunction('shorten', fn($text, $length) => new \Twig\Markup( + shortenString($text, $length), + 'UTF-8' + ))); - $twig->addTest(new \Twig\TwigTest('nan', function ($value) { - return is_nan($value); - })); + $twig->addTest(new \Twig\TwigTest('donor', fn($user) => $user::class === \Gazelle\User::class && (new \Gazelle\User\Privilege($user))->isDonor())); - $twig->addTest(new \Twig\TwigTest('request_fill', function ($contest) { - return $contest instanceof \Gazelle\Contest\RequestFill; - })); + $twig->addTest(new \Twig\TwigTest('nan', fn($value) => is_nan($value))); + + $twig->addTest(new \Twig\TwigTest('request_fill', fn($contest) => $contest instanceof \Gazelle\Contest\RequestFill)); $twig->addGlobal('dom', new \Gazelle\Util\Dominator); diff --git a/app/Wiki.php b/app/Wiki.php index affc8d831..e029dd57b 100644 --- a/app/Wiki.php +++ b/app/Wiki.php @@ -57,8 +57,6 @@ class Wiki extends BaseObject { /** * Normalize an alias - * @param string $alias - * @return string */ static public function normalizeAlias(string $alias): string { return trim(substr(preg_replace('/[^a-z0-9]/', '', strtolower(htmlentities(trim($alias)))), 0, 50)); diff --git a/lib/rector.php b/lib/rector.php index 7b4f2fb21..315f5dd8f 100644 --- a/lib/rector.php +++ b/lib/rector.php @@ -13,8 +13,8 @@ use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ - // __DIR__ . '/../app', - __DIR__ . '/../classes', + __DIR__ . '/../app', + // __DIR__ . '/../classes', // __DIR__ . '/../lib', // __DIR__ . '/../sections', ]); diff --git a/package.json b/package.json index be630dbb3..240f97630 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "lint-staged": { "*.php": [ ".bin/phpcbf", - "vendor/bin/phpstan analyse --memory-limit 256M", + "vendor/bin/phpstan analyse --memory-limit 512M", ".bin/phpcs" ] }, diff --git a/phpstan.neon b/phpstan.neon index 5d1f792c1..df09767e5 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -15,6 +15,7 @@ parameters: - classes - db - scripts + - tests excludePaths: - sections parallel: diff --git a/sections/apply/apply.php b/sections/apply/apply.php index 4c7d66538..e06a7d06a 100644 --- a/sections/apply/apply.php +++ b/sections/apply/apply.php @@ -10,7 +10,7 @@ if (isset($_POST['auth'])) { $error = "You need to explain things a bit more."; } else { header('Location: /apply.php?action=view&id=' - . $appMan->createApplicant($Viewer->id(), $roleId, $body)->id()); + . $appMan->create($Viewer->id(), $roleId, $body)->id()); exit; } } diff --git a/sections/artist/artist.php b/sections/artist/artist.php index bd64889ed..6ad058d41 100644 --- a/sections/artist/artist.php +++ b/sections/artist/artist.php @@ -126,7 +126,6 @@ if ($tagLeaderboard) { groupIds()) > 1000) { // prevent OOMs - $Cache->disableLocalCache(); $DB->disableQueryLog(); } $artistReleaseType = []; diff --git a/sections/upload/upload_handle.php b/sections/upload/upload_handle.php index 892f387fa..7f5aba6b5 100644 --- a/sections/upload/upload_handle.php +++ b/sections/upload/upload_handle.php @@ -530,14 +530,8 @@ $LogName .= $Properties['Title']; $Debug->set_flag('upload: database begin transaction'); $DB->begin_transaction(); -if (!$IsNewGroup) { - $DB->prepared_query(' - UPDATE torrents_group SET - Time = now() - WHERE ID = ? - ', $Properties['GroupID'] - ); - $tgroup = $tgMan->findById($Properties['GroupID']); +if ($tgroup) { + $tgroup->touch(); } else { $tgroup = $tgMan->create( categoryId: $categoryId, @@ -824,7 +818,7 @@ if (defined('AJAX')) { ->addUser($Viewer) ->setDebug(DEBUG_UPLOAD_NOTIFICATION); - if (isset($releaseTypes[$Properties['ReleaseType']])) { + if ($isMusicUpload) { $notification->addReleaseType($releaseTypes[$Properties['ReleaseType']]); } diff --git a/tests/phpunit/ApplicantTest.php b/tests/phpunit/ApplicantTest.php new file mode 100644 index 000000000..6066f1825 --- /dev/null +++ b/tests/phpunit/ApplicantTest.php @@ -0,0 +1,38 @@ +roleManager = new \Gazelle\Manager\ApplicantRole; + $this->manager = new \Gazelle\Manager\Applicant; + } + + public function tearDown(): void {} + + public function testApplicant() { + $this->assertIsArray($this->roleManager->list(), 'role-manager-list-published-is-array'); + $new = $this->manager->newApplicantCount(); + $admin = (new Gazelle\Manager\User)->find('@admin'); + $user = (new Gazelle\Manager\User)->find('@user'); + + $role = 'published-' . randomString(6); + $published = $this->roleManager->create($role, 'this is a published role', true, 1); + $this->assertInstanceOf('\\Gazelle\\ApplicantRole', $published, 'applicant-role-instance'); + + $unpublished = $this->roleManager->create('unpublished-' . randomString(6), 'this is an unpublished role', false, $admin->id()); + + + $this->assertEquals($role, $this->roleManager->title($published->id()), 'role-manager-title'); + + $apply = $this->manager->create($user->id(), $published->id(), 'application message'); + $this->assertInstanceOf('\\Gazelle\\Applicant', $apply, 'applicant-instance'); + $this->assertTrue($this->manager->userIsApplicant($user->id()), 'applicant-user-applied'); + $this->assertEquals($new + 1, $this->manager->newApplicantCount(), 'applicant-new-count'); + } +} diff --git a/tests/phpunit/Util/TextTest.php b/tests/phpunit/Util/TextTest.php deleted file mode 100644 index 41a304597..000000000 --- a/tests/phpunit/Util/TextTest.php +++ /dev/null @@ -1,65 +0,0 @@ -assertEquals($expected, Text::startsWith($string, $substr, $case_insensitive)); - } - - public function providerStartsWith() { - return [ - ['arrow', '', false, true], - ['arrow', 'arrow', false, true], - ['arrow', 'a', false, true], - ['arrow', 'f', false, false], - [null, null, false, false], - [null, 't', false, false], - ['arrow', null, false, false], - ['Arrow', 'arr', false, false], - ['Arrow', 'a', true, true], - ['Arrow', 'arrow', true, true], - [null, null, true, true], - [null, '', true, true] - ]; - } - - /** - * @param $string - * @param $substr - * @param $case_insensitive - * @param $expected - * - * @dataProvider providerEndsWith - */ - public function testEndsWith($string, $substr, $case_insensitive, $expected) { - $this->assertEquals($expected, Text::endsWith($string, $substr, $case_insensitive)); - } - - public function providerEndsWith() { - return [ - ['arrow', '', false, true], - ['arrow', 'arrow', false, true], - ['arrow', 'w', false, true], - ['arrow', 'p', false, false], - [null, null, false, false], - [null, 't', false, false], - ['arrow', null, false, false], - ['Arrow', 'roW', false, false], - ['ArroW', 'w', true, true], - ['ArroW', 'arrow', true, true], - [null, null, true, true], - [null, '', true, true] - ]; - } -}