cache = new DbStatementCache($dbConn); } public function getUploads( ?bool $deleted = null, ?bool $expired = null, ?bool $dmca = null ): array { $hasDeleted = $deleted !== null; $hasExpired = $expired !== null; $hasDMCA = $dmca !== null; $args = 0; $query = 'SELECT upload_id, user_id, app_id, LOWER(HEX(upload_hash)), INET6_NTOA(upload_ip), UNIX_TIMESTAMP(upload_created), UNIX_TIMESTAMP(upload_accessed), UNIX_TIMESTAMP(upload_expires), UNIX_TIMESTAMP(upload_deleted), UNIX_TIMESTAMP(upload_dmca), upload_bump, upload_name, upload_type, upload_size FROM prm_uploads'; if($hasDeleted) { ++$args; $query .= sprintf(' WHERE upload_deleted %s NULL', $deleted ? 'IS NOT' : 'IS'); } if($hasExpired) $query .= sprintf(' %s upload_expires %s NOW()', ++$args > 1 ? 'AND' : 'WHERE', $expired ? '<=' : '>'); if($hasDMCA) $query .= sprintf(' %s upload_dmca %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $dmca ? 'IS NOT' : 'IS'); $stmt = $this->cache->get($query); $stmt->execute(); $result = $stmt->getResult(); $uploads = []; while($result->next()) $uploads[] = new UploadInfo($result); return $uploads; } public function getUpload( ?string $uploadId = null, ?string $hashString = null, AppInfo|string|null $appInfo = null, UserInfo|string|null $userInfo = null, ): ?UploadInfo { $hasUploadId = $uploadId !== null; $hasHashString = $hashString !== null; $hasAppInfo = $appInfo !== null; $hasUserInfo = $userInfo !== null; $args = 0; $query = 'SELECT upload_id, user_id, app_id, LOWER(HEX(upload_hash)), INET6_NTOA(upload_ip), UNIX_TIMESTAMP(upload_created), UNIX_TIMESTAMP(upload_accessed), UNIX_TIMESTAMP(upload_expires), UNIX_TIMESTAMP(upload_deleted), UNIX_TIMESTAMP(upload_dmca), upload_bump, upload_name, upload_type, upload_size FROM prm_uploads'; if($hasUploadId) { ++$args; $query .= ' WHERE upload_id = ?'; } if($hasHashString) $query .= sprintf(' %s upload_hash = UNHEX(?)', ++$args > 1 ? 'AND' : 'WHERE'); if($hasAppInfo) $query .= sprintf(' %s app_id = ?', ++$args > 1 ? 'AND' : 'WHERE'); if($hasUserInfo) $query .= sprintf(' %s user_id = ?', ++$args > 1 ? 'AND' : 'WHERE'); $args = 0; $stmt = $this->cache->get($query); if($hasUploadId) $stmt->addParameter(++$args, $uploadId); if($hasHashString) $stmt->addParameter(++$args, $hashString); if($hasAppInfo) $stmt->addParameter(++$args, $appInfo instanceof AppInfo ? $appInfo->getId() : $appInfo); if($hasUserInfo) $stmt->addParameter(++$args, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo); $stmt->execute(); $result = $stmt->getResult(); return $result->next() ? new UploadInfo($result) : null; } public function createUpload( AppInfo|string $appInfo, UserInfo|string $userInfo, string $remoteAddr, string $fileName, string $fileType, int $fileSize, string $fileHash, int $fileExpiry, bool $bumpExpiry ): UploadInfo { if(strpos($fileType, '/') === false) throw new InvalidArgumentException('$fileType must contain a /'); if($fileSize < 1) throw new InvalidArgumentException('$fileSize must be more than 0.'); if(strlen($fileHash) !== 64) throw new InvalidArgumentException('$fileHash must be 64 characters.'); if($fileExpiry < 0) throw new InvalidArgumentException('$fileExpiry must be a positive integer.'); $uploadId = XString::random(32); $stmt = $this->cache->get('INSERT INTO prm_uploads (upload_id, app_id, user_id, upload_name, upload_type, upload_size, upload_hash, upload_ip, upload_expires, upload_bump) VALUES (?, ?, ?, ?, ?, ?, UNHEX(?), INET6_ATON(?), FROM_UNIXTIME(?), ?)'); $stmt->addParameter(1, $uploadId); $stmt->addParameter(2, $appInfo instanceof AppInfo ? $appInfo->getId() : $appInfo); $stmt->addParameter(3, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo); $stmt->addParameter(4, $fileName); $stmt->addParameter(5, $fileType); $stmt->addParameter(6, $fileSize); $stmt->addParameter(7, $fileHash); $stmt->addParameter(8, $remoteAddr); $stmt->addParameter(9, $fileExpiry > 0 ? (time() + $fileExpiry) : 0); $stmt->addParameter(10, $bumpExpiry ? $fileExpiry : 0); $stmt->execute(); return $this->getUpload(uploadId: $uploadId); } public function bumpUploadAccess(UploadInfo $uploadInfo): void { $stmt = $this->cache->get('UPDATE prm_uploads SET upload_accessed = NOW() WHERE upload_id = ?'); $stmt->addParameter(1, $uploadInfo->getId()); $stmt->execute(); } public function bumpUploadExpires(UploadInfo|string $uploadInfo): void { if(!$uploadInfo->hasExpiryTime()) return; $bumpAmount = $uploadInfo->getBumpAmount(); if($bumpAmount < 1) return; $stmt = $this->cache->get('UPDATE prm_uploads SET upload_expires = NOW() + INTERVAL ? SECOND WHERE upload_id = ?'); $stmt->addParameter(1, $bumpAmount); $stmt->addParameter(2, $uploadInfo->getId()); $stmt->execute(); } public function restoreUpload(UploadInfo|string $uploadInfo): void { $stmt = $this->cache->get('UPDATE prm_uploads SET upload_deleted = NULL WHERE upload_id = ?'); $stmt->addParameter(1, $uploadInfo instanceof UploadInfo ? $uploadInfo->getId() : $uploadInfo); $stmt->execute(); } public function deleteUpload(UploadInfo|string $uploadInfo): void { $stmt = $this->cache->get('UPDATE prm_uploads SET upload_deleted = COALESCE(upload_deleted, NOW()) WHERE upload_id = ?'); $stmt->addParameter(1, $uploadInfo instanceof UploadInfo ? $uploadInfo->getId() : $uploadInfo); $stmt->execute(); } public function nukeUpload(UploadInfo|string $uploadInfo): void { $stmt = $this->cache->get('DELETE FROM prm_uploads WHERE upload_id = ? AND upload_dmca IS NULL'); $stmt->addParameter(1, $uploadInfo instanceof UploadInfo ? $uploadInfo->getId() : $uploadInfo); $stmt->execute(); } }