table('user') ->where('user_id', $xfUserId) ->first(); if(!$xfUser) return null; return new XenForoUser($xfUser); } /** * Get specific XenForo user group. * * @param int $xfUserGroupId * * @return XenForoUserGroup|null */ public function getXfUserGroup( int $xfUserGroupId ): ?XenForoUserGroup { $xfUserGroup = \DB::connection('xenforo') ->table('user_group') ->where('user_group_id', $xfUserGroupId) ->first(); if(!$xfUserGroup) return null; return new XenForoUserGroup($xfUserGroup); } /** * Get permissions for a specific user ID. * * @param int $userId * @param int $permissionCombinationId * * @return array */ public function getPermissions(int $userId, int $permissionCombinationId): array { return Cache::remember("xf_permissions_{$userId}", self::TTL_PERMISSIONS, function() use($permissionCombinationId) { $row = \DB::connection('xenforo') ->table('permission_combination') ->where('permission_combination_id', $permissionCombinationId) ->value('cache_value'); if( !$row ) return []; $data = json_decode($row, true); $data = array_intersect_key($data, array_flip(self::PERMISSIONS_KEPT)); return $data ?: []; }); } /** * Clear user data. * * @param int $userId * * @return void */ public function clearUserData(int $userId): void { Cache::forget("xf_permissions_{$userId}"); } /** * * * @param string $routeName . * * @return string */ public function getRoute( string $routeName, array $arguments ): string { $routes = Cache::remember("xf_routes", self::TTL_ROUTES, function(){ return \DB::connection('xenforo') ->table('route') ->where('route_type', 'public' ) ->get(['route_prefix', 'sub_name', 'format']) ->map(fn($r) => (array) $r ) ->toArray(); }); $baseUrl = config('app.forum_url'); try { [$prefix, $subName] = explode('.', $routeName, 2); $route = collect($routes)->first(function ($r) use ($prefix, $subName) { return $r['route_prefix'] === $prefix && $r['sub_name'] === $subName; }); if( !$route ) return $baseUrl . '/' . $prefix; $path = $this->buildRoutePath((array)$route, $arguments); return rtrim($baseUrl, '/') . '/' . $path; } catch (\Throwable $th) { $prefix = $routeName; $route = collect($routes)->first(function ($r) use ($prefix) { return $r['route_prefix'] === $prefix; }); if( !$route ) return $baseUrl . '/' . $prefix; $path = $this->buildRoutePath((array)$route, $arguments); return rtrim($baseUrl, '/') . '/' . $path; } } private function buildRoutePath(array $route, array $arguments): string { $prefix = $route['route_prefix']; $format = $route['format']; $subName = $route['sub_name']; if (!$format) { return $subName ? $prefix . '-/' . $subName : $prefix; } if (str_starts_with($format, '-/')) { return $prefix . $format; } $built = preg_replace_callback( '/:\+?(\w+)(?:_\w+)?(?:<([^>]+)>)?/', function(array $m) use ($arguments): string { $type = $m[1]; $keys = isset($m[2]) ? explode(',', $m[2]) : []; return match(true) { $type === 'page' => isset($params['page']) && $params['page'] > 1 ? 'page-' . $params['page'] : '', $type === 'str_int' && count($keys) >= 2 => implode('.', array_filter([ $params[$keys[0]] ?? null, $params[$keys[1]] ?? null, ])), $type === 'int' && count($keys) >= 1 => (string) ($params[$keys[0]] ?? ''), in_array($type, ['str', 'any']) && count($keys) >= 1 => (string) ($params[$keys[0]] ?? ''), default => isset($params[$type]) ? (string) $params[$type] : '', }; }, $format ); $built = preg_replace('/\/+/', '/', $prefix . '/' . $built); $built = rtrim($built, '/'); return $built; } private function hashCSRFToken( string $token ): string { return hash_hmac('md5', $token . time(), config('app.xf_salt') ); } public function getCSRFToken(): string { $token = Cookie::get('xf_csrf'); if( !$token ){ $token = Str::random(16); Cookie::queue('xf_csrf', $token, 0, '/', config('session.domain'), 0, false, false ); } return time() . ',' . $this->hashCSRFToken($token); } }