['min_range'=>1]]); if($page===false)throw new AppException('Choose a valid page.');return $page; } public static function rows(PDO $db,string $sql,array $args,?int $page,string $scope): array { if($page!==null){ $stmt=$db->prepare('SELECT COUNT(*) FROM ('.$sql.') scoped_rows');$stmt->execute($args);$count=(int)$stmt->fetchColumn(); $paging=Pagination::calculate($count,25,$page);self::$pages[$scope]=$paging+['count'=>$count,'pages'=>max(1,(int)ceil($count/25))]; $sql.=' LIMIT '.$paging['size'].' OFFSET '.$paging['offset']; } if($page===null&&self::$exporting)$sql.=' LIMIT '.(self::exportLimit()+1); $stmt=$db->prepare($sql);$stmt->execute($args);$rows=$stmt->fetchAll(); if(self::$exporting&&count($rows)>self::exportLimit())throw new AppException('This export exceeds the configured row limit.',422); return $rows; } public static function navigation(string $scope,?string $action=null): string { $p=self::$pages[$scope]??null;if(!$p)return ''; $h=static fn($v)=>htmlspecialchars((string)$v,ENT_QUOTES,'UTF-8');$html=''; } public static function exportLimit(): int { $value=getenv('HCR_EXPORT_MAX_ROWS');$limit=$value===false?1000:filter_var($value,FILTER_VALIDATE_INT,['options'=>['min_range'=>1,'max_range'=>5000]]); if($limit===false)throw new RuntimeException('Invalid export row limit.');return $limit; } public static function exportGuard(PDO $db,string $sql,array $args): void { $stmt=$db->prepare($sql);$stmt->execute($args); if((int)$stmt->fetchColumn()>self::exportLimit())throw new AppException('This export exceeds the configured row limit. Contact support for a large export.',422); } }