feat(06-sonarqube-quality): reduce return statements to ≤3 (S1142 fix)
Extract validation helpers in AllegroIntegrationController: - validateSaveInput(): ?string (save: 6→3 returns) - validateImportSettingsInput(): ?string (saveImportSettings: 5→3 returns) - validateOAuthCallbackParams(): ?string (oauthCallback: 4→3 returns) Extract validation helpers in ShopproIntegrationsController: - validateSaveAccess(): ?Response (save: 9→3 returns) - validateSaveInput(): ?string (save field validation) - validateCsrfAndIntegrationAccess(): ?Response (saveStatusMappings/syncStatuses: 4→3 returns) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -124,27 +124,14 @@ final class AllegroIntegrationController
|
||||
}
|
||||
|
||||
$environment = trim((string) $request->input('environment', 'sandbox'));
|
||||
if (!in_array($environment, ['sandbox', 'production'], true)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.environment_invalid'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$clientId = trim((string) $request->input('client_id', ''));
|
||||
if ($clientId !== '' && mb_strlen($clientId) > 128) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.client_id_too_long'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$redirectUriInput = trim((string) $request->input('redirect_uri', ''));
|
||||
$redirectUri = $redirectUriInput !== '' ? $redirectUriInput : $this->defaultRedirectUri();
|
||||
if (!$this->isValidHttpUrl($redirectUri)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.redirect_uri_invalid'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$ordersFetchStartDate = trim((string) $request->input('orders_fetch_start_date', ''));
|
||||
if ($ordersFetchStartDate !== '' && !$this->isValidDate($ordersFetchStartDate)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.orders_fetch_start_date_invalid'));
|
||||
|
||||
$validationError = $this->validateSaveInput($environment, $clientId, $redirectUri, $ordersFetchStartDate);
|
||||
if ($validationError !== null) {
|
||||
Flash::set('settings_error', $validationError);
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
@@ -178,27 +165,27 @@ final class AllegroIntegrationController
|
||||
|
||||
$intervalMinutesRaw = (int) $request->input('orders_import_interval_minutes', 5);
|
||||
$intervalMinutes = max(1, min(1440, $intervalMinutesRaw));
|
||||
if ($intervalMinutesRaw !== $intervalMinutes) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.orders_import_interval_invalid'));
|
||||
return Response::redirect(RedirectPaths::ALLEGRO_SETTINGS_TAB);
|
||||
}
|
||||
|
||||
$statusSyncDirection = trim((string) $request->input(
|
||||
'status_sync_direction',
|
||||
self::STATUS_SYNC_DIRECTION_ALLEGRO_TO_ORDERPRO
|
||||
));
|
||||
if (!in_array($statusSyncDirection, $this->allowedStatusSyncDirections(), true)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.status_sync_direction_invalid'));
|
||||
return Response::redirect(RedirectPaths::ALLEGRO_SETTINGS_TAB);
|
||||
}
|
||||
|
||||
$statusSyncIntervalRaw = (int) $request->input(
|
||||
'status_sync_interval_minutes',
|
||||
self::STATUS_SYNC_DEFAULT_INTERVAL_MINUTES
|
||||
);
|
||||
$statusSyncInterval = max(1, min(1440, $statusSyncIntervalRaw));
|
||||
if ($statusSyncIntervalRaw !== $statusSyncInterval) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.validation.status_sync_interval_invalid'));
|
||||
|
||||
$validationError = $this->validateImportSettingsInput(
|
||||
$intervalMinutesRaw,
|
||||
$intervalMinutes,
|
||||
$statusSyncDirection,
|
||||
$statusSyncIntervalRaw,
|
||||
$statusSyncInterval
|
||||
);
|
||||
if ($validationError !== null) {
|
||||
Flash::set('settings_error', $validationError);
|
||||
return Response::redirect(RedirectPaths::ALLEGRO_SETTINGS_TAB);
|
||||
}
|
||||
|
||||
@@ -419,14 +406,11 @@ final class AllegroIntegrationController
|
||||
$state = trim((string) $request->input('state', ''));
|
||||
$expectedState = trim((string) ($_SESSION[self::OAUTH_STATE_SESSION_KEY] ?? ''));
|
||||
unset($_SESSION[self::OAUTH_STATE_SESSION_KEY]);
|
||||
if ($state === '' || $expectedState === '' || !hash_equals($expectedState, $state)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.flash.oauth_state_invalid'));
|
||||
return Response::redirect(RedirectPaths::ALLEGRO_INTEGRATION);
|
||||
}
|
||||
|
||||
$authorizationCode = trim((string) $request->input('code', ''));
|
||||
if ($authorizationCode === '') {
|
||||
Flash::set('settings_error', $this->translator->get('settings.allegro.flash.oauth_code_missing'));
|
||||
|
||||
$validationError = $this->validateOAuthCallbackParams($state, $expectedState, $authorizationCode);
|
||||
if ($validationError !== null) {
|
||||
Flash::set('settings_error', $validationError);
|
||||
return Response::redirect(RedirectPaths::ALLEGRO_INTEGRATION);
|
||||
}
|
||||
|
||||
@@ -896,6 +880,60 @@ final class AllegroIntegrationController
|
||||
];
|
||||
}
|
||||
|
||||
private function validateSaveInput(
|
||||
string $environment,
|
||||
string $clientId,
|
||||
string $redirectUri,
|
||||
string $ordersFetchStartDate
|
||||
): ?string {
|
||||
if (!in_array($environment, ['sandbox', 'production'], true)) {
|
||||
return $this->translator->get('settings.allegro.validation.environment_invalid');
|
||||
}
|
||||
if ($clientId !== '' && mb_strlen($clientId) > 128) {
|
||||
return $this->translator->get('settings.allegro.validation.client_id_too_long');
|
||||
}
|
||||
if (!$this->isValidHttpUrl($redirectUri)) {
|
||||
return $this->translator->get('settings.allegro.validation.redirect_uri_invalid');
|
||||
}
|
||||
if ($ordersFetchStartDate !== '' && !$this->isValidDate($ordersFetchStartDate)) {
|
||||
return $this->translator->get('settings.allegro.validation.orders_fetch_start_date_invalid');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function validateImportSettingsInput(
|
||||
int $intervalMinutesRaw,
|
||||
int $intervalMinutes,
|
||||
string $statusSyncDirection,
|
||||
int $statusSyncIntervalRaw,
|
||||
int $statusSyncInterval
|
||||
): ?string {
|
||||
if ($intervalMinutesRaw !== $intervalMinutes) {
|
||||
return $this->translator->get('settings.allegro.validation.orders_import_interval_invalid');
|
||||
}
|
||||
if (!in_array($statusSyncDirection, $this->allowedStatusSyncDirections(), true)) {
|
||||
return $this->translator->get('settings.allegro.validation.status_sync_direction_invalid');
|
||||
}
|
||||
if ($statusSyncIntervalRaw !== $statusSyncInterval) {
|
||||
return $this->translator->get('settings.allegro.validation.status_sync_interval_invalid');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function validateOAuthCallbackParams(
|
||||
string $state,
|
||||
string $expectedState,
|
||||
string $authorizationCode
|
||||
): ?string {
|
||||
if ($state === '' || $expectedState === '' || !hash_equals($expectedState, $state)) {
|
||||
return $this->translator->get('settings.allegro.flash.oauth_state_invalid');
|
||||
}
|
||||
if ($authorizationCode === '') {
|
||||
return $this->translator->get('settings.allegro.flash.oauth_code_missing');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function ensureDefaultSchedulesExist(): void
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -118,44 +118,21 @@ final class ShopproIntegrationsController
|
||||
$redirectBase = RedirectPaths::SHOPPRO_INTEGRATION;
|
||||
$redirectTo = $this->buildRedirectUrl($integrationId, $tab);
|
||||
|
||||
if (!Csrf::validate((string) $request->input('_token', ''))) {
|
||||
Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$existing = $integrationId > 0 ? $this->repository->findIntegration($integrationId) : null;
|
||||
if ($integrationId > 0 && $existing === null) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.not_found'));
|
||||
return Response::redirect($this->buildRedirectUrl(0, $tab));
|
||||
$accessError = $this->validateSaveAccess((string) $request->input('_token', ''), $integrationId, $existing, $tab);
|
||||
if ($accessError !== null) {
|
||||
return $accessError;
|
||||
}
|
||||
|
||||
$name = trim((string) $request->input('name', ''));
|
||||
if (mb_strlen($name) < 2) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.validation.name_min'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$baseUrl = rtrim(trim((string) $request->input('base_url', '')), '/');
|
||||
if (!$this->isValidHttpUrl($baseUrl)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.validation.base_url_invalid'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$apiKey = trim((string) $request->input('api_key', ''));
|
||||
$hasExistingApiKey = (bool) ($existing['has_api_key'] ?? false);
|
||||
if ($tab === 'integration' && $apiKey === '' && !$hasExistingApiKey) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.validation.api_key_required'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
$ordersFetchStartDate = trim((string) $request->input('orders_fetch_start_date', ''));
|
||||
if ($ordersFetchStartDate !== '' && !$this->isValidYmdDate($ordersFetchStartDate)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.validation.orders_fetch_start_date_invalid'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
if ($this->isDuplicateName($integrationId, $name)) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.validation.name_taken'));
|
||||
$validationError = $this->validateSaveInput($name, $baseUrl, $apiKey, $hasExistingApiKey, $tab, $ordersFetchStartDate, $integrationId);
|
||||
if ($validationError !== null) {
|
||||
Flash::set('settings_error', $validationError);
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
@@ -193,12 +170,12 @@ final class ShopproIntegrationsController
|
||||
? 'settings.integrations.flash.updated'
|
||||
: 'settings.integrations.flash.created';
|
||||
Flash::set('settings_success', $this->translator->get($flashKey));
|
||||
|
||||
return Response::redirect($this->buildRedirectUrl($savedId, $tab));
|
||||
$redirectTo = $this->buildRedirectUrl($savedId, $tab);
|
||||
} catch (Throwable) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.failed'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
public function test(Request $request): Response
|
||||
@@ -242,14 +219,9 @@ final class ShopproIntegrationsController
|
||||
$integrationId = max(0, (int) $request->input('integration_id', 0));
|
||||
$redirectTo = $this->buildRedirectUrl($integrationId, 'statuses');
|
||||
|
||||
if (!Csrf::validate((string) $request->input('_token', ''))) {
|
||||
Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
if ($integrationId <= 0 || $this->repository->findIntegration($integrationId) === null) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.not_found'));
|
||||
return Response::redirect($this->buildRedirectUrl(0, 'statuses'));
|
||||
$accessError = $this->validateCsrfAndIntegrationAccess((string) $request->input('_token', ''), $integrationId, 'statuses');
|
||||
if ($accessError !== null) {
|
||||
return $accessError;
|
||||
}
|
||||
|
||||
$shopCodes = $request->input('shoppro_status_code', []);
|
||||
@@ -305,14 +277,9 @@ final class ShopproIntegrationsController
|
||||
$integrationId = max(0, (int) $request->input('integration_id', 0));
|
||||
$redirectTo = $this->buildRedirectUrl($integrationId, 'statuses');
|
||||
|
||||
if (!Csrf::validate((string) $request->input('_token', ''))) {
|
||||
Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
if ($integrationId <= 0 || $this->repository->findIntegration($integrationId) === null) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.not_found'));
|
||||
return Response::redirect($this->buildRedirectUrl(0, 'statuses'));
|
||||
$accessError = $this->validateCsrfAndIntegrationAccess((string) $request->input('_token', ''), $integrationId, 'statuses');
|
||||
if ($accessError !== null) {
|
||||
return $accessError;
|
||||
}
|
||||
|
||||
$result = $this->repository->fetchOrderStatuses($integrationId);
|
||||
@@ -431,6 +398,62 @@ final class ShopproIntegrationsController
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed>|null $existing
|
||||
*/
|
||||
private function validateSaveAccess(string $token, int $integrationId, ?array $existing, string $tab): ?Response
|
||||
{
|
||||
if (!Csrf::validate($token)) {
|
||||
Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
|
||||
return Response::redirect($this->buildRedirectUrl($integrationId, $tab));
|
||||
}
|
||||
if ($integrationId > 0 && $existing === null) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.not_found'));
|
||||
return Response::redirect($this->buildRedirectUrl(0, $tab));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function validateSaveInput(
|
||||
string $name,
|
||||
string $baseUrl,
|
||||
string $apiKey,
|
||||
bool $hasExistingApiKey,
|
||||
string $tab,
|
||||
string $ordersFetchStartDate,
|
||||
int $integrationId
|
||||
): ?string {
|
||||
if (mb_strlen($name) < 2) {
|
||||
return $this->translator->get('settings.integrations.validation.name_min');
|
||||
}
|
||||
if (!$this->isValidHttpUrl($baseUrl)) {
|
||||
return $this->translator->get('settings.integrations.validation.base_url_invalid');
|
||||
}
|
||||
if ($tab === 'integration' && $apiKey === '' && !$hasExistingApiKey) {
|
||||
return $this->translator->get('settings.integrations.validation.api_key_required');
|
||||
}
|
||||
if ($ordersFetchStartDate !== '' && !$this->isValidYmdDate($ordersFetchStartDate)) {
|
||||
return $this->translator->get('settings.integrations.validation.orders_fetch_start_date_invalid');
|
||||
}
|
||||
if ($this->isDuplicateName($integrationId, $name)) {
|
||||
return $this->translator->get('settings.integrations.validation.name_taken');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function validateCsrfAndIntegrationAccess(string $token, int $integrationId, string $tab): ?Response
|
||||
{
|
||||
if (!Csrf::validate($token)) {
|
||||
Flash::set('settings_error', $this->translator->get('auth.errors.csrf_expired'));
|
||||
return Response::redirect($this->buildRedirectUrl($integrationId, $tab));
|
||||
}
|
||||
if ($integrationId <= 0 || $this->repository->findIntegration($integrationId) === null) {
|
||||
Flash::set('settings_error', $this->translator->get('settings.integrations.flash.not_found'));
|
||||
return Response::redirect($this->buildRedirectUrl(0, $tab));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function isDuplicateName(int $currentId, string $name): bool
|
||||
{
|
||||
$needle = mb_strtolower(trim($name));
|
||||
|
||||
Reference in New Issue
Block a user