fix(astrolabe): resolve Psalm type errors in PDF preview code

Fix Psalm static analysis errors:
- Add return type annotations to refresh callback closures
- Use strict null comparisons instead of truthy/falsy checks
- Cast response body to string for json_decode
- Add type annotation for decoded JSON data
- Update psalm-baseline.xml to remove fixed issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-01-26 20:19:23 +01:00
parent d5544a7731
commit c09ebe99cc
3 changed files with 26 additions and 36 deletions
+24 -18
View File
@@ -152,10 +152,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback that calls IdP directly
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -168,7 +169,7 @@ class ApiController extends Controller {
// Get user's OAuth token for MCP server with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required. Please authorize the app first.'
@@ -417,10 +418,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -433,7 +435,7 @@ class ApiController extends Controller {
// Get access token with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required'
@@ -529,10 +531,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -545,7 +548,7 @@ class ApiController extends Controller {
// Get access token with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required'
@@ -628,10 +631,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -644,7 +648,7 @@ class ApiController extends Controller {
// Get access token with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required'
@@ -757,10 +761,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -773,7 +778,7 @@ class ApiController extends Controller {
// Get user's OAuth token for MCP server with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required.'
@@ -814,10 +819,11 @@ class ApiController extends Controller {
$userId = $user->getUID();
// Create refresh callback
$refreshCallback = function (string $refreshToken) {
/** @return array{access_token: string, refresh_token: string, expires_in: int}|null */
$refreshCallback = function (string $refreshToken): ?array {
$newTokenData = $this->tokenRefresher->refreshAccessToken($refreshToken);
if (!$newTokenData) {
if ($newTokenData === null) {
return null;
}
@@ -830,7 +836,7 @@ class ApiController extends Controller {
// Get user's OAuth token for MCP server with automatic refresh
$accessToken = $this->tokenStorage->getAccessToken($userId, $refreshCallback);
if (!$accessToken) {
if ($accessToken === null) {
return new JSONResponse([
'success' => false,
'error' => 'MCP server authorization required.'
+2 -1
View File
@@ -646,7 +646,8 @@ class McpServerClient {
]
]
);
$data = json_decode($response->getBody(), true);
/** @var array{success?: bool, image?: string, page_number?: int, total_pages?: int, error?: string} $data */
$data = json_decode((string)$response->getBody(), true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \RuntimeException('Invalid JSON response from server');
-17
View File
@@ -13,13 +13,6 @@
<code><![CDATA[$result['query_coords']]]></code>
<code><![CDATA[$webhook['eventFilter']]]></code>
</InvalidArrayOffset>
<MissingClosureReturnType>
<code><![CDATA[function (string $refreshToken) {]]></code>
<code><![CDATA[function (string $refreshToken) {]]></code>
<code><![CDATA[function (string $refreshToken) {]]></code>
<code><![CDATA[function (string $refreshToken) {]]></code>
<code><![CDATA[function (string $refreshToken) {]]></code>
</MissingClosureReturnType>
<MixedArgument>
<code><![CDATA[!empty($eventConfig['filter']) ? $eventConfig['filter'] : null]]></code>
<code><![CDATA[$accessToken]]></code>
@@ -62,16 +55,6 @@
<code><![CDATA[$webhook['id']]]></code>
</PossiblyUndefinedArrayOffset>
<RiskyTruthyFalsyComparison>
<code><![CDATA[!$accessToken]]></code>
<code><![CDATA[!$accessToken]]></code>
<code><![CDATA[!$accessToken]]></code>
<code><![CDATA[!$accessToken]]></code>
<code><![CDATA[!$accessToken]]></code>
<code><![CDATA[!$newTokenData]]></code>
<code><![CDATA[!$newTokenData]]></code>
<code><![CDATA[!$newTokenData]]></code>
<code><![CDATA[!$newTokenData]]></code>
<code><![CDATA[!$newTokenData]]></code>
<code><![CDATA[!$token]]></code>
<code><![CDATA[empty($webhook['eventFilter'])]]></code>
</RiskyTruthyFalsyComparison>