Files
RomhackPlaza/app/Services/XenforoService.php

213 lines
5.8 KiB
PHP
Raw Normal View History

2026-05-20 18:25:15 +02:00
<?php
namespace App\Services;
use App\Auth\XenForoUser;
use App\XenForoDataTypes\XenForoUserGroup;
2026-05-20 18:25:15 +02:00
use Illuminate\Support\Facades\Cache;
2026-05-25 12:23:10 +02:00
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Str;
2026-05-20 18:25:15 +02:00
class XenforoService {
private const array PERMISSIONS_KEPT = [ 'general', 'romhackplaza' ];
private const int TTL_PERMISSIONS = 300;
private const int TTL_ROUTES = 86400;
2026-05-20 18:25:15 +02:00
/**
* Get specific XenForo user.
*
* @param int $xfUserId
*
* @return XenForoUser|null
*/
public function getXfUser( int $xfUserId ): ?XenForoUser {
$xfUser = \DB::connection('xenforo')
->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
*/
2026-05-20 18:25:15 +02:00
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
*/
2026-05-20 18:25:15 +02:00
public function clearUserData(int $userId): void
{
Cache::forget("xf_permissions_{$userId}");
}
/**
*
*
* @param string $routeName <prefix>.<secname>
*
* @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;
}
2026-05-25 12:23:10 +02:00
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);
}
2026-05-20 18:25:15 +02:00
}