1
0

refactor: fix all 105 PHPStan 2 strict type findings across core and modules

Resolve all non-false-positive PHPStan 2 findings, reducing the baseline
from 486 to 382 entries (only unused-public false positives remain).

Categories fixed:
- Remove 39 redundant type checks (is_string, is_array, is_object, method_exists)
- Remove 12 no-op array_values() on already-sequential lists
- Simplify 13 null-coalesce on guaranteed offsets
- Remove 8 always-true instanceof checks
- Replace 12 redundant test assertions (assertTrue(true) → addToAssertionCount)
- Simplify 6 unnecessary nullsafe operators (?-> → ->)
- Fix 6 always-true !== '' comparisons
- Fix remaining: unset.offset, return.unusedType, staticMethod narrowing

53 files changed across core/, modules/, pages/, and tests/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-14 12:54:20 +02:00
parent a736566071
commit 3f0db68b27
53 changed files with 90 additions and 640 deletions

View File

@@ -283,7 +283,7 @@ final class ModuleRegistry
// — Merge search resources (fail-fast on duplicate provider) ——
foreach ($manifest->searchResources as $provider) {
if (!is_string($provider) || trim($provider) === '') {
if (trim($provider) === '') {
throw new RuntimeException(
"Search resource provider in module '{$manifest->id}' must be a non-empty class-string."
);
@@ -333,7 +333,7 @@ final class ModuleRegistry
// — Merge layout context providers ————————————————
foreach ($manifest->layoutContextProviders as $providerClass) {
if (!is_string($providerClass) || trim($providerClass) === '') {
if (trim($providerClass) === '') {
throw new RuntimeException(
"Layout context provider in module '{$manifest->id}' must be a non-empty class-string."
);
@@ -343,7 +343,7 @@ final class ModuleRegistry
// — Merge session providers ——————————————————————
foreach ($manifest->sessionProviders as $providerClass) {
if (!is_string($providerClass) || trim($providerClass) === '') {
if (trim($providerClass) === '') {
throw new RuntimeException(
"Session provider in module '{$manifest->id}' must be a non-empty class-string."
);
@@ -353,7 +353,7 @@ final class ModuleRegistry
// — Merge authorization policies (fail-fast on duplicate) ———
foreach ($manifest->authorizationPolicies as $policyClass) {
if (!is_string($policyClass) || trim($policyClass) === '') {
if (trim($policyClass) === '') {
throw new RuntimeException(
"Authorization policy in module '{$manifest->id}' must be a non-empty class-string."
);
@@ -402,7 +402,7 @@ final class ModuleRegistry
'default_schedule_time' => $schedulerJob['default_schedule_time'],
'default_schedule_weekdays_csv' => $schedulerJob['default_schedule_weekdays_csv'],
'default_catchup_once' => (int) $schedulerJob['default_catchup_once'],
'allowed_schedule_types' => array_values($schedulerJob['allowed_schedule_types']),
'allowed_schedule_types' => $schedulerJob['allowed_schedule_types'],
'module_id' => $manifest->id,
];
}
@@ -637,10 +637,10 @@ final class ModuleRegistry
/** @return list<string> */
public function getPermissionKeys(): array
{
return array_values(array_map(
return array_map(
static fn (array $permission): string => (string) $permission['key'],
$this->mergedPermissions
));
);
}
/** @return list<class-string> */

View File

@@ -34,9 +34,6 @@ final class ModuleRuntimeAssetPublisher
$desired = [];
foreach ($modules as $manifest) {
if (!$manifest instanceof ModuleManifest) {
continue;
}
$moduleWebDir = rtrim($manifest->basePath, '/') . '/web';
if (!is_dir($moduleWebDir)) {
continue;

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace MintyPHP\Console\Runner\Doctor;
use MintyPHP\App\AppContainer;
use MintyPHP\App\Bootstrap\EnvValidator;
use MintyPHP\Console\Support\CliAppBootstrap;
use MintyPHP\DB;
@@ -22,8 +21,7 @@ final class DoctorRunner implements DoctorRunnerInterface
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
ini_set('display_errors', '0');
/** @var AppContainer $container */
$container = CliAppBootstrap::bootstrap('cli', 'bin/console doctor');
CliAppBootstrap::bootstrap('cli', 'bin/console doctor');
$startedAt = microtime(true);
$results = [];
@@ -71,14 +69,7 @@ final class DoctorRunner implements DoctorRunnerInterface
];
});
$runCheck('App container bootstrap', static function () use ($container): array {
if (!$container instanceof AppContainer) {
return [
'status' => 'fail',
'message' => 'registerContainer.php did not return AppContainer',
];
}
$runCheck('App container bootstrap', static function (): array {
app(AuthService::class);
app(AuthorizationService::class);
app(UiAccessService::class);

View File

@@ -229,7 +229,7 @@ class ApiBootstrap
}
$parts = explode(':', $token, 2);
$selector = trim((string) ($parts[0] ?? ''));
$selector = trim($parts[0]);
if ($selector === '' || !preg_match('/^[a-f0-9]{24}$/i', $selector)) {
return '';
}
@@ -256,7 +256,7 @@ class ApiBootstrap
try {
if (is_callable(self::$apiAuditServiceResolver)) {
$service = (self::$apiAuditServiceResolver)();
if (is_object($service) && method_exists($service, 'startRequestContext')) {
if (method_exists($service, 'startRequestContext')) {
$service->startRequestContext();
}
}
@@ -270,7 +270,7 @@ class ApiBootstrap
try {
if (is_callable(self::$apiAuditServiceResolver)) {
$service = (self::$apiAuditServiceResolver)();
if (is_object($service) && method_exists($service, 'finish')) {
if (method_exists($service, 'finish')) {
$service->finish($statusCode, $errorCode);
}
}
@@ -284,7 +284,7 @@ class ApiBootstrap
try {
if (is_callable(self::$apiSystemAuditReporterResolver)) {
$service = (self::$apiSystemAuditReporterResolver)();
if (is_object($service) && method_exists($service, 'start')) {
if (method_exists($service, 'start')) {
$service->start();
}
}
@@ -298,7 +298,7 @@ class ApiBootstrap
try {
if (is_callable(self::$apiSystemAuditReporterResolver)) {
$service = (self::$apiSystemAuditReporterResolver)();
if (is_object($service) && method_exists($service, 'finish')) {
if (method_exists($service, 'finish')) {
$service->finish($statusCode, $errorCode);
}
}

View File

@@ -243,7 +243,7 @@ class ApiResponse
try {
if (is_callable(self::$apiAuditServiceResolver)) {
$service = (self::$apiAuditServiceResolver)();
if (is_object($service) && method_exists($service, 'finish')) {
if (method_exists($service, 'finish')) {
$service->finish($statusCode, $errorCode);
}
}
@@ -257,7 +257,7 @@ class ApiResponse
try {
if (is_callable(self::$apiAuditServiceResolver)) {
$service = (self::$apiAuditServiceResolver)();
if (is_object($service) && method_exists($service, 'currentRequestId')) {
if (method_exists($service, 'currentRequestId')) {
return $service->currentRequestId();
}
}
@@ -273,12 +273,7 @@ class ApiResponse
throw new \RuntimeException('ApiResponse is not configured for dependency: ' . AuthorizationService::class);
}
$service = (self::$authorizationServiceResolver)();
if (!$service instanceof AuthorizationService) {
throw new \RuntimeException('ApiResponse resolver returned invalid dependency: ' . AuthorizationService::class);
}
return $service;
return (self::$authorizationServiceResolver)();
}
private static function finishSystemAuditReporter(int $statusCode, ?string $errorCode = null): void
@@ -286,7 +281,7 @@ class ApiResponse
try {
if (is_callable(self::$apiSystemAuditReporterResolver)) {
$service = (self::$apiSystemAuditReporterResolver)();
if (is_object($service) && method_exists($service, 'finish')) {
if (method_exists($service, 'finish')) {
$service->finish($statusCode, $errorCode);
}
}

View File

@@ -52,7 +52,7 @@ class RequestRuntime implements RequestRuntimeInterface
}
$parts = explode(',', $forwarded);
return trim((string) ($parts[0] ?? '')) === 'https';
return trim($parts[0]) === 'https';
}
/**

View File

@@ -46,7 +46,7 @@ class MailLogRepository implements MailLogRepositoryInterface
public function listPaged(array $options): array
{
$search = trim((string) ($options['search'] ?? ''));
$status = MailLogStatus::tryNormalize((string) ($options['status'] ?? ''))?->value ?? '';
$status = MailLogStatus::tryNormalize((string) ($options['status'] ?? ''))->value ?? '';
$createdFrom = trim((string) ($options['created_from'] ?? ''));
$createdTo = trim((string) ($options['created_to'] ?? ''));

View File

@@ -1080,6 +1080,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$vars = get_defined_vars();
/** @phpstan-ignore unset.offset (get_defined_vars() includes $this in object context; must remove before returning) */
unset($vars['this']);
return $vars;
}

View File

@@ -95,7 +95,7 @@ class AccessPolicyFactory
if ($this->moduleRegistry !== null) {
try {
foreach ($this->moduleRegistry->getAuthorizationPolicies() as $policyClass) {
if (!is_string($policyClass) || trim($policyClass) === '') {
if (trim($policyClass) === '') {
continue;
}
$policy = $this->instantiateModulePolicy($policyClass);

View File

@@ -15,9 +15,7 @@ class AuthorizationService
public function __construct(array $policies)
{
foreach ($policies as $policy) {
if ($policy instanceof AuthorizationPolicyInterface) {
$this->policies[] = $policy;
}
$this->policies[] = $policy;
}
}

View File

@@ -53,14 +53,10 @@ final class UiAccessService
continue;
}
if (!is_array($definition)) {
$resolved[$key] = false;
continue;
}
$ability = $definition['ability'];
$context = [];
if (array_key_exists('context', $definition) && is_array($definition['context'])) {
if (array_key_exists('context', $definition)) {
$context = $this->normalizeContext($definition['context']);
}
$resolved[$key] = $this->allow($actorUserId, $ability, [
@@ -113,7 +109,7 @@ final class UiAccessService
private function normalizeContext(array $context): array
{
$normalized = $this->normalizeValue($context);
return is_array($normalized) ? $normalized : [];
return $this->normalizeValue($context);
}
private function normalizeValue(mixed $value): mixed

View File

@@ -278,12 +278,10 @@ class TenantSsoService
if ($auth['client_secret_override_enc'] === '') {
return ['ok' => false, 'error' => 'client_secret_override_required'];
}
if ($auth['client_secret_override_enc'] !== '') {
try {
$clientSecret = $this->cryptoGateway->decryptString($auth['client_secret_override_enc']);
} catch (\Throwable $exception) {
return ['ok' => false, 'error' => 'secret_invalid'];
}
try {
$clientSecret = $this->cryptoGateway->decryptString($auth['client_secret_override_enc']);
} catch (\Throwable $exception) {
return ['ok' => false, 'error' => 'secret_invalid'];
}
if (trim($clientSecret) === '') {
return ['ok' => false, 'error' => 'client_secret_override_required'];

View File

@@ -138,6 +138,6 @@ class BrandingLogoService
usort($matches, static function ($a, $b) {
return filemtime($b) <=> filemtime($a);
});
return $matches[0] ?? null;
return $matches[0];
}
}

View File

@@ -136,9 +136,6 @@ class UserCustomFieldValueService
$tenantScopeId = (int) ($tenantScopeId ?? 0);
$orderedTenants = [];
foreach ($tenantSummaries as $tenantSummary) {
if (!is_array($tenantSummary)) {
continue;
}
$tenantId = (int) ($tenantSummary['id'] ?? 0);
if ($tenantId <= 0) {
continue;
@@ -579,7 +576,7 @@ class UserCustomFieldValueService
private static function mapPublicValueByType(string $type, ?array $valueData, array $optionsById)
{
$hasValue = is_array($valueData);
$hasValue = $valueData !== null;
if ($type === 'multiselect') {
if (!$hasValue) {
return [];

View File

@@ -112,7 +112,7 @@ trait ImageUploadTrait
usort($matches, static function ($a, $b) {
return filemtime($b) <=> filemtime($a);
});
return $matches[0] ?? null;
return $matches[0];
}
protected static function imageCreateResource(string $path, string $mime)

View File

@@ -126,9 +126,6 @@ class CsvReaderService
$lineNumber = 0;
while (($row = fgetcsv($handle, 0, $delimiter, '"', '\\')) !== false) {
$lineNumber++;
if (!is_array($row)) {
continue;
}
$row = $this->normalizeRowColumns($row, count($row));
if ($this->isEmptyRow($row)) {
continue;
@@ -207,9 +204,6 @@ class CsvReaderService
if ($lineNumber <= $headerLine) {
continue;
}
if (!is_array($row)) {
continue;
}
$row = $this->normalizeRowColumns($row, count($headers));
if ($this->isEmptyRow($row)) {
continue;

View File

@@ -161,7 +161,7 @@ class ScheduledJobRegistry
'default_schedule_time' => $jobDefinition['default_schedule_time'],
'default_schedule_weekdays_csv' => $jobDefinition['default_schedule_weekdays_csv'],
'default_catchup_once' => (int) $jobDefinition['default_catchup_once'],
'allowed_schedule_types' => array_values($jobDefinition['allowed_schedule_types']),
'allowed_schedule_types' => $jobDefinition['allowed_schedule_types'],
];
}
}

View File

@@ -196,7 +196,7 @@ class SchedulerRunService
$errorCode = 'job_not_registered';
} else {
$execution = $this->scheduledJobRegistry->execute((string) $job['job_key'], $actorUserId);
$status = ScheduledJobRunStatus::tryNormalize((string) $execution['status'])?->value
$status = ScheduledJobRunStatus::tryNormalize((string) $execution['status'])->value
?? ScheduledJobRunStatus::Failed->value;
$errorCode = $this->nullableString($execution['error_code']);
$errorMessage = $this->nullableString($execution['error_message']);

View File

@@ -156,7 +156,7 @@ class TenantAvatarService
usort($matches, static function ($a, $b) {
return filemtime($b) <=> filemtime($a);
});
return $matches[0] ?? null;
return $matches[0];
}
private function avatarDirs(string $uuid): array

View File

@@ -105,19 +105,9 @@ class UserAccessPdfService
private static function configurePdfOptions(Options $options): void
{
// Keep PDF rendering deterministic and avoid remote/network execution.
if (method_exists($options, 'setIsRemoteEnabled')) {
$options->setIsRemoteEnabled(false);
} else {
$options->set('isRemoteEnabled', false);
}
if (method_exists($options, 'setIsPhpEnabled')) {
$options->setIsPhpEnabled(false);
} else {
$options->set('isPhpEnabled', false);
}
if (method_exists($options, 'setDefaultFont')) {
$options->setDefaultFont('DejaVu Sans');
}
$options->setIsRemoteEnabled(false);
$options->setIsPhpEnabled(false);
$options->setDefaultFont('DejaVu Sans');
}
private static function renderTemplate(string $template, array $vars, string $locale): string

View File

@@ -217,6 +217,6 @@ class UserAvatarService
usort($matches, static function ($a, $b) {
return filemtime($b) <=> filemtime($a);
});
return $matches[0] ?? null;
return $matches[0];
}
}

View File

@@ -145,11 +145,7 @@ class Guard
if (!is_callable(self::$authorizationServiceResolver)) {
throw new \RuntimeException('Guard is not configured for dependency: ' . AuthorizationService::class);
}
$service = (self::$authorizationServiceResolver)();
if (!$service instanceof AuthorizationService) {
throw new \RuntimeException('Guard resolver returned invalid dependency: ' . AuthorizationService::class);
}
return $service;
return (self::$authorizationServiceResolver)();
}
private static function authService(): AuthService
@@ -157,11 +153,7 @@ class Guard
if (!is_callable(self::$authServiceResolver)) {
throw new \RuntimeException('Guard is not configured for dependency: ' . AuthService::class);
}
$service = (self::$authServiceResolver)();
if (!$service instanceof AuthService) {
throw new \RuntimeException('Guard resolver returned invalid dependency: ' . AuthService::class);
}
return $service;
return (self::$authServiceResolver)();
}
private static function tenantService(): TenantService
@@ -169,11 +161,7 @@ class Guard
if (!is_callable(self::$tenantServiceResolver)) {
throw new \RuntimeException('Guard is not configured for dependency: ' . TenantService::class);
}
$service = (self::$tenantServiceResolver)();
if (!$service instanceof TenantService) {
throw new \RuntimeException('Guard resolver returned invalid dependency: ' . TenantService::class);
}
return $service;
return (self::$tenantServiceResolver)();
}
private static function isAllowedByAbility(int $userId, string $ability, array $context = []): bool

View File

@@ -163,9 +163,6 @@ class SearchConfig
try {
$registry = (self::$moduleRegistryResolver)();
if (!$registry instanceof ModuleRegistry) {
return self::$moduleProviders;
}
foreach ($registry->getSearchResources() as $providerClass) {
$provider = self::resolveModuleProvider($providerClass);
if ($provider instanceof SearchResourceProvider) {

View File

@@ -487,11 +487,6 @@ function appBuildLayoutNavContext(array $layoutAuth, array $session, array $quer
$provider = \MintyPHP\App\Module\ModuleClassResolver::resolve($container, $providerClass);
if ($provider instanceof \MintyPHP\App\Module\Contracts\LayoutContextProvider) {
$providerData = $provider->provide($session, $container);
if (!is_array($providerData)) {
throw new \RuntimeException(
"Layout context provider '{$providerClass}' must return an array."
);
}
$layoutNav = appMergeLayoutNavProviderData($layoutNav, $providerData, $providerClass);
}
}

View File

@@ -206,9 +206,6 @@ function gridSplitToolbarSchema(array $toolbarSchema, array $searchKeys = []): a
$search = [];
$drawer = [];
foreach ($toolbarSchema as $field) {
if (!is_array($field)) {
continue;
}
$key = trim((string) ($field['key'] ?? ''));
$isSearch = (bool) ($field['search'] ?? false) || ($key !== '' && isset($searchKeyMap[$key]));
if ($isSearch) {
@@ -231,9 +228,6 @@ function gridSchemaByKey(array $toolbarSchema): array
{
$schemaByKey = [];
foreach ($toolbarSchema as $field) {
if (!is_array($field)) {
continue;
}
$key = trim((string) ($field['key'] ?? ''));
if ($key === '') {
continue;
@@ -255,9 +249,6 @@ function gridBuildToolbarFilterState(array $toolbarSchema, array $filterState):
{
$state = [];
foreach ($toolbarSchema as $field) {
if (!is_array($field)) {
continue;
}
$key = trim((string) ($field['key'] ?? ''));
if ($key === '') {
@@ -347,9 +338,6 @@ function gridOptionMapFromItems(array $items): array
{
$map = [];
foreach ($items as $item) {
if (!is_array($item)) {
continue;
}
$id = trim((string) ($item['id'] ?? ''));
if ($id === '') {
continue;
@@ -370,9 +358,6 @@ function gridOptionMapFromAllowed(array $field): array
{
$map = [];
foreach ((array) ($field['allowed'] ?? []) as $item) {
if (!is_array($item)) {
continue;
}
$id = trim((string) ($item['id'] ?? ''));
if ($id === '') {
continue;

View File

@@ -101,9 +101,6 @@ function requestNormalizeSafeInternalTarget(string $target, int $maxDepth = 5):
$queryParams = [];
parse_str((string) ($safeParts['query'] ?? ''), $queryParams);
if (!is_array($queryParams)) {
$queryParams = [];
}
$nestedReturnTarget = requestExtractNestedReturnValue($queryParams['return'] ?? null);
unset($queryParams['return']);
$query = http_build_query($queryParams);
@@ -185,9 +182,6 @@ function requestPathWithReturnTarget(string $path, string $returnTarget = ''): s
}
$queryParams = [];
parse_str((string) ($parts['query'] ?? ''), $queryParams);
if (!is_array($queryParams)) {
$queryParams = [];
}
unset($queryParams['return']);
$queryParams['return'] = $normalizedReturnTarget;
$query = http_build_query($queryParams);

View File

@@ -146,9 +146,6 @@ function selectFilter(
function renderGridFilterToolbar(array $schema, array $active = [], array $optionSets = []): void
{
foreach ($schema as $field) {
if (!is_array($field)) {
continue;
}
if (($field['render'] ?? true) === false) {
continue;
}
@@ -463,10 +460,10 @@ function appStylePathsForGroups(array $groupNames): array
$registry = app(\MintyPHP\App\Module\ModuleRegistry::class);
if ($registry instanceof \MintyPHP\App\Module\ModuleRegistry) {
foreach ($registry->getAssetGroups() as $groupName => $paths) {
if (!is_string($groupName) || $groupName === '') {
if ($groupName === '') {
continue;
}
if (!is_array($paths) || isset($groups[$groupName])) {
if (isset($groups[$groupName])) {
continue;
}
$groups[$groupName] = $paths;

View File

@@ -65,17 +65,17 @@ class UserLifecycleAuditRepository
$actions = RepoQuery::normalizeStringList(
$filters['actions'] ?? '',
self::FILTER_OPTIONS_LIMIT_MAX,
static fn (string $value): string => UserLifecycleAction::tryNormalize($value)?->value ?? ''
static fn (string $value): string => UserLifecycleAction::tryNormalize($value)->value ?? ''
);
$statuses = RepoQuery::normalizeStringList(
$filters['statuses'] ?? '',
self::FILTER_OPTIONS_LIMIT_MAX,
static fn (string $value): string => UserLifecycleStatus::tryNormalize($value)?->value ?? ''
static fn (string $value): string => UserLifecycleStatus::tryNormalize($value)->value ?? ''
);
$triggerTypes = RepoQuery::normalizeStringList(
$filters['trigger_types'] ?? '',
self::FILTER_OPTIONS_LIMIT_MAX,
static fn (string $value): string => UserLifecycleTriggerType::tryNormalize($value)?->value ?? ''
static fn (string $value): string => UserLifecycleTriggerType::tryNormalize($value)->value ?? ''
);
$actorUserIds = array_slice(
RepoQuery::normalizeIdList($filters['actor_user_ids'] ?? ''),

View File

@@ -485,11 +485,7 @@ class FrontendTelemetryIngestService
$cutoff = $now - self::DEDUPE_WINDOW_SECONDS;
foreach ($seen as $key => $timestamp) {
if (!is_string($key)) {
unset($seen[$key]);
continue;
}
if (!is_int($timestamp) || $timestamp < $cutoff) {
if ($timestamp < $cutoff) {
unset($seen[$key]);
}
}

View File

@@ -28,18 +28,10 @@ if (!Session::checkCsrfToken()) {
}
$body = requestInput()->bodyAll();
if (!is_array($body)) {
http_response_code(204);
return;
}
$allowedKeys = ['event_type', 'severity', 'message', 'fingerprint', 'meta', 'occurred_at'];
$csrfKey = Session::$csrfSessionKey;
foreach ($body as $key => $value) {
if (!is_string($key)) {
continue;
}
if ($key === $csrfKey) {
continue;
}

View File

@@ -141,9 +141,7 @@ class BcODataGateway
. '&$count=true'
. '&$orderby=' . rawurlencode($sortField . ' ' . $sortDir)
. $select;
if ($clauses !== []) {
$url .= '&$filter=' . rawurlencode(implode(' and ', $clauses));
}
$url .= '&$filter=' . rawurlencode(implode(' and ', $clauses));
try {
$response = $this->request('GET', $url);
@@ -469,9 +467,6 @@ class BcODataGateway
$rows = $this->extractODataValues($response);
$mapped = [];
foreach ($rows as $row) {
if (!is_array($row)) {
continue;
}
$ticketNo = trim((string) ($row['No'] ?? ''));
if ($ticketNo === '') {
continue;
@@ -1271,9 +1266,6 @@ class BcODataGateway
{
$uniqueRows = [];
foreach ($rows as $row) {
if (!is_array($row)) {
continue;
}
$no = trim((string) ($row['No'] ?? ''));
$rowKey = $no !== '' ? $no : md5((string) json_encode($row));

View File

@@ -645,7 +645,7 @@ class DebitorDetailService
$billToNo = trim((string) ($contract['Bill_to_Cust_No'] ?? ''));
$sellToNo = trim((string) ($contract['Sell_to_Cust_No'] ?? ''));
if ($customerNo !== '' && $billToNo !== $customerNo && $sellToNo !== $customerNo) {
if ($billToNo !== $customerNo && $sellToNo !== $customerNo) {
continue;
}
@@ -1178,7 +1178,7 @@ class DebitorDetailService
$days = isset($matches[1]) && $matches[1] !== '' ? (int) $matches[1] : 0;
$hours = isset($matches[2]) && $matches[2] !== '' ? (int) $matches[2] : 0;
$minutes = isset($matches[3]) && $matches[3] !== '' ? (int) $matches[3] : 0;
$secondsFloat = isset($matches[4]) && $matches[4] !== '' ? (float) $matches[4] : 0.0;
$secondsFloat = isset($matches[4]) ? (float) $matches[4] : 0.0;
$seconds = (int) floor($secondsFloat);
return ($days * 86400) + ($hours * 3600) + ($minutes * 60) + $seconds;

View File

@@ -332,7 +332,7 @@ final class RiskRadarService
$days = isset($m[1]) && $m[1] !== '' ? (int) $m[1] : 0;
$hours = isset($m[2]) && $m[2] !== '' ? (int) $m[2] : 0;
$minutes = isset($m[3]) && $m[3] !== '' ? (int) $m[3] : 0;
$seconds = isset($m[4]) && $m[4] !== '' ? (int) floor((float) $m[4]) : 0;
$seconds = isset($m[4]) ? (int) floor((float) $m[4]) : 0;
return ($days * 86400) + ($hours * 3600) + ($minutes * 60) + $seconds;
}
@@ -355,7 +355,7 @@ final class RiskRadarService
private static function resolveActivityTimestamp(array $ticket): ?int
{
$lastActivity = trim((string) ($ticket['Last_Activity_Date'] ?? ''));
if ($lastActivity !== '' && !str_starts_with($lastActivity, '0001-01-01')) {
if (!str_starts_with($lastActivity, '0001-01-01')) {
$ts = strtotime($lastActivity);
if (is_int($ts)) {
return $ts;

View File

@@ -244,7 +244,7 @@ class SystemRecommendationEngine
return [
'recommendations' => array_slice($deduped, 0, $maxItems),
'meta' => [
'applied_rules' => array_values(array_keys($appliedRulesMap)),
'applied_rules' => array_keys($appliedRulesMap),
'max_items' => $maxItems,
'escalation_data_available' => $escalationAvailable,
],
@@ -379,9 +379,6 @@ class SystemRecommendationEngine
$openTickets = [];
foreach ($tickets as $ticket) {
if (!is_array($ticket)) {
continue;
}
$state = trim((string) ($ticket['Ticket_State'] ?? ''));
if (in_array($state, self::CLOSED_TICKET_STATES, true)) {

View File

@@ -193,9 +193,6 @@ class TicketCommunicationService
// Collect support user name → ticket code mappings
$supportUserNamesByTicket = [];
foreach ($tickets as $ticket) {
if (!is_array($ticket)) {
continue;
}
$no = trim((string) ($ticket['No'] ?? ''));
$name = trim((string) ($ticket['Support_User_Name'] ?? ''));
if ($no !== '' && $name !== '') {
@@ -784,7 +781,7 @@ class TicketCommunicationService
}
if (preg_match('/^(\d{2}:\d{2})(:\d{2})?/', $time, $m) === 1) {
return isset($m[2]) && $m[2] !== '' ? ($m[1] . $m[2]) : ($m[1] . ':00');
return isset($m[2]) ? ($m[1] . $m[2]) : ($m[1] . ':00');
}
return $time;
@@ -902,9 +899,6 @@ class TicketCommunicationService
$nameMap = [];
foreach ($contacts as $contact) {
if (!is_array($contact)) {
continue;
}
$contactNo = strtoupper(trim((string) ($contact['No'] ?? '')));
$contactName = trim((string) ($contact['Name'] ?? ''));
if ($contactNo === '' || $contactName === '') {
@@ -1075,7 +1069,7 @@ class TicketCommunicationService
}
}
return $trimmed !== '' ? $trimmed : '';
return $trimmed;
}
private function normalizeActorRole(string $createdByType, string $actor): string

View File

@@ -184,7 +184,7 @@ foreach ($rows as $contact) {
}
Router::json([
'data' => array_values($preparedRows),
'data' => $preparedRows,
'total' => max(0, $total),
'type_options' => $typeOptions,
'meta' => [

View File

@@ -115,9 +115,9 @@ usort($contactValues, 'strnatcasecmp');
Router::json([
'ok' => true,
'categories' => array_values($categoryValues),
'support_users' => array_values($supportUserValues),
'contacts' => array_values($contactValues),
'categories' => $categoryValues,
'support_users' => $supportUserValues,
'contacts' => $contactValues,
'meta' => [
'cache_used' => $cacheUsed,
'cache_bypassed' => $refreshRequested,

View File

@@ -254,7 +254,7 @@ foreach ($rows as $ticket) {
}
Router::json([
'data' => array_values($preparedRows),
'data' => $preparedRows,
'total' => max(0, $total),
'meta' => [
'cache_used' => $cacheUsed,

View File

@@ -193,7 +193,7 @@ class BcODataGatewayTest extends TestCase
$this->fail('Umlauts should be allowed in search queries');
} catch (\RuntimeException) {
// Expected: cURL fails against fake URL
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
}
@@ -206,7 +206,7 @@ class BcODataGatewayTest extends TestCase
$this->fail('Numbers and dashes should be allowed in search queries');
} catch (\RuntimeException) {
// Expected: cURL fails against fake URL
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
}
@@ -242,13 +242,13 @@ class BcODataGatewayTest extends TestCase
{
$gateway = $this->createGatewayWithSettings();
try {
$results = $gateway->getContactsForCustomer('10636', 'Behindertenwerkstätten Oberpfalz Betreuungs GmbH');
$this->assertIsArray($results);
$gateway->getContactsForCustomer('10636', 'Behindertenwerkstätten Oberpfalz Betreuungs GmbH');
$this->addToAssertionCount(1);
} catch (\InvalidArgumentException) {
$this->fail('Trusted customer literals should not be rejected for contact loads.');
} catch (\RuntimeException) {
// Expected: cURL fails against fake URL.
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
}
@@ -256,13 +256,13 @@ class BcODataGatewayTest extends TestCase
{
$gateway = $this->createGatewayWithSettings();
try {
$results = $gateway->getTicketsForCustomer('10494', "J.G. Knopf´s Sohn Gmbh & Co. KG");
$this->assertIsArray($results);
$gateway->getTicketsForCustomer('10494', "J.G. Knopf´s Sohn Gmbh & Co. KG");
$this->addToAssertionCount(1);
} catch (\InvalidArgumentException) {
$this->fail('Trusted customer literals should not be rejected for ticket loads.');
} catch (\RuntimeException) {
// Expected: cURL fails against fake URL.
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
}
@@ -396,7 +396,7 @@ class BcODataGatewayTest extends TestCase
$threw = true;
}
// Either cURL failed (expected) or returned empty — both are fine
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
public function testGetContractLinesForCustomerAcceptsCustomerNoWithDash(): void
@@ -410,6 +410,6 @@ class BcODataGatewayTest extends TestCase
} catch (\RuntimeException) {
$threw = true;
}
$this->assertTrue(true);
$this->addToAssertionCount(1);
}
}

View File

@@ -537,7 +537,6 @@ class DebitorDetailServiceTest extends TestCase
$result = DebitorDetailService::buildSupportDashboard($tickets, 48);
$this->assertTrue($result['ok']);
$this->assertSame(4, $result['health']['total_tickets']);
$this->assertSame(3, $result['health']['open_tickets']);
$this->assertSame(1, $result['health']['critical_tickets']);
@@ -566,7 +565,6 @@ class DebitorDetailServiceTest extends TestCase
$result = DebitorDetailService::buildSupportDashboard($tickets, 48);
$this->assertTrue($result['ok']);
$this->assertSame(0, $result['health']['open_tickets']);
$this->assertSame(0, $result['health']['critical_tickets']);
$this->assertNull($result['health']['oldest_open_age_hours']);
@@ -639,7 +637,6 @@ class DebitorDetailServiceTest extends TestCase
'definitions_count' => 15,
]);
$this->assertTrue($result['ok']);
$this->assertSame(4, $result['health']['escalation_count']);
$this->assertTrue($result['health']['escalation_available']);
$this->assertSame(6, $result['meta']['escalation_tickets_considered']);

View File

@@ -36,8 +36,7 @@ class TicketCommunicationServiceTest extends TestCase
$service = new TicketCommunicationService($soapGateway, $odataGateway);
$result = $service->loadTicketCommunicationFeed('T26-1216', 40);
$this->assertTrue($result['ok']);
$this->assertIsArray($result['entries']);
$this->assertNotEmpty($result['entries']);
$this->assertGreaterThanOrEqual(3, count($result['entries']));
$this->assertSame(true, $result['meta']['soap_used']);
$this->assertSame(false, $result['meta']['fallback_used']);

View File

@@ -134,7 +134,7 @@ final class NotificationMessage
}
}
return array_values($normalized);
return $normalized;
}
/**

View File

@@ -377,7 +377,7 @@ class NotificationService
}
}
return array_values($normalized);
return $normalized;
}
/**

View File

@@ -30,7 +30,7 @@ foreach ($importService->listProfileOptions() as $option) {
$allowedProfileOptions = array_values(array_filter($profileOptions, static fn (array $option): bool => !empty($option['allowed'])));
$firstAllowedType = '';
if ($allowedProfileOptions) {
$firstAllowedType = (string) ($allowedProfileOptions[0]['key'] ?? '');
$firstAllowedType = (string) $allowedProfileOptions[0]['key'];
}
$selectedType = trim((string) ($request->body('type', $request->query('type', $firstAllowedType))));

View File

@@ -32,8 +32,8 @@ foreach ((array) ($result['rows'] ?? []) as $row) {
'schedule_summary' => $scheduledJobService->scheduleSummary($row),
'next_run_at' => dt((string) ($row['next_run_at'] ?? '')),
'last_run_finished_at' => dt((string) ($row['last_run_finished_at'] ?? '')),
'last_run_status' => $status?->value ?? '',
'last_run_status_badge' => $status?->badgeVariant() ?? 'neutral',
'last_run_status' => $status->value ?? '',
'last_run_status_badge' => $status->badgeVariant(),
'last_run_status_label' => $status !== null ? t($status->labelToken()) : '-',
'last_error' => trim((string) ($row['last_error_code'] ?? '')) !== ''
? trim((string) ($row['last_error_code'] ?? ''))

View File

@@ -304,7 +304,7 @@ if (requestInput()->method() === 'POST') {
} else {
$ldapConfig = $ldapConfigResult['config'];
$allowedDomains = trim((string) ($ldapConfig['allowed_domains'] ?? ''));
if ($allowedDomains !== '' && $email !== '') {
if ($allowedDomains !== '') {
$domainList = array_filter(array_map('trim', explode(',', $allowedDomains)));
if (!$tenantSsoService->isEmailDomainAllowed($email, $domainList)) {
$setLoginWarning(t('Your email domain is not allowed for LDAP login on this tenant.'));

View File

@@ -12,18 +12,6 @@ parameters:
count: 1
path: core/App/Bootstrap/EnvValidator.php
-
message: '#^Call to function is_string\(\) with class\-string will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 4
path: core/App/Module/ModuleRegistry.php
-
message: '#^Parameter \#1 \$array \(list\<string\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 2
path: core/App/Module/ModuleRegistry.php
-
message: '#^Public method "MintyPHP\\App\\Module\\ModuleRegistry\:\:getModule\(\)" is never used$#'
identifier: public.method.unused
@@ -48,12 +36,6 @@ parameters:
count: 1
path: core/App/Module/ModuleRegistry.php
-
message: '#^Instanceof between MintyPHP\\App\\Module\\ModuleManifest and MintyPHP\\App\\Module\\ModuleManifest will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/App/Module/ModuleRuntimeAssetPublisher.php
-
message: '#^Public method "MintyPHP\\App\\Module\\ModuleRuntimePageBuilder\:\:expectedFingerprint\(\)" is never used$#'
identifier: public.method.unused
@@ -78,12 +60,6 @@ parameters:
count: 1
path: core/Console/ConsoleApplication.php
-
message: '#^Instanceof between MintyPHP\\App\\AppContainer and MintyPHP\\App\\AppContainer will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Console/Runner/Doctor/DoctorRunner.php
-
message: '#^Public method "MintyPHP\\Console\\Support\\ModuleCliRuntime\:\:bootstrap\(\)" is never used$#'
identifier: public.method.unused
@@ -132,30 +108,6 @@ parameters:
count: 1
path: core/Http/ApiAuth.php
-
message: '#^Call to function is_object\(\) with object will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 4
path: core/Http/ApiBootstrap.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 1
path: core/Http/ApiBootstrap.php
-
message: '#^Call to function is_object\(\) with object will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 3
path: core/Http/ApiResponse.php
-
message: '#^Instanceof between MintyPHP\\Service\\Access\\AuthorizationService and MintyPHP\\Service\\Access\\AuthorizationService will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Http/ApiResponse.php
-
message: '#^Public method "MintyPHP\\Http\\ApiResponse\:\:readJsonBody\(\)" is never used$#'
identifier: public.method.unused
@@ -252,12 +204,6 @@ parameters:
count: 1
path: core/Http/RequestContext.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 1
path: core/Http/RequestRuntime.php
-
message: '#^Public method "MintyPHP\\Http\\RouteCatalog\:\:corePublicPaths\(\)" is never used$#'
identifier: public.method.unused
@@ -288,24 +234,6 @@ parameters:
count: 1
path: core/Repository/CustomField/TenantCustomFieldDefinitionRepository.php
-
message: '#^Using nullsafe property access "\?\-\>value" on left side of \?\? is unnecessary\. Use \-\> instead\.$#'
identifier: nullsafe.neverNull
count: 1
path: core/Repository/Mail/MailLogRepository.php
-
message: '#^Cannot unset offset ''this'' on array\{tenantActiveStatus\: ''active'', tenantInactiveStatus\: ''inactive'', importStatusRunning\: ''running'', importStatusSuccess\: ''success'', importStatusPartial\: ''partial'', importStatusFailed\: ''failed'', systemAuditOutcomeFailed\: ''failed'', systemAuditOutcomeDenied\: ''denied'', \.\.\.\}\.$#'
identifier: unset.offset
count: 1
path: core/Repository/Stats/AdminStatsRepository.php
-
message: '#^Call to function is_string\(\) with class\-string will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/Access/AccessPolicyFactory.php
-
message: '#^Public method "MintyPHP\\Service\\Access\\AccessServicesFactory\:\:createAuthorizationService\(\)" is never used$#'
identifier: public.method.unused
@@ -384,12 +312,6 @@ parameters:
count: 1
path: core/Service/Access/AuthorizationDecision.php
-
message: '#^Instanceof between MintyPHP\\Service\\Access\\AuthorizationPolicyInterface and MintyPHP\\Service\\Access\\AuthorizationPolicyInterface will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Service/Access/AuthorizationService.php
-
message: '#^Public method "MintyPHP\\Service\\Access\\AuthorizationService\:\:allow\(\)" is never used$#'
identifier: public.method.unused
@@ -486,18 +408,6 @@ parameters:
count: 1
path: core/Service/Access/RoleService.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/Access/UiAccessService.php
-
message: '#^Call to function is_array\(\) with array\{ability\: string, context\?\: array\<string, mixed\>\} will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/Access/UiAccessService.php
-
message: '#^Public method "MintyPHP\\Service\\Access\\UiAccessService\:\:layoutCapabilities\(\)" is never used$#'
identifier: public.method.unused
@@ -834,18 +744,6 @@ parameters:
count: 1
path: core/Service/Auth/TenantSsoService.php
-
message: '#^Strict comparison using \!\=\= between mixed~'''' and '''' will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: core/Service/Auth/TenantSsoService.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 1
path: core/Service/Branding/BrandingFaviconService.php
-
message: '#^Public method "MintyPHP\\Service\\Branding\\BrandingFaviconService\:\:hasFavicon\(\)" is never used$#'
identifier: public.method.unused
@@ -858,12 +756,6 @@ parameters:
count: 1
path: core/Service/Branding/BrandingFaviconService.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 2
path: core/Service/Branding/BrandingLogoService.php
-
message: '#^Public method "MintyPHP\\Service\\Branding\\BrandingLogoService\:\:saveUpload\(\)" is never used$#'
identifier: public.method.unused
@@ -930,12 +822,6 @@ parameters:
count: 1
path: core/Service/CustomField/TenantCustomFieldService.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/CustomField/UserCustomFieldValueService.php
-
message: '#^Public method "MintyPHP\\Service\\CustomField\\UserCustomFieldValueService\:\:buildPublicValuesByTenant\(\)" is never used$#'
identifier: public.method.unused
@@ -990,12 +876,6 @@ parameters:
count: 1
path: core/Service/Docs/DocsCatalogService.php
-
message: '#^Call to function is_array\(\) with non\-empty\-list\<string\|null\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 2
path: core/Service/Import/CsvReaderService.php
-
message: '#^Public method "MintyPHP\\Service\\Import\\ImportService\:\:analyzeUpload\(\)" is never used$#'
identifier: public.method.unused
@@ -1104,12 +984,6 @@ parameters:
count: 1
path: core/Service/Org/DepartmentService.php
-
message: '#^Parameter \#1 \$array \(list\<string\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: core/Service/Scheduler/ScheduledJobRegistry.php
-
message: '#^Public constant "MintyPHP\\Service\\Scheduler\\ScheduledJobRegistry\:\:USER_LIFECYCLE_RUN" is never used$#'
identifier: public.classConstant.unused
@@ -1170,12 +1044,6 @@ parameters:
count: 1
path: core/Service/Scheduler/SchedulerRunService.php
-
message: '#^Using nullsafe property access "\?\-\>value" on left side of \?\? is unnecessary\. Use \-\> instead\.$#'
identifier: nullsafe.neverNull
count: 1
path: core/Service/Scheduler/SchedulerRunService.php
-
message: '#^Public method "MintyPHP\\Service\\Scheduler\\SchedulerServicesFactory\:\:createSchedulerRunService\(\)" is never used$#'
identifier: public.method.unused
@@ -1308,12 +1176,6 @@ parameters:
count: 1
path: core/Service/System/SystemInfoService.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 2
path: core/Service/Tenant/TenantAvatarService.php
-
message: '#^Public method "MintyPHP\\Service\\Tenant\\TenantAvatarService\:\:hasAvatar\(\)" is never used$#'
identifier: public.method.unused
@@ -1326,12 +1188,6 @@ parameters:
count: 1
path: core/Service/Tenant/TenantAvatarService.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 1
path: core/Service/Tenant/TenantFaviconService.php
-
message: '#^Public method "MintyPHP\\Service\\Tenant\\TenantFaviconService\:\:hasFavicon\(\)" is never used$#'
identifier: public.method.unused
@@ -1398,24 +1254,6 @@ parameters:
count: 1
path: core/Service/Tenant/TenantServicesFactory.php
-
message: '#^Call to function method_exists\(\) with Dompdf\\Options and ''setDefaultFont'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/User/UserAccessPdfService.php
-
message: '#^Call to function method_exists\(\) with Dompdf\\Options and ''setIsPhpEnabled'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/User/UserAccessPdfService.php
-
message: '#^Call to function method_exists\(\) with Dompdf\\Options and ''setIsRemoteEnabled'' will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Service/User/UserAccessPdfService.php
-
message: '#^Public method "MintyPHP\\Service\\User\\UserAccessPdfService\:\:renderUsersAccessZip\(\)" is never used$#'
identifier: public.method.unused
@@ -1500,12 +1338,6 @@ parameters:
count: 1
path: core/Service/User/UserAssignmentService.php
-
message: '#^Offset 0 on non\-empty\-list\<string\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 2
path: core/Service/User/UserAvatarService.php
-
message: '#^Public method "MintyPHP\\Service\\User\\UserAvatarService\:\:saveUpload\(\)" is never used$#'
identifier: public.method.unused
@@ -1578,24 +1410,6 @@ parameters:
count: 1
path: core/Support/Flash.php
-
message: '#^Instanceof between MintyPHP\\Service\\Access\\AuthorizationService and MintyPHP\\Service\\Access\\AuthorizationService will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Support/Guard.php
-
message: '#^Instanceof between MintyPHP\\Service\\Auth\\AuthService and MintyPHP\\Service\\Auth\\AuthService will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Support/Guard.php
-
message: '#^Instanceof between MintyPHP\\Service\\Tenant\\TenantService and MintyPHP\\Service\\Tenant\\TenantService will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Support/Guard.php
-
message: '#^Public method "MintyPHP\\Support\\Search\\SearchSqlResourceProvider\:\:resourceKeys\(\)" is never used$#'
identifier: public.method.unused
@@ -1614,12 +1428,6 @@ parameters:
count: 1
path: core/Support/Search/SearchUiMetaProvider.php
-
message: '#^Instanceof between MintyPHP\\App\\Module\\ModuleRegistry and MintyPHP\\App\\Module\\ModuleRegistry will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
count: 1
path: core/Support/SearchConfig.php
-
message: '#^Public method "MintyPHP\\Support\\SearchConfig\:\:iconForKey\(\)" is never used$#'
identifier: public.method.unused
@@ -1638,42 +1446,6 @@ parameters:
count: 1
path: core/Support/Tile.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Support/helpers/app.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 4
path: core/Support/helpers/grid.php
-
message: '#^Call to function is_array\(\) with array\<int\|string, array\<mixed\>\|string\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 2
path: core/Support/helpers/request.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Support/helpers/ui.php
-
message: '#^Call to function is_array\(\) with list\<string\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Support/helpers/ui.php
-
message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: core/Support/helpers/ui.php
-
message: '#^Public constant "MintyPHP\\Module\\AddressBook\\AddressBookAuthorizationPolicy\:\:PERMISSION_KEY" is never used$#'
identifier: public.classConstant.unused
@@ -1728,12 +1500,6 @@ parameters:
count: 1
path: modules/audit/lib/Module/Audit/Domain/UserLifecycleTriggerType.php
-
message: '#^Using nullsafe property access "\?\-\>value" on left side of \?\? is unnecessary\. Use \-\> instead\.$#'
identifier: nullsafe.neverNull
count: 3
path: modules/audit/lib/Module/Audit/Repository/UserLifecycleAuditRepository.php
-
message: '#^Public method "MintyPHP\\Module\\Audit\\Service\\ApiAuditService\:\:filterOptions\(\)" is never used$#'
identifier: public.method.unused
@@ -1752,18 +1518,6 @@ parameters:
count: 1
path: modules/audit/lib/Module/Audit/Service/ApiAuditService.php
-
message: '#^Call to function is_int\(\) with int will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: modules/audit/lib/Module/Audit/Service/FrontendTelemetryIngestService.php
-
message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: modules/audit/lib/Module/Audit/Service/FrontendTelemetryIngestService.php
-
message: '#^Public method "MintyPHP\\Module\\Audit\\Service\\FrontendTelemetryIngestService\:\:ingest\(\)" is never used$#'
identifier: public.method.unused
@@ -1824,18 +1578,6 @@ parameters:
count: 1
path: modules/audit/lib/Module/Audit/Service/UserLifecycleAuditService.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: 'modules/audit/pages/audit/frontend-telemetry/ingest().php'
-
message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: 'modules/audit/pages/audit/frontend-telemetry/ingest().php'
-
message: '#^Public method "MintyPHP\\Module\\Bookmarks\\Service\\BookmarkService\:\:allowedGroupIconLabels\(\)" is never used$#'
identifier: public.method.unused
@@ -1926,12 +1668,6 @@ parameters:
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Repository/HelpdeskTokenRepository.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 2
path: modules/helpdesk/lib/Module/Helpdesk/Service/BcODataGateway.php
-
message: '#^Public constant "MintyPHP\\Module\\Helpdesk\\Service\\BcODataGateway\:\:ENTITY_CONTACT" is never used$#'
identifier: public.classConstant.unused
@@ -2016,12 +1752,6 @@ parameters:
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/BcODataGateway.php
-
message: '#^Strict comparison using \!\=\= between list\{0\: ''Name ne \\''\\'''', 1\?\: non\-empty\-string, 2\?\: non\-empty\-string\} and array\{\} will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/BcODataGateway.php
-
message: '#^Public method "MintyPHP\\Module\\Helpdesk\\Service\\BcSoapGateway\:\:getTicketFile\(\)" is never used$#'
identifier: public.method.unused
@@ -2106,12 +1836,6 @@ parameters:
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/DebitorDetailService.php
-
message: '#^Strict comparison using \!\=\= between non\-empty\-string and '''' will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/DebitorDetailService.php
-
message: '#^Public constant "MintyPHP\\Module\\Helpdesk\\Service\\DebitorSearchService\:\:MIN_QUERY_LENGTH" is never used$#'
identifier: public.classConstant.unused
@@ -2340,108 +2064,24 @@ parameters:
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/HelpdeskTenantSettingsGateway.php
-
message: '#^Strict comparison using \!\=\= between non\-empty\-string and '''' will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/RiskRadarService.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/SystemRecommendationEngine.php
-
message: '#^Parameter \#1 \$array \(list\<string\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/SystemRecommendationEngine.php
-
message: '#^Public method "MintyPHP\\Module\\Helpdesk\\Service\\SystemRecommendationEngine\:\:buildRecommendations\(\)" is never used$#'
identifier: public.method.unused
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/SystemRecommendationEngine.php
-
message: '#^Call to function is_array\(\) with array\<string, mixed\> will always evaluate to true\.$#'
identifier: function.alreadyNarrowedType
count: 2
path: modules/helpdesk/lib/Module/Helpdesk/Service/TicketCommunicationService.php
-
message: '#^Public method "MintyPHP\\Module\\Helpdesk\\Service\\TicketCommunicationService\:\:loadDebitorCommunicationFeed\(\)" is never used$#'
identifier: public.method.unused
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/TicketCommunicationService.php
-
message: '#^Strict comparison using \!\=\= between non\-falsy\-string and '''' will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: modules/helpdesk/lib/Module/Helpdesk/Service/TicketCommunicationService.php
-
message: '#^Parameter \#1 \$array \(list\<array\{Name\: string, Type\: string, Job_Title\: string, E_Mail\: string, Phone_No\: string, Mobile_Phone_No\: string\}\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: 'modules/helpdesk/pages/helpdesk/debitor-contacts-data().php'
-
message: '#^Parameter \#1 \$array \(list\<non\-empty\-string\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 3
path: 'modules/helpdesk/pages/helpdesk/debitor-ticket-categories-data().php'
-
message: '#^Parameter \#1 \$array \(list\<array\{No\: string, Description\: string, Ticket_State\: string, state_variant\: ''neutral''\|''success''\|''warning'', Category_1_Description\: string, Support_User_Name\: string, Current_Contact_Name\: string, Created_On\: string, \.\.\.\}\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: 'modules/helpdesk/pages/helpdesk/debitor-tickets-data().php'
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array\<int, array\<string, mixed\>\> will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 2
path: modules/helpdesk/tests/Module/Helpdesk/Service/BcODataGatewayTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 6
path: modules/helpdesk/tests/Module/Helpdesk/Service/BcODataGatewayTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 3
path: modules/helpdesk/tests/Module/Helpdesk/Service/DebitorDetailServiceTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array\<int, array\<string, string\>\> will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 1
path: modules/helpdesk/tests/Module/Helpdesk/Service/TicketCommunicationServiceTest.php
-
message: '#^Public constant "MintyPHP\\Module\\Notifications\\NotificationsAuthorizationPolicy\:\:PERMISSION_KEY" is never used$#'
identifier: public.classConstant.unused
count: 1
path: modules/notifications/lib/Module/Notifications/NotificationsAuthorizationPolicy.php
-
message: '#^Parameter \#1 \$array \(list\<bool\|float\|int\|string\|null\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: modules/notifications/lib/Module/Notifications/Service/NotificationMessage.php
-
message: '#^Parameter \#1 \$array \(list\<bool\|float\|int\|string\|null\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: modules/notifications/lib/Module/Notifications/Service/NotificationService.php
-
message: '#^Public method "MintyPHP\\Module\\Notifications\\Service\\NotificationService\:\:createForTenantAdminUsers\(\)" is never used$#'
identifier: public.method.unused
@@ -2484,30 +2124,6 @@ parameters:
count: 1
path: modules/notifications/lib/Module/Notifications/Service/NotificationService.php
-
message: '#^Offset ''key'' on array\{key\: string, label\: string, allowed\: true, permission\: mixed\} on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 1
path: 'pages/admin/imports/index().php'
-
message: '#^Using nullsafe property access "\?\-\>value" on left side of \?\? is unnecessary\. Use \-\> instead\.$#'
identifier: nullsafe.neverNull
count: 1
path: 'pages/admin/scheduled-jobs/data().php'
-
message: '#^Strict comparison using \!\=\= between lowercase\-string&non\-empty\-string and '''' will always evaluate to true\.$#'
identifier: notIdentical.alwaysTrue
count: 1
path: 'pages/auth/login().php'
-
message: '#^Method MintyPHP\\Tests\\App\\Module\\InMemoryPermissionRepository\:\:create\(\) never returns null so it can be removed from the return type\.$#'
identifier: return.unusedType
count: 1
path: tests/App/Module/ModulePermissionSynchronizerTest.php
-
message: '#^Public method "MintyPHP\\Tests\\Architecture\\AuthHelpLinksContractFiles\:\:secondaryAuthPages\(\)" is never used$#'
identifier: public.method.unused
@@ -2550,18 +2166,6 @@ parameters:
count: 1
path: tests/Architecture/ListTitlebarContractFiles.php
-
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertIsString\(\) with string will always evaluate to true\.$#'
identifier: staticMethod.alreadyNarrowedType
count: 1
path: tests/Architecture/ModuleManifestContractTest.php
-
message: '#^Parameter \#1 \$array \(list\<string\>\) of array_values is already a list, call has no effect\.$#'
identifier: arrayValues.list
count: 1
path: tests/Architecture/ModuleUiContractTest.php
-
message: '#^Public method "MintyPHP\\Tests\\Architecture\\StatusTaxonomyContractFiles\:\:forbiddenLiteralPatterns\(\)" is never used$#'
identifier: public.method.unused
@@ -2646,12 +2250,6 @@ parameters:
count: 1
path: tests/Console/ModuleCommandsTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 2
path: tests/Http/ErrorHandlerTest.php
-
message: '#^Public constant "MintyPHP\\Tests\\Service\\Access\\TestMultiDependencyPolicy\:\:ABILITY" is never used$#'
identifier: public.classConstant.unused
@@ -2670,30 +2268,6 @@ parameters:
count: 1
path: tests/Service/Auth/AuthSessionTenantContextServiceTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array\<int, array\{action_key\: string, mac\: string, win\: string\}\> will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 1
path: tests/Service/Ui/HotkeyServiceTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsArray\(\) with array\<string\> will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 1
path: tests/Service/Ui/HotkeyServiceTest.php
-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertIsString\(\) with string will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 1
path: tests/Service/Ui/HotkeyServiceTest.php
-
message: '#^Offset ''minty_app_container'' on non\-empty\-array\<mixed\> on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 2
path: tests/Support/AppContainerIsolationTraitTest.php
-
message: '#^Public method "AnonymousClass1c441bccb4cb10bf3a2542eabe719765\:\:push\(\)" is never used$#'
identifier: public.method.unused

View File

@@ -268,7 +268,7 @@ final class InMemoryPermissionRepository implements PermissionRepositoryInterfac
return null;
}
public function create(array $data): ?int
public function create(array $data): int
{
$id = $this->nextId++;
$this->rows[$id] = [

View File

@@ -75,7 +75,6 @@ final class ModuleManifestContractTest extends AbstractModuleStructureContractTe
{
foreach (self::$modules as $module) {
foreach ($module['manifest']->requires as $index => $requiredId) {
self::assertIsString($requiredId);
self::assertNotEmpty(
trim($requiredId),
"Module '{$module['id']}' requires[{$index}] must be a non-empty string"

View File

@@ -95,7 +95,7 @@ final class ModuleUiContractTest extends AbstractModuleStructureContractTestCase
"Module '{$module['id']}' scheduler_jobs[{$index}] default_schedule_type invalid"
);
$allowedTypes = array_values($job['allowed_schedule_types']);
$allowedTypes = $job['allowed_schedule_types'];
self::assertNotEmpty($allowedTypes, "Module '{$module['id']}' scheduler_jobs[{$index}] allowed_schedule_types must be non-empty");
foreach ($allowedTypes as $allowedType) {
self::assertContains(

View File

@@ -99,8 +99,8 @@ class ErrorHandlerTest extends TestCase
{
putenv('APP_VENDOR_PHP_ISSUES_MODE=suppress_deprecations');
$result = ErrorHandler::handleError(E_DEPRECATED, 'deprecated', '/var/www/vendor/mintyphp/core/src/Router.php', 69);
$this->assertTrue($result);
ErrorHandler::handleError(E_DEPRECATED, 'deprecated', '/var/www/vendor/mintyphp/core/src/Router.php', 69);
$this->addToAssertionCount(1);
}
public function testHandleErrorSuppressesVendorWarningsOnlyInWarningMode(): void
@@ -115,8 +115,8 @@ class ErrorHandlerTest extends TestCase
}
putenv('APP_VENDOR_PHP_ISSUES_MODE=suppress_deprecations_warnings');
$result = ErrorHandler::handleError(E_WARNING, 'warning', '/var/www/vendor/mintyphp/core/src/Router.php', 69);
$this->assertTrue($result);
ErrorHandler::handleError(E_WARNING, 'warning', '/var/www/vendor/mintyphp/core/src/Router.php', 69);
$this->addToAssertionCount(1);
}
public function testHandleErrorNeverSuppressesNonVendorWarnings(): void

View File

@@ -11,7 +11,6 @@ class HotkeyServiceTest extends TestCase
{
$result = HotkeyService::list();
$this->assertIsArray($result);
$this->assertNotEmpty($result);
}
@@ -42,7 +41,6 @@ class HotkeyServiceTest extends TestCase
{
$result = HotkeyService::searchKeywords();
$this->assertIsArray($result);
$this->assertNotEmpty($result);
}
@@ -60,7 +58,6 @@ class HotkeyServiceTest extends TestCase
$result = HotkeyService::searchKeywords();
foreach ($result as $keyword) {
$this->assertIsString($keyword);
$this->assertNotEmpty($keyword);
}
}

View File

@@ -9,7 +9,7 @@ final class AppContainerIsolationTraitTest extends TestCase
{
public function testPushAndRestoreRoundTripKeepsOriginalGlobalContainer(): void
{
$original = $GLOBALS['minty_app_container'] ?? null;
$original = $GLOBALS['minty_app_container'];
self::assertInstanceOf(AppContainer::class, $original);
$harness = new class () {
@@ -29,16 +29,16 @@ final class AppContainerIsolationTraitTest extends TestCase
$replacement = new AppContainer();
$harness->push($replacement);
self::assertSame($replacement, $GLOBALS['minty_app_container'] ?? null);
self::assertSame($replacement, $GLOBALS['minty_app_container']);
$harness->restore();
self::assertSame($original, $GLOBALS['minty_app_container'] ?? null);
self::assertSame($original, $GLOBALS['minty_app_container']);
}
public function testMultiplePushesRestoreToInitialContainer(): void
{
$original = $GLOBALS['minty_app_container'] ?? null;
$original = $GLOBALS['minty_app_container'];
self::assertInstanceOf(AppContainer::class, $original);
$harness = new class () {
@@ -61,10 +61,10 @@ final class AppContainerIsolationTraitTest extends TestCase
$harness->push($first);
$harness->push($second);
self::assertSame($second, $GLOBALS['minty_app_container'] ?? null);
self::assertSame($second, $GLOBALS['minty_app_container']);
$harness->restore();
self::assertSame($original, $GLOBALS['minty_app_container'] ?? null);
self::assertSame($original, $GLOBALS['minty_app_container']);
}
}