diff --git a/lib/BackgroundJob/HookRetryJob.php b/lib/BackgroundJob/HookRetryJob.php index d42fb644d..5e3f66493 100644 --- a/lib/BackgroundJob/HookRetryJob.php +++ b/lib/BackgroundJob/HookRetryJob.php @@ -55,7 +55,7 @@ class HookRetryJob extends QueuedJob * Constructor for HookRetryJob * * @param ITimeFactory $time Time factory - * @param MagicMapper $objectEntityMapper Object mapper + * @param MagicMapper $objectEntityMapper Object mapper * @param SchemaMapper $schemaMapper Schema mapper * @param WorkflowEngineRegistry $engineRegistry Engine registry * @param CloudEventFormatter $cloudEventFormatter CloudEvent formatter diff --git a/lib/Controller/ConfigurationController.php b/lib/Controller/ConfigurationController.php index 0eb7d1a1e..8a47321f6 100644 --- a/lib/Controller/ConfigurationController.php +++ b/lib/Controller/ConfigurationController.php @@ -1242,7 +1242,8 @@ private function importFromSource(callable $fetchConfig, array $params, string $ $configuration = $this->configurationMapper->insert($configuration); - $msg = '[ConfigurationController] Created configuration'." entity with ID {$configuration->getId()} for app {$appId}"; + $configId = $configuration->getId(); + $msg = "[ConfigurationController] Created configuration entity with ID {$configId} for app {$appId}"; $this->logger->info( message: $msg, context: ['file' => __FILE__, 'line' => __LINE__] @@ -1267,7 +1268,8 @@ private function importFromSource(callable $fetchConfig, array $params, string $ // But we need to save the sync status. $this->configurationMapper->update($configuration); - $msg = '[ConfigurationController] Successfully imported'." configuration {$configuration->getTitle()} from {$sourceType}"; + $configTitle = $configuration->getTitle(); + $msg = "[ConfigurationController] Successfully imported configuration {$configTitle} from {$sourceType}"; $this->logger->info( message: $msg, context: ['file' => __FILE__, 'line' => __LINE__] diff --git a/lib/Controller/DeletedController.php b/lib/Controller/DeletedController.php index aea27661b..f10362f00 100644 --- a/lib/Controller/DeletedController.php +++ b/lib/Controller/DeletedController.php @@ -44,13 +44,13 @@ class DeletedController extends Controller /** * Constructor for the DeletedController * - * @param string $appName The name of the app - * @param IRequest $request The request object - * @param MagicMapper $objectEntityMapper The object entity mapper - * @param RegisterMapper $registerMapper The register mapper - * @param SchemaMapper $schemaMapper The schema mapper - * @param ObjectService $objectService The object service - * @param IUserSession $userSession The user session + * @param string $appName The name of the app + * @param IRequest $request The request object + * @param MagicMapper $objectEntityMapper The object entity mapper + * @param RegisterMapper $registerMapper The register mapper + * @param SchemaMapper $schemaMapper The schema mapper + * @param ObjectService $objectService The object service + * @param IUserSession $userSession The user session * * @return void */ diff --git a/lib/Controller/HealthController.php b/lib/Controller/HealthController.php index 5dbe13e0c..1e250c02e 100644 --- a/lib/Controller/HealthController.php +++ b/lib/Controller/HealthController.php @@ -78,10 +78,18 @@ public function index(): JSONResponse // Check filesystem. $checks['filesystem'] = $this->checkFilesystem(); if ($checks['filesystem'] !== 'ok') { - $status = ($status === 'error') ? 'error' : 'degraded'; + if ($status === 'error') { + $status = 'error'; + } else { + $status = 'degraded'; + } } - $httpStatus = ($status === 'ok') ? Http::STATUS_OK : Http::STATUS_SERVICE_UNAVAILABLE; + if ($status === 'ok') { + $httpStatus = Http::STATUS_OK; + } else { + $httpStatus = Http::STATUS_SERVICE_UNAVAILABLE; + } return new JSONResponse( [ @@ -109,7 +117,7 @@ private function checkDatabase(): string return 'ok'; } catch (\Exception $e) { $this->logger->error('[HealthController] Database check failed', ['error' => $e->getMessage()]); - return 'failed: ' . $e->getMessage(); + return 'failed: '.$e->getMessage(); } }//end checkDatabase() @@ -121,7 +129,7 @@ private function checkDatabase(): string private function checkFilesystem(): string { try { - $tmpFile = sys_get_temp_dir() . '/openregister_health_' . getmypid(); + $tmpFile = sys_get_temp_dir().'/openregister_health_'.getmypid(); $written = file_put_contents($tmpFile, 'health'); if ($written === false) { return 'failed: cannot write to temp directory'; @@ -131,7 +139,7 @@ private function checkFilesystem(): string return 'ok'; } catch (\Exception $e) { - return 'failed: ' . $e->getMessage(); + return 'failed: '.$e->getMessage(); } }//end checkFilesystem() diff --git a/lib/Controller/MetricsController.php b/lib/Controller/MetricsController.php index 28c3c079b..4fa23980f 100644 --- a/lib/Controller/MetricsController.php +++ b/lib/Controller/MetricsController.php @@ -91,7 +91,7 @@ private function collectMetrics(): string $lines[] = '# HELP openregister_info Application information'; $lines[] = '# TYPE openregister_info gauge'; - $lines[] = 'openregister_info{version="' . $version . '",php_version="' . $phpVersion . '"} 1'; + $lines[] = 'openregister_info{version="'.$version.'",php_version="'.$phpVersion.'"} 1'; $lines[] = ''; // App up gauge. @@ -101,40 +101,40 @@ private function collectMetrics(): string $lines[] = ''; // Registers total. - $registersTotal = $this->countTable('openregister_registers'); + $registersTotal = $this->countTable(table: 'openregister_registers'); $lines[] = '# HELP openregister_registers_total Total number of registers'; $lines[] = '# TYPE openregister_registers_total gauge'; - $lines[] = 'openregister_registers_total ' . $registersTotal; + $lines[] = 'openregister_registers_total '.$registersTotal; $lines[] = ''; // Schemas total. - $schemasTotal = $this->countTable('openregister_schemas'); + $schemasTotal = $this->countTable(table: 'openregister_schemas'); $lines[] = '# HELP openregister_schemas_total Total number of schemas'; $lines[] = '# TYPE openregister_schemas_total gauge'; - $lines[] = 'openregister_schemas_total ' . $schemasTotal; + $lines[] = 'openregister_schemas_total '.$schemasTotal; $lines[] = ''; // Objects total (by register and schema). - $lines[] = '# HELP openregister_objects_total Total objects by register and schema'; - $lines[] = '# TYPE openregister_objects_total gauge'; + $lines[] = '# HELP openregister_objects_total Total objects by register and schema'; + $lines[] = '# TYPE openregister_objects_total gauge'; $objectCounts = $this->getObjectCountsByRegisterAndSchema(); foreach ($objectCounts as $row) { - $register = $this->sanitizeLabel($row['register_name'] ?? 'unknown'); - $schema = $this->sanitizeLabel($row['schema_name'] ?? 'unknown'); + $register = $this->sanitizeLabel(value: $row['register_name'] ?? 'unknown'); + $schema = $this->sanitizeLabel(value: $row['schema_name'] ?? 'unknown'); $count = (int) $row['object_count']; - $lines[] = 'openregister_objects_total{register="' . $register . '",schema="' . $schema . '"} ' . $count; + $lines[] = 'openregister_objects_total{register="'.$register.'",schema="'.$schema.'"} '.$count; } $lines[] = ''; // Search requests total (from metrics table if it exists). - $searchCount = $this->countMetricsByType('search_'); + $searchCount = $this->countMetricsByType(typePrefix: 'search_'); $lines[] = '# HELP openregister_search_requests_total Total search requests'; $lines[] = '# TYPE openregister_search_requests_total counter'; - $lines[] = 'openregister_search_requests_total ' . $searchCount; + $lines[] = 'openregister_search_requests_total '.$searchCount; $lines[] = ''; - return implode("\n", $lines) . "\n"; + return implode("\n", $lines)."\n"; }//end collectMetrics() /** @@ -156,7 +156,7 @@ private function countTable(string $table): int return (int) ($row['cnt'] ?? 0); } catch (\Exception $e) { - $this->logger->warning('[MetricsController] Failed to count table ' . $table, ['error' => $e->getMessage()]); + $this->logger->warning('[MetricsController] Failed to count table '.$table, ['error' => $e->getMessage()]); return 0; } }//end countTable() @@ -201,7 +201,7 @@ private function countMetricsByType(string $typePrefix): int $qb = $this->db->getQueryBuilder(); $qb->select($qb->func()->count('*', 'cnt')) ->from('openregister_metrics') - ->where($qb->expr()->like('metric_type', $qb->createNamedParameter($typePrefix . '%'))); + ->where($qb->expr()->like('metric_type', $qb->createNamedParameter($typePrefix.'%'))); $result = $qb->executeQuery(); $row = $result->fetch(); diff --git a/lib/Controller/ObjectsController.php b/lib/Controller/ObjectsController.php index 93679511a..b0fa8c8c8 100644 --- a/lib/Controller/ObjectsController.php +++ b/lib/Controller/ObjectsController.php @@ -93,21 +93,21 @@ class ObjectsController extends Controller /** * Constructor for the ObjectsController * - * @param string $appName The name of the app - * @param IRequest $request The request object - * @param IAppConfig $config The app configuration object - * @param IAppManager $appManager The app manager - * @param ContainerInterface $container The DI container - * @param RegisterMapper $registerMapper The register mapper - * @param SchemaMapper $schemaMapper The schema mapper - * @param AuditTrailMapper $auditTrailMapper The audit trail mapper - * @param ObjectService $objectService The object service - * @param IUserSession $userSession The user session - * @param IGroupManager $groupManager The group manager - * @param ExportService $exportService The export service - * @param ImportService $importService The import service - * @param WebhookService $webhookService The webhook service (optional) - * @param LoggerInterface $logger The logger (optional) + * @param string $appName The name of the app + * @param IRequest $request The request object + * @param IAppConfig $config The app configuration object + * @param IAppManager $appManager The app manager + * @param ContainerInterface $container The DI container + * @param RegisterMapper $registerMapper The register mapper + * @param SchemaMapper $schemaMapper The schema mapper + * @param AuditTrailMapper $auditTrailMapper The audit trail mapper + * @param ObjectService $objectService The object service + * @param IUserSession $userSession The user session + * @param IGroupManager $groupManager The group manager + * @param ExportService $exportService The export service + * @param ImportService $importService The import service + * @param WebhookService $webhookService The webhook service (optional) + * @param LoggerInterface $logger The logger (optional) * * @return void * @@ -525,7 +525,7 @@ private function getConfig(?string $_register=null, ?string $_schema=null, ?arra 'offset' => $offset, 'page' => $page, 'filters' => $params, - 'sort' => $this->normalizeOrderParameter($params['order'] ?? $params['_order'] ?? []), + 'sort' => $this->normalizeOrderParameter(order: $params['order'] ?? $params['_order'] ?? []), '_search' => ($params['_search'] ?? null), '_extend' => $this->normalizeExtendParameter(extend: $params['extend'] ?? $params['_extend'] ?? null), '_fields' => ($params['fields'] ?? $params['_fields'] ?? null), @@ -955,8 +955,8 @@ public function index(string $register, string $schema, ObjectService $objectSer $rbac = filter_var($params['rbac'] ?? true, FILTER_VALIDATE_BOOLEAN); // Check both _multi and multi params (URL uses _multi, but we also support multi). $multiExplicitlySet = isset($params['_multi']) || isset($params['multi']); - $multi = filter_var($params['_multi'] ?? $params['multi'] ?? true, FILTER_VALIDATE_BOOLEAN); - $deleted = filter_var($params['deleted'] ?? false, FILTER_VALIDATE_BOOLEAN); + $multi = filter_var($params['_multi'] ?? $params['multi'] ?? true, FILTER_VALIDATE_BOOLEAN); + $deleted = filter_var($params['deleted'] ?? false, FILTER_VALIDATE_BOOLEAN); // Check if magic mapping is enabled for this register+schema. $registerEntity = $resolved['registerEntity'] ?? null; diff --git a/lib/Controller/RegistersController.php b/lib/Controller/RegistersController.php index 6c6748f63..5cd4e0051 100644 --- a/lib/Controller/RegistersController.php +++ b/lib/Controller/RegistersController.php @@ -151,7 +151,7 @@ class RegistersController extends Controller * @param string $appName Application name * @param IRequest $request HTTP request object * @param RegisterService $registerService Register service for business logic - * @param MagicMapper $objectEntityMapper Object entity mapper for database operations + * @param MagicMapper $objectEntityMapper Object entity mapper for database operations * @param UploadService $uploadService Upload service for file uploads * @param LoggerInterface $logger Logger for error tracking * @param IUserSession $userSession User session service @@ -303,7 +303,9 @@ public function index(): JSONResponse schemas: $expandedSchemas ); - $msg = '[RegistersController] Schema counts for register '.$register['id'].': '.json_encode($schemaCounts); + $registerId = $register['id']; + $countsJson = json_encode($schemaCounts); + $msg = "[RegistersController] Schema counts for register {$registerId}: {$countsJson}"; $this->logger->debug( message: $msg, context: ['file' => __FILE__, 'line' => __LINE__] @@ -326,7 +328,8 @@ public function index(): JSONResponse $schema['stats'] = [ 'objects' => $schemaCounts[$schemaId], ]; - $msg = '[RegistersController] Set stats for schema '."{$schemaId}: ".json_encode($schema['stats']); + $statsJson = json_encode($schema['stats']); + $msg = "[RegistersController] Set stats for schema {$schemaId}: {$statsJson}"; $this->logger->debug( message: $msg, context: ['file' => __FILE__, 'line' => __LINE__] diff --git a/lib/Controller/SchemasController.php b/lib/Controller/SchemasController.php index 1a91ce389..997bc74c0 100644 --- a/lib/Controller/SchemasController.php +++ b/lib/Controller/SchemasController.php @@ -82,7 +82,7 @@ class SchemasController extends Controller * @param IRequest $request HTTP request object * @param IAppConfig $config App configuration for settings * @param SchemaMapper $schemaMapper Schema mapper for database operations - * @param MagicMapper $objectEntityMapper Object entity mapper for object queries + * @param MagicMapper $objectEntityMapper Object entity mapper for object queries * @param DownloadService $downloadService Download service for file downloads * @param UploadService $uploadService Upload service for file uploads * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for log statistics diff --git a/lib/Db/AbstractObjectMapper.php b/lib/Db/AbstractObjectMapper.php index 0d2c7b9e6..83b8335a5 100644 --- a/lib/Db/AbstractObjectMapper.php +++ b/lib/Db/AbstractObjectMapper.php @@ -57,8 +57,8 @@ abstract class AbstractObjectMapper * @param Register|null $register Optional register to filter by. * @param Schema|null $schema Optional schema to filter by. * @param bool $includeDeleted Whether to include deleted objects. - * @param bool $_rbac Whether to apply RBAC checks (default: true). - * @param bool $_multitenancy Whether to apply multitenancy filtering (default: true). + * @param bool $_rbac Whether to apply RBAC checks (default: true). + * @param bool $_multitenancy Whether to apply multitenancy filtering (default: true). * * @return ObjectEntity The found object. * @@ -300,8 +300,8 @@ abstract public function getFacetableFieldsFromSchemas(array $baseQuery=[]): arr * * @param array $query Query parameters. * @param string|null $activeOrgUuid Active organisation UUID. - * @param bool $_rbac Whether to apply RBAC checks. - * @param bool $_multitenancy Whether to apply multitenancy filtering. + * @param bool $_rbac Whether to apply RBAC checks. + * @param bool $_multitenancy Whether to apply multitenancy filtering. * @param array|null $ids Array of IDs or UUIDs to filter by. * @param string|null $uses Value that must be present in relations. * @@ -325,8 +325,8 @@ abstract public function searchObjects( * * @param array $query Query parameters. * @param string|null $activeOrgUuid Active organisation UUID. - * @param bool $_rbac Whether to apply RBAC checks. - * @param bool $_multitenancy Whether to apply multitenancy filtering. + * @param bool $_rbac Whether to apply RBAC checks. + * @param bool $_multitenancy Whether to apply multitenancy filtering. * @param array|null $ids Array of IDs or UUIDs to filter by. * @param string|null $uses Value that must be present in relations. * diff --git a/lib/Db/AuditTrailMapper.php b/lib/Db/AuditTrailMapper.php index 9a2b9f733..f94ffe110 100644 --- a/lib/Db/AuditTrailMapper.php +++ b/lib/Db/AuditTrailMapper.php @@ -61,7 +61,7 @@ class AuditTrailMapper extends QBMapper /** * Constructor for the AuditTrailMapper * - * @param IDBConnection $db The database connection + * @param IDBConnection $db The database connection * @param \Psr\Container\ContainerInterface $container DI container for lazy mapper resolution */ public function __construct( @@ -439,7 +439,7 @@ public function revertObject($identifier, $until=null, bool $overwriteVersion=fa { // Get the current object (lazy-resolved to avoid circular DI). $objectMapper = $this->container->get(MagicMapper::class); - $object = $objectMapper->find($identifier); + $object = $objectMapper->find($identifier); // Get audit trail entries until the specified point. $auditTrails = $this->findByObjectUntil( diff --git a/lib/Db/MagicMapper.php b/lib/Db/MagicMapper.php index 09b858d3f..c05080209 100644 --- a/lib/Db/MagicMapper.php +++ b/lib/Db/MagicMapper.php @@ -253,29 +253,34 @@ class MagicMapper extends AbstractObjectMapper */ private ?bool $hasPgTrgm = null; + /** + * Constructor call counter for circular dependency detection. + * + * @var integer + */ + private static int $constructCount = 0; + /** * Constructor for MagicMapper service * * Initializes the service with required dependencies for database operations, * schema and register management, configuration handling, logging, and specialized handlers. * - * @param IDBConnection $db Database connection for table operations - * @param SchemaMapper $schemaMapper Mapper for schema operations - * @param RegisterMapper $registerMapper Mapper for register operations - * @param IConfig $config Nextcloud config for settings - * @param IEventDispatcher $eventDispatcher Event dispatcher for audit trail events - * @param IUserSession $userSession User session for authentication context - * @param IGroupManager $groupManager Group manager for RBAC operations - * @param IUserManager $userManager User manager for user operations - * @param IAppConfig $appConfig App configuration for feature flags - * @param LoggerInterface $logger Logger for debugging and monitoring - * @param SettingsService $settingsService Settings service for configuration - * @param ContainerInterface $container Container for lazy loading services + * @param IDBConnection $db Database connection for table operations + * @param SchemaMapper $schemaMapper Mapper for schema operations + * @param RegisterMapper $registerMapper Mapper for register operations + * @param IConfig $config Nextcloud config for settings + * @param IEventDispatcher $eventDispatcher Event dispatcher for audit trail events + * @param IUserSession $userSession User session for authentication context + * @param IGroupManager $groupManager Group manager for RBAC operations + * @param IUserManager $userManager User manager for user operations + * @param IAppConfig $appConfig App configuration for feature flags + * @param LoggerInterface $logger Logger for debugging and monitoring + * @param SettingsService $settingsService Settings service for configuration + * @param ContainerInterface $container Container for lazy loading services * * @SuppressWarnings(PHPMD.ExcessiveParameterList) Nextcloud DI requires constructor injection */ - private static int $constructCount = 0; - public function __construct( private readonly IDBConnection $db, private readonly SchemaMapper $schemaMapper, @@ -293,9 +298,14 @@ public function __construct( self::$constructCount++; file_put_contents('/tmp/or-debug.log', "MagicMapper::__construct #".self::$constructCount."\n", FILE_APPEND); if (self::$constructCount > 2) { - file_put_contents('/tmp/or-debug.log', "CIRCULAR! Stack:\n".(new \Exception())->getTraceAsString()."\n", FILE_APPEND); + file_put_contents( + '/tmp/or-debug.log', + "CIRCULAR! Stack:\n".(new \Exception())->getTraceAsString()."\n", + FILE_APPEND + ); return; } + // Initialize specialized handlers for modular functionality. $this->initializeHandlers(); }//end __construct() @@ -872,8 +882,10 @@ public function getSimpleFacetsFromRegisterSchemaTable(array $query, Register $r schemaSlug: $schema->getSlug() ); if ($isMagicEnabled === true) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- log message string cannot be shortened + $infoMsg = '[MagicMapper] Register+schema table does not exist but magic mapping enabled, creating table for facets'; $this->logger->info( - message: '[MagicMapper] Register+schema table does not exist but magic mapping enabled, creating table for facets', + message: $infoMsg, context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -1101,8 +1113,10 @@ private function searchAcrossMultipleTablesWithUnion(array $query, array $regist schemaSlug: $schema->getSlug() ); if ($isMagicEnabled === true) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- log message string cannot be shortened + $infoMsg = '[MagicMapper] Register+schema table does not exist but magic mapping enabled, creating table for cross-search'; $this->logger->info( - message: '[MagicMapper] Register+schema table does not exist but magic mapping enabled, creating table for cross-search', + message: $infoMsg, context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -1601,6 +1615,7 @@ private function checkTableExistsInDatabase(string $tableName): bool $isPostgres = stripos($platform::class, 'PostgreSQL') !== false; if ($isPostgres === true) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- SQL query cannot be shortened $sql = "SELECT 1 FROM information_schema.tables WHERE table_name = ? AND table_schema = current_schema() LIMIT 1"; } else { // MySQL/MariaDB/SQLite. @@ -1862,7 +1877,9 @@ public function syncTableForRegisterSchema(Register $register, Schema $schema): // Calculate regular properties (excluding metadata). $regularPropCount = count($requiredColumns) - $metadataCount; - $unchangedCount = count($currentColumns) - count($columnStats['columnsAdded']) - count($columnStats['columnsDropped']); + $addedCount = count($columnStats['columnsAdded']); + $droppedCount = count($columnStats['columnsDropped']); + $unchangedCount = count($currentColumns) - $addedCount - $droppedCount; $result = [ 'success' => true, @@ -3152,8 +3169,10 @@ private function prepareObjectDataForTable(array $objectData, Register $register && (($propertyConfig['items']['type'] ?? '') === 'file'); if ($isFileProperty === true && is_string($value) === true && strpos($value, 'data:') === 0) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- log message string cannot be shortened + $warnMsg = '[MagicMapper] File property contains unprocessed base64 data URL - setting to null to prevent DB error'; $this->logger->warning( - message: '[MagicMapper] File property contains unprocessed base64 data URL - setting to null to prevent DB error', + message: $warnMsg, context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -3169,8 +3188,10 @@ private function prepareObjectDataForTable(array $objectData, Register $register $cleanedArray = []; foreach ($value as $item) { if (is_string($item) === true && strpos($item, 'data:') === 0) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- log message string cannot be shortened + $warnMsg = '[MagicMapper] Array file item contains unprocessed base64 data URL - skipping item'; $this->logger->warning( - message: '[MagicMapper] Array file item contains unprocessed base64 data URL - skipping item', + message: $warnMsg, context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -4585,8 +4606,8 @@ public function isMagicMappingEnabledForSchema(Schema $schema): bool * @param string|int $identifier Object identifier (ID, UUID, slug, or URI). * @param Register $register The register context. * @param Schema $schema The schema context. - * @param bool $_rbac Whether to apply RBAC. - * @param bool $_multitenancy Whether to apply multi-tenancy. + * @param bool $_rbac Whether to apply RBAC. + * @param bool $_multitenancy Whether to apply multi-tenancy. * @param bool $includeDeleted Whether to include soft-deleted objects. * * @throws \OCP\AppFramework\Db\DoesNotExistException If object not found. @@ -6247,7 +6268,8 @@ public function findByRelationBatchInSchema( // PostgreSQL: Handle both array and object formats. // - For arrays: use @> containment operator (can't use ? as it conflicts with PDO placeholders). // - For objects: use jsonb_each_text to search values. - $arrSql = "(jsonb_typeof(_relations)='array' AND _relations @> to_jsonb(?::text))"; + $arrSql = "(jsonb_typeof(_relations)='array' AND _relations @> to_jsonb(?::text))"; + // phpcs:ignore Generic.Files.LineLength.TooLong -- SQL query cannot be shortened $objSql = "(jsonb_typeof(_relations)='object' AND EXISTS(SELECT 1 FROM jsonb_each_text(_relations) kv WHERE kv.value=?))"; $conditions[] = "({$arrSql} OR {$objSql})"; $params[] = $uuid; @@ -6750,8 +6772,8 @@ private function getResolvedRegisterAndSchema( * @param Register|null $register Optional register to filter by. * @param Schema|null $schema Optional schema to filter by. * @param bool $includeDeleted Whether to include deleted objects. - * @param bool $_rbac Whether to apply RBAC checks (default: true). - * @param bool $_multitenancy Whether to apply multitenancy filtering (default: true). + * @param bool $_rbac Whether to apply RBAC checks (default: true). + * @param bool $_multitenancy Whether to apply multitenancy filtering (default: true). * * @return ObjectEntity The found object. * @@ -6929,7 +6951,7 @@ public function findBySchema(int $schemaId): array register: $register, schema: $schema ); - $results = array_merge($results, $entities); + $results = array_merge($results, $entities); } catch (\Exception $e) { $this->logger->warning( message: '[MagicMapper] Failed to search table for findBySchema', @@ -6941,8 +6963,8 @@ public function findBySchema(int $schemaId): array 'error' => $e->getMessage(), ] ); - } - } + }//end try + }//end foreach return $results; }//end findBySchema() @@ -7037,8 +7059,8 @@ public function update( ] ); $oldEntity = $entity; - } - } + }//end try + }//end if if ($register === null || $schema === null) { throw new Exception('Cannot update object without register and schema context'); @@ -7211,11 +7233,11 @@ public function ultraFastBulkSave( ); $allResults = array_merge($allResults, $groupResults); - } + }//end foreach return $allResults; - } - } + }//end if + }//end if return $this->ultraFastBulkSaveSingleSchema( insertObjects: $insertObjects, @@ -7269,7 +7291,7 @@ private function ultraFastBulkSaveSingleSchema( ); } } - } + }//end if if ($register === null || $schema === null) { throw new Exception('Cannot bulk save without register and schema context'); @@ -7341,7 +7363,7 @@ public function getStatistics( if (in_array($pairRegisterId, $registerId, true) === false) { continue; } - } elseif ($pairRegisterId !== $registerId) { + } else if ($pairRegisterId !== $registerId) { continue; } } @@ -7352,7 +7374,7 @@ public function getStatistics( if (in_array($pairSchemaId, $schemaId, true) === false) { continue; } - } elseif ($pairSchemaId !== $schemaId) { + } else if ($pairSchemaId !== $schemaId) { continue; } } @@ -7360,7 +7382,7 @@ public function getStatistics( // Apply exclusion filter. $excluded = false; foreach ($exclude as $ex) { - if (isset($ex['register'], $ex['schema']) + if (isset($ex['register'], $ex['schema']) === true && (int) $ex['register'] === $pairRegisterId && (int) $ex['schema'] === $pairSchemaId ) { @@ -7377,7 +7399,7 @@ public function getStatistics( $register = $this->registerMapper->find($pairRegisterId, _multitenancy: false, _rbac: false); $schema = $this->schemaMapper->find($pairSchemaId, _multitenancy: false, _rbac: false); - $count = $this->countObjectsInRegisterSchemaTable( + $count = $this->countObjectsInRegisterSchemaTable( query: [], register: $register, schema: $schema @@ -7386,7 +7408,7 @@ public function getStatistics( } catch (\Exception $e) { // Skip tables that can't be queried. } - } + }//end foreach return [ 'total' => $total, @@ -7412,7 +7434,7 @@ public function getRegisterChartData(?int $registerId=null, ?int $schemaId=null) $labels = []; $series = []; - $allPairs = $this->getAllRegisterSchemaPairs(); + $allPairs = $this->getAllRegisterSchemaPairs(); $registerCounts = []; foreach ($allPairs as $pair) { @@ -7446,7 +7468,7 @@ public function getRegisterChartData(?int $registerId=null, ?int $schemaId=null) } catch (\Exception $e) { // Skip. } - } + }//end foreach foreach ($registerCounts as $name => $count) { $labels[] = $name; @@ -7471,7 +7493,7 @@ public function getSchemaChartData(?int $registerId=null, ?int $schemaId=null): $labels = []; $series = []; - $allPairs = $this->getAllRegisterSchemaPairs(); + $allPairs = $this->getAllRegisterSchemaPairs(); $schemaCounts = []; foreach ($allPairs as $pair) { @@ -7505,7 +7527,7 @@ public function getSchemaChartData(?int $registerId=null, ?int $schemaId=null): } catch (\Exception $e) { // Skip. } - } + }//end foreach foreach ($schemaCounts as $name => $count) { $labels[] = $name; @@ -7644,8 +7666,8 @@ private function getSimpleFacetsMultiSchema(array $query, array $registerIds, ar message: '[MagicMapper] Failed to find schema for multi-schema facets', context: ['file' => __FILE__, 'line' => __LINE__, 'schemaId' => $sId, 'error' => $e->getMessage()] ); - } - } + }//end try + }//end foreach if (empty($registerSchemaPairs) === true) { return []; @@ -7702,7 +7724,7 @@ public function getFacetableFieldsFromSchemas(array $baseQuery=[]): array } catch (\Exception $e) { // Skip missing schemas. } - } + }//end foreach return $facetableFields; }//end getFacetableFieldsFromSchemas() @@ -7712,8 +7734,8 @@ public function getFacetableFieldsFromSchemas(array $baseQuery=[]): array * * @param array $query Search query * @param string|null $activeOrgUuid Organisation UUID - * @param bool $_rbac Apply RBAC - * @param bool $_multitenancy Apply multitenancy + * @param bool $_rbac Apply RBAC + * @param bool $_multitenancy Apply multitenancy * @param array|null $ids Specific IDs * @param string|null $uses Uses filter * @@ -7766,8 +7788,8 @@ public function searchObjects( * * @param array $query Search query * @param string|null $activeOrgUuid Organisation UUID - * @param bool $_rbac Apply RBAC - * @param bool $_multitenancy Apply multitenancy + * @param bool $_rbac Apply RBAC + * @param bool $_multitenancy Apply multitenancy * @param array|null $ids Specific IDs * @param string|null $uses Uses filter * @@ -7854,7 +7876,7 @@ public function countAll(?array $filters=null, ?Schema $schema=null, ?Register $ } catch (\Exception $e) { // Skip. } - } + }//end foreach return $total; }//end countAll() @@ -7899,14 +7921,14 @@ public function getMaxAllowedPacketSize(): int * @param array $searchQuery Query for search (with _limit, _offset). * @param array $countQuery Query for count (without pagination). * @param string|null $activeOrgUuid Active organization UUID. - * @param bool $_rbac Whether to apply RBAC. - * @param bool $_multitenancy Whether to apply multitenancy. + * @param bool $_rbac Whether to apply RBAC. + * @param bool $_multitenancy Whether to apply multitenancy. * @param array|null $ids Optional ID filter. * @param string|null $uses Optional uses filter. * * @return array{results: ObjectEntity[], total: int, register: ?array, schema: ?array} * - * @SuppressWarnings(PHPMD.BooleanArgumentFlag) Flags control security filtering behavior + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) Flags control security filtering behavior * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -8018,7 +8040,7 @@ public function searchObjectsPaginated( 'count_ms' => $countTime, ], ]; - } + }//end if // ID search across all tables. $queryIds = $searchQuery['_ids'] ?? null; @@ -8091,18 +8113,19 @@ public function searchObjectsPaginated( * @param array $registerIds Register IDs to search. * @param array $schemaIds Array of schema IDs to search. * @param string|null $activeOrgUuid Organisation UUID. - * @param bool $_rbac Apply RBAC. - * @param bool $_multitenancy Apply multitenancy. + * @param bool $_rbac Apply RBAC. + * @param bool $_multitenancy Apply multitenancy. * @param array|null $ids Specific IDs to filter. * @param string|null $uses Uses filter. * * @return array{results: ObjectEntity[], total: int, registers: array, schemas: array} * - * @SuppressWarnings(PHPMD.BooleanArgumentFlag) Flags control security filtering behavior + * @SuppressWarnings(PHPMD.BooleanArgumentFlag) + * Flags control security filtering behavior * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @psalm-suppress UnusedParam Parameters reserved for future per-schema security filtering. + * @psalm-suppress UnusedParam Reserved for future per-schema security filtering. */ private function searchObjectsPaginatedMultiSchema( array $searchQuery, @@ -8176,8 +8199,8 @@ private function searchObjectsPaginatedMultiSchema( $registerSchemaPairs[] = ['register' => $matchedRegister, 'schema' => $schema]; - $schemaCountQuery = $countQuery; - $schemaCountQuery['_rbac'] = $_rbac; + $schemaCountQuery = $countQuery; + $schemaCountQuery['_rbac'] = $_rbac; $schemaCountQuery['_multitenancy'] = $_multitenancy; $schemaCount = $this->countObjectsInRegisterSchemaTable( query: $schemaCountQuery, @@ -8190,8 +8213,8 @@ private function searchObjectsPaginatedMultiSchema( message: '[MagicMapper] Failed to load schema for multi-schema search', context: ['file' => __FILE__, 'line' => __LINE__, 'schemaId' => $sId, 'error' => $e->getMessage()] ); - } - } + }//end try + }//end foreach if (empty($registerSchemaPairs) === true) { return [ @@ -8204,8 +8227,8 @@ private function searchObjectsPaginatedMultiSchema( ]; } - $unionQuery = $searchQuery; - $unionQuery['_rbac'] = $_rbac; + $unionQuery = $searchQuery; + $unionQuery['_rbac'] = $_rbac; $unionQuery['_multitenancy'] = $_multitenancy; $results = $this->searchAcrossMultipleTables( @@ -8228,7 +8251,7 @@ private function searchObjectsPaginatedMultiSchema( * * @param array $objects Array of ObjectEntity objects to filter. * @param array $schemasCache Cache of schema data by ID. - * @param bool $_rbac Whether RBAC is enabled. + * @param bool $_rbac Whether RBAC is enabled. * * @return array Filtered array of ObjectEntity objects. * @@ -8289,7 +8312,7 @@ private function filterBySchemaRbac(array $objects, array &$schemasCache, bool $ ) { $filtered[] = $object; } - } + }//end foreach return $filtered; }//end filterBySchemaRbac() @@ -8299,7 +8322,7 @@ private function filterBySchemaRbac(array $objects, array &$schemasCache, bool $ * * @param array $results Array of ObjectEntity results from the storage search. * @param array $searchQuery The original search query parameters (for _limit/_offset). - * @param bool $_rbac Whether to apply RBAC filtering. + * @param bool $_rbac Whether to apply RBAC filtering. * * @return array{results: array, total: int, registers: array, schemas: array} */ @@ -8333,7 +8356,7 @@ private function getGlobalSearchResult(array $results, array $searchQuery, bool // Skip if schema not found. } } - } + }//end foreach $results = $this->filterBySchemaRbac(objects: $results, schemasCache: $schemasCache, _rbac: $_rbac); @@ -8374,8 +8397,8 @@ private function getGlobalSearchResult(array $results, array $searchQuery, bool * @param array $searchQuery The search query parameters (must contain _search). * @param array $countQuery The count query parameters. * @param string|null $activeOrgUuid The active organisation UUID for multitenancy. - * @param bool $_rbac Whether to apply RBAC filtering. - * @param bool $_multitenancy Whether to apply multitenancy filtering. + * @param bool $_rbac Whether to apply RBAC filtering. + * @param bool $_multitenancy Whether to apply multitenancy filtering. * * @return array Search results with pagination info. * @@ -8396,8 +8419,8 @@ private function searchObjectsGloballyBySearch( foreach ($idPairs as $idPair) { try { - $regId = $idPair['registerId']; - $schId = $idPair['schemaId']; + $regId = $idPair['registerId']; + $schId = $idPair['schemaId']; $register = $this->registerMapper->find($regId, _multitenancy: false, _rbac: false); $schema = $this->schemaMapper->find($schId, _multitenancy: false, _rbac: false); @@ -8414,7 +8437,7 @@ private function searchObjectsGloballyBySearch( } catch (\Exception $e) { continue; } - } + }//end foreach if (empty($registerSchemaPairs) === true) { return [ @@ -8426,8 +8449,8 @@ private function searchObjectsGloballyBySearch( ]; } - $unionQuery = $searchQuery; - $unionQuery['_rbac'] = $_rbac; + $unionQuery = $searchQuery; + $unionQuery['_rbac'] = $_rbac; $unionQuery['_multitenancy'] = $_multitenancy; $results = $this->searchAcrossMultipleTables( diff --git a/lib/Db/MagicMapper/MagicFacetHandler.php b/lib/Db/MagicMapper/MagicFacetHandler.php index ad2940700..c4cc1dc0a 100644 --- a/lib/Db/MagicMapper/MagicFacetHandler.php +++ b/lib/Db/MagicMapper/MagicFacetHandler.php @@ -169,7 +169,7 @@ class MagicFacetHandler /** * Whether lazy dependencies have been resolved. * - * @var bool + * @var boolean */ private bool $lazyResolved = false; @@ -235,7 +235,7 @@ private function resolveLazyDependencies(): void } try { - $cacheFactory = $this->container->get(ICacheFactory::class); + $cacheFactory = $this->container->get(ICacheFactory::class); $this->cacheFactory = $cacheFactory; $this->distLabelCache = $cacheFactory->createDistributed('openregister_facet_labels'); } catch (\Exception $e) { @@ -1960,8 +1960,9 @@ private function batchResolveUuidLabels( ); $this->warmedFields[$fieldCacheKey] = true; } catch (\Exception $e) { + $eMsg = $e->getMessage(); $this->logger->warning( - message: '[MagicFacetHandler] Failed to persist facet labels to distributed cache: '.$e->getMessage(), + message: "[MagicFacetHandler] Failed to persist facet labels to distributed cache: {$eMsg}", context: ['file' => __FILE__, 'line' => __LINE__] ); } diff --git a/lib/Db/MagicMapper/MagicSearchHandler.php b/lib/Db/MagicMapper/MagicSearchHandler.php index 5d0b64dc0..b3c2f9b9d 100644 --- a/lib/Db/MagicMapper/MagicSearchHandler.php +++ b/lib/Db/MagicMapper/MagicSearchHandler.php @@ -182,7 +182,11 @@ public function searchObjects(array $query, Register $register, Schema $schema, // The _order parameter may arrive as a JSON string from URL query params. if (is_string($order) === true) { $decoded = json_decode($order, true); - $order = is_array($decoded) === true ? $decoded : []; + if (is_array($decoded) === true) { + $order = $decoded; + } else { + $order = []; + } } $count = $query['_count'] ?? false; @@ -273,14 +277,14 @@ public function buildFilteredQuery(array $query, Schema $schema, string $tableNa $search = $query['_search'] ?? null; $includeDeleted = $query['_includeDeleted'] ?? false; $ids = $query['_ids'] ?? null; - $_rbac = $query['_rbac'] ?? true; - $_multitenancy = $query['_multitenancy'] ?? true; + $_rbac = $query['_rbac'] ?? true; + $_multitenancy = $query['_multitenancy'] ?? true; $relationsContains = $query['_relations_contains'] ?? null; $source = $query['_source'] ?? null; // Resolve multitenancy flag based on public schema access and explicit request. $multitenancyExplicit = $this->isExplicitlyTrue(value: $query['_multitenancy_explicit'] ?? false); - $_multitenancy = $this->resolveMultitenancyFlag( + $_multitenancy = $this->resolveMultitenancyFlag( _multitenancy: $_multitenancy, multitenancyExplicit: $multitenancyExplicit, source: $source, @@ -372,7 +376,7 @@ public function buildWhereConditionsSql(array $query, Schema $schema): array // Extract options from query. $search = $query['_search'] ?? null; $includeDeleted = $query['_includeDeleted'] ?? false; - $_rbac = $query['_rbac'] ?? true; + $_rbac = $query['_rbac'] ?? true; // 1. Deleted filter. if ($includeDeleted === false) { @@ -684,7 +688,7 @@ private function isExplicitlyTrue(mixed $value): bool * multitenancy with _multi=true. This allows public data to be visible across orgs * while still giving users the option to filter by their own organisation. * - * @param bool $_multitenancy Current multitenancy flag + * @param bool $_multitenancy Current multitenancy flag * @param bool $multitenancyExplicit Whether multitenancy was explicitly requested * @param string|null $source Data source type * @param Schema $schema Schema to check for public access @@ -721,8 +725,8 @@ private function resolveMultitenancyFlag( * * @param IQueryBuilder $qb Query builder to modify * @param Schema $schema Schema for access control rules - * @param bool $_rbac Whether RBAC filtering is enabled - * @param bool $_multitenancy Whether multitenancy filtering is enabled + * @param bool $_rbac Whether RBAC filtering is enabled + * @param bool $_multitenancy Whether multitenancy filtering is enabled * @param bool $multitenancyExplicit Whether multitenancy was explicitly requested * * @return void diff --git a/lib/Db/MultiTenancyTrait.php b/lib/Db/MultiTenancyTrait.php index 76d0b3c34..c8a537f73 100644 --- a/lib/Db/MultiTenancyTrait.php +++ b/lib/Db/MultiTenancyTrait.php @@ -409,11 +409,11 @@ private function isAdminOverrideEnabled(): bool /** * Apply filter when no active organisation is set * - * @param IQueryBuilder $qb Query builder - * @param mixed $user User object - * @param bool $allowNullOrg Allow NULL organisation - * @param string $organisationColumn Organisation column name - * @param string $tableAlias Table alias + * @param IQueryBuilder $qb Query builder + * @param mixed $user User object + * @param bool $allowNullOrg Allow NULL organisation + * @param string $organisationColumn Organisation column name + * * @return void * * @SuppressWarnings(PHPMD.BooleanArgumentFlag) Flags control multitenancy filtering behavior diff --git a/lib/Db/RegisterMapper.php b/lib/Db/RegisterMapper.php index 53d0a373a..d0510c2c1 100644 --- a/lib/Db/RegisterMapper.php +++ b/lib/Db/RegisterMapper.php @@ -151,14 +151,14 @@ class RegisterMapper extends QBMapper * Initializes mapper with database connection and required dependencies * for multi-tenancy, RBAC, and event dispatching. * - * @param IDBConnection $db Database connection for queries - * @param SchemaMapper $schemaMapper Schema mapper for schema operations - * @param IEventDispatcher $eventDispatcher Event dispatcher for register events - * @param \Psr\Container\ContainerInterface $container Container for lazy MagicMapper resolution - * @param OrganisationMapper $organisationMapper Organisation mapper for multi-tenancy - * @param IUserSession $userSession User session for current user context - * @param IGroupManager $groupManager Group manager for RBAC checks - * @param IAppConfig $appConfig App configuration for multitenancy settings + * @param IDBConnection $db Database connection for queries + * @param SchemaMapper $schemaMapper Schema mapper for schema operations + * @param IEventDispatcher $eventDispatcher Event dispatcher for register events + * @param \Psr\Container\ContainerInterface $container Container for lazy MagicMapper resolution + * @param OrganisationMapper $organisationMapper Organisation mapper for multi-tenancy + * @param IUserSession $userSession User session for current user context + * @param IGroupManager $groupManager Group manager for RBAC checks + * @param IAppConfig $appConfig App configuration for multitenancy settings * * @return void */ diff --git a/lib/Listener/CommentsEntityListener.php b/lib/Listener/CommentsEntityListener.php index 362b64be1..c458610bc 100644 --- a/lib/Listener/CommentsEntityListener.php +++ b/lib/Listener/CommentsEntityListener.php @@ -57,8 +57,8 @@ class CommentsEntityListener implements IEventListener /** * Constructor. * - * @param MagicMapper $objectEntityMapper Mapper for object validation - * @param LoggerInterface $logger Logger for error reporting + * @param MagicMapper $objectEntityMapper Mapper for object validation + * @param LoggerInterface $logger Logger for error reporting * * @return void */ diff --git a/lib/Service/AuthenticationService.php b/lib/Service/AuthenticationService.php index 68ea15f0b..595799a58 100644 --- a/lib/Service/AuthenticationService.php +++ b/lib/Service/AuthenticationService.php @@ -409,7 +409,12 @@ public function fetchJWTToken(array $configuration): string $jwk = $this->getJWK(configuration: $configuration); if (isset($configuration['x5t']) === true) { - return $this->generateJWT(payload: $payload, jwk: $jwk, algorithm: $configuration['algorithm'], x5t: $configuration['x5t']); + return $this->generateJWT( + payload: $payload, + jwk: $jwk, + algorithm: $configuration['algorithm'], + x5t: $configuration['x5t'] + ); } return $this->generateJWT(payload: $payload, jwk: $jwk, algorithm: $configuration['algorithm']); diff --git a/lib/Service/AuthorizationService.php b/lib/Service/AuthorizationService.php index 7952ad8f9..f3b7368d5 100644 --- a/lib/Service/AuthorizationService.php +++ b/lib/Service/AuthorizationService.php @@ -200,7 +200,7 @@ public function authorizeJwt(string $authorization): void [$headerB64, $payloadB64, $signatureB64] = $parts; - $headerJson = $this->base64urlDecode($headerB64); + $headerJson = $this->base64urlDecode(data: $headerB64); if ($headerJson === false) { throw new AuthenticationException( message: 'The token could not be validated', @@ -216,7 +216,7 @@ public function authorizeJwt(string $authorization): void ); } - $payloadJson = $this->base64urlDecode($payloadB64); + $payloadJson = $this->base64urlDecode(data: $payloadB64); if ($payloadJson === false) { throw new AuthenticationException( message: 'The token could not be validated', @@ -245,7 +245,7 @@ public function authorizeJwt(string $authorization): void $publicKey = $authConf['publicKey'] ?? ''; $algorithm = $authConf['algorithm'] ?? $header['alg']; - $signature = $this->base64urlDecode($signatureB64); + $signature = $this->base64urlDecode(data: $signatureB64); if ($signature === false) { throw new AuthenticationException( message: 'The token could not be validated', @@ -255,7 +255,14 @@ public function authorizeJwt(string $authorization): void // Verify HMAC signature. if (isset(self::HMAC_MAP[$algorithm]) === true) { - if ($this->verifyHmac($headerB64, $payloadB64, $signature, $publicKey, $algorithm) === false) { + $hmacValid = $this->verifyHmac( + headerB64: $headerB64, + payloadB64: $payloadB64, + signature: $signature, + secret: $publicKey, + algorithm: $algorithm + ); + if ($hmacValid === false) { throw new AuthenticationException( message: 'The token could not be validated', details: ['reason' => 'The token does not match the public key'] diff --git a/lib/Service/Configuration/ExportHandler.php b/lib/Service/Configuration/ExportHandler.php index ecc8a35de..4483d1671 100644 --- a/lib/Service/Configuration/ExportHandler.php +++ b/lib/Service/Configuration/ExportHandler.php @@ -122,7 +122,7 @@ class ExportHandler * * @param SchemaMapper $schemaMapper The schema mapper. * @param RegisterMapper $registerMapper The register mapper. - * @param MagicMapper $objectEntityMapper The object entity mapper. + * @param MagicMapper $objectEntityMapper The object entity mapper. * @param ConfigurationMapper $configurationMapper The configuration mapper. * @param MappingMapper $mappingMapper The mapping mapper. * @param LoggerInterface $logger The logger interface. diff --git a/lib/Service/Configuration/ImportHandler.php b/lib/Service/Configuration/ImportHandler.php index 25f1b7bec..661423a94 100644 --- a/lib/Service/Configuration/ImportHandler.php +++ b/lib/Service/Configuration/ImportHandler.php @@ -75,8 +75,6 @@ class ImportHandler * which could trigger another dependency check. This flag prevents infinite recursion. * * @var boolean - * - * @SuppressWarnings(PHPMD.UnusedPrivateField) */ private static bool $depCheckActive = false; @@ -203,8 +201,6 @@ class ImportHandler * OpenConnector configuration service for optional integration. * * @var mixed The OpenConnector configuration service or null. - * - * @SuppressWarnings(PHPMD.UnusedPrivateField) */ private mixed $connectorConfigSvc = null; @@ -227,7 +223,7 @@ class ImportHandler * * @param SchemaMapper $schemaMapper The schema mapper. * @param RegisterMapper $registerMapper The register mapper. - * @param MagicMapper $objectEntityMapper The object entity mapper. + * @param MagicMapper $objectEntityMapper The object entity mapper. * @param ConfigurationMapper $configurationMapper The configuration mapper. * @param MappingMapper $mappingMapper The mapping mapper. * @param Client $client The HTTP client for URL fetching. diff --git a/lib/Service/DashboardService.php b/lib/Service/DashboardService.php index 6427a0207..d9d5bb8cf 100644 --- a/lib/Service/DashboardService.php +++ b/lib/Service/DashboardService.php @@ -114,12 +114,12 @@ class DashboardService * * Initializes service with required mappers and logger for dashboard operations. * - * @param MagicMapper $objectMapper Object entity mapper for object statistics - * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for log statistics - * @param WebhookLogMapper $webhookLogMapper Webhook log mapper for webhook statistics - * @param RegisterMapper $registerMapper Register mapper for register operations - * @param SchemaMapper $schemaMapper Schema mapper for schema operations - * @param LoggerInterface $logger Logger instance for error tracking + * @param MagicMapper $objectMapper Object entity mapper for object statistics + * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for log statistics + * @param WebhookLogMapper $webhookLogMapper Webhook log mapper for webhook statistics + * @param RegisterMapper $registerMapper Register mapper for register operations + * @param SchemaMapper $schemaMapper Schema mapper for schema operations + * @param LoggerInterface $logger Logger instance for error tracking * * @return void */ diff --git a/lib/Service/File/CreateFileHandler.php b/lib/Service/File/CreateFileHandler.php index 6198f1350..91a04a7f2 100644 --- a/lib/Service/File/CreateFileHandler.php +++ b/lib/Service/File/CreateFileHandler.php @@ -63,7 +63,7 @@ class CreateFileHandler * @param FolderManagementHandler $folderMgmtHandler Folder management handler. * @param FileValidationHandler $fileValidHandler File validation handler. * @param FileOwnershipHandler $fileOwnershipHandler File ownership handler. - * @param MagicMapper $objectEntityMapper Object entity mapper. + * @param MagicMapper $objectEntityMapper Object entity mapper. * @param LoggerInterface $logger Logger for logging operations. */ public function __construct( diff --git a/lib/Service/File/FilePublishingHandler.php b/lib/Service/File/FilePublishingHandler.php index 8af29fa8a..7074878f2 100644 --- a/lib/Service/File/FilePublishingHandler.php +++ b/lib/Service/File/FilePublishingHandler.php @@ -55,9 +55,9 @@ class FilePublishingHandler /** * Constructor for FilePublishingHandler. * - * @param MagicMapper $objectEntityMapper Object entity mapper for fetching objects. - * @param FileMapper $fileMapper File mapper for share operations. - * @param LoggerInterface $logger Logger for logging operations. + * @param MagicMapper $objectEntityMapper Object entity mapper for fetching objects. + * @param FileMapper $fileMapper File mapper for share operations. + * @param LoggerInterface $logger Logger for logging operations. */ public function __construct( private readonly MagicMapper $objectEntityMapper, @@ -148,8 +148,10 @@ public function publishFile(ObjectEntity | string $object, string | int $file): context: ['file' => __FILE__, 'line' => __LINE__] ); if ($fileName !== $filePath) { + $extractMsg = "[FilePublishingHandler] publishFile: Extracted filename from path:"; + $extractMsg .= " '$fileName' (from '$filePath')"; $this->logger->info( - message: "[FilePublishingHandler] publishFile: Extracted filename from path: '$fileName' (from '$filePath')", + message: $extractMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); } @@ -158,8 +160,9 @@ public function publishFile(ObjectEntity | string $object, string | int $file): $objectFolder = $this->fileService->getObjectFolder($object); if ($objectFolder === null) { + $objectId = $object->getId(); $this->logger->error( - message: '[FilePublishingHandler] publishFile: Could not get object folder for object: '.$object->getId(), + message: "[FilePublishingHandler] publishFile: Could not get object folder for object: $objectId", context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception('Object folder not found.'); @@ -202,17 +205,20 @@ function ($file) { } catch (NotFoundException $e) { // Try with full path if filename didn't work. try { - $attemptMsg = "[FilePublishingHandler] publishFile: Attempting to get file '$filePath' (full path) from object folder"; + $attemptMsg = "[FilePublishingHandler] publishFile: Attempting to get file"; + $attemptMsg .= " '$filePath' (full path) from object folder"; $this->logger->info(message: $attemptMsg, context: ['file' => __FILE__, 'line' => __LINE__]); - $fileNode = $objectFolder->get($filePath); - $nodeName = $fileNode->getName(); - $nodePath = $fileNode->getPath(); - $successMsg = "[FilePublishingHandler] publishFile: Successfully found file using full path: $nodeName at $nodePath"; + $fileNode = $objectFolder->get($filePath); + $nodeName = $fileNode->getName(); + $nodePath = $fileNode->getPath(); + $successMsg = "[FilePublishingHandler] publishFile: Successfully found file"; + $successMsg .= " using full path: $nodeName at $nodePath"; $this->logger->info(message: $successMsg, context: ['file' => __FILE__, 'line' => __LINE__]); } catch (NotFoundException $e2) { $errDetail = $e2->getMessage(); $prefix = '[FilePublishingHandler] publishFile:'; - $errMsg = "$prefix File '$fileName' and '$filePath' not found in object folder. NotFoundException: $errDetail"; + $errMsg = "$prefix File '$fileName' and '$filePath' not found"; + $errMsg .= " in object folder. NotFoundException: $errDetail"; $this->logger->error(message: $errMsg, context: ['file' => __FILE__, 'line' => __LINE__]); throw new Exception('File not found.'); } @@ -226,8 +232,9 @@ function ($file) { // Verify file exists and is a File instance. if ($fileNode instanceof File === false) { + $nodeClass = get_class($fileNode); $this->logger->error( - message: "[FilePublishingHandler] publishFile: Found node is not a File instance, it's a: ".get_class($fileNode), + message: "[FilePublishingHandler] publishFile: Found node is not a File instance, it's a: $nodeClass", context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception('File not found.'); @@ -340,8 +347,10 @@ public function unpublishFile(ObjectEntity | string $object, string|int $filePat context: ['file' => __FILE__, 'line' => __LINE__] ); if ($fileName !== $filePath) { + $extractMsg = "[FilePublishingHandler] unpublishFile: Extracted filename from path:"; + $extractMsg .= " '$fileName' (from '$filePath')"; $this->logger->info( - message: "[FilePublishingHandler] unpublishFile: Extracted filename from path: '$fileName' (from '$filePath')", + message: $extractMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); } @@ -350,8 +359,9 @@ public function unpublishFile(ObjectEntity | string $object, string|int $filePat $objectFolder = $this->fileService->getObjectFolder($object); if ($objectFolder === null) { + $objectId = $object->getId(); $this->logger->error( - message: '[FilePublishingHandler] unpublishFile: Could not get object folder for object: '.$object->getId(), + message: "[FilePublishingHandler] unpublishFile: Could not get object folder for object: $objectId", context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception('Object folder not found.'); @@ -376,8 +386,9 @@ function ($file) { context: ['file' => __FILE__, 'line' => __LINE__] ); } catch (Exception $e) { + $errDetail = $e->getMessage(); $this->logger->error( - message: '[FilePublishingHandler] unpublishFile: Error listing object folder contents: '.$e->getMessage(), + message: "[FilePublishingHandler] unpublishFile: Error listing object folder contents: $errDetail", context: ['file' => __FILE__, 'line' => __LINE__] ); } @@ -394,16 +405,18 @@ function ($file) { } catch (NotFoundException $e) { // Try with full path if filename didn't work. try { - $attemptMsg = "[FilePublishingHandler] unpublishFile: Attempting to get file '$filePath' (full path) from object folder"; + $attemptMsg = "[FilePublishingHandler] unpublishFile: Attempting to get file"; + $attemptMsg .= " '$filePath' (full path) from object folder"; $this->logger->info(message: $attemptMsg, context: ['file' => __FILE__, 'line' => __LINE__]); $file = $objectFolder->get($filePath); - $successMsg = "[FilePublishingHandler] unpublishFile: Successfully found file using full path: "; - $successMsg .= $file->getName()." at ".$file->getPath(); + $successMsg = "[FilePublishingHandler] unpublishFile: Successfully found file"; + $successMsg .= " using full path: ".$file->getName()." at ".$file->getPath(); $this->logger->info(message: $successMsg, context: ['file' => __FILE__, 'line' => __LINE__]); } catch (NotFoundException $e2) { $errDetail = $e2->getMessage(); $prefix = '[FilePublishingHandler] unpublishFile:'; - $errMsg = "$prefix File '$fileName' and '$filePath' not found in object folder. NotFoundException: $errDetail"; + $errMsg = "$prefix File '$fileName' and '$filePath' not found"; + $errMsg .= " in object folder. NotFoundException: $errDetail"; $this->logger->error(message: $errMsg, context: ['file' => __FILE__, 'line' => __LINE__]); throw new Exception('File not found.'); } @@ -417,8 +430,9 @@ function ($file) { // Verify file exists and is a File instance. if ($file instanceof File === false) { + $fileClass = get_class($file); $this->logger->error( - message: "[FilePublishingHandler] unpublishFile: Found node is not a File instance, it's a: ".get_class($file), + message: "[FilePublishingHandler] unpublishFile: Found node is not a File instance, it's a: $fileClass", context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception('File not found.'); @@ -588,8 +602,9 @@ public function createObjectFilesZip(ObjectEntity | string $object, ?string $zip throw new Exception("Failed to finalize ZIP archive"); } + $zipMsg = "[FilePublishingHandler] ZIP creation completed. Added: $addedFiles files, Skipped: $skippedFiles files"; $this->logger->info( - message: "[FilePublishingHandler] ZIP creation completed. Added: $addedFiles files, Skipped: $skippedFiles files", + message: $zipMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); diff --git a/lib/Service/File/FileValidationHandler.php b/lib/Service/File/FileValidationHandler.php index 89a8ddae5..746295fd7 100644 --- a/lib/Service/File/FileValidationHandler.php +++ b/lib/Service/File/FileValidationHandler.php @@ -271,14 +271,16 @@ public function checkOwnership(Node $file): void } // If we get here, the file is accessible. + $fileName = $file->getName(); + $fileId = $file->getId(); $this->logger->debug( - message: '[FileValidationHandler] checkOwnership: File '."{$file->getName()} (ID: {$file->getId()}) is accessible", + message: "[FileValidationHandler] checkOwnership: File {$fileName} (ID: {$fileId}) is accessible", context: ['file' => __FILE__, 'line' => __LINE__] ); } catch (NotFoundException $e) { // File exists but we can't access it - likely an ownership issue. $this->logger->warning( - message: '[FileValidationHandler] checkOwnership: File '."{$file->getName()} (ID: {$file->getId()}) not accessible", + message: "[FileValidationHandler] checkOwnership: File {$fileName} (ID: {$fileId}) not accessible", context: ['file' => __FILE__, 'line' => __LINE__] ); @@ -288,7 +290,7 @@ public function checkOwnership(Node $file): void if ($fileOwner === null || $fileOwner->getUID() !== $openRegisterUser->getUID()) { $this->logger->info( - message: '[FileValidationHandler] checkOwnership: '."File {$file->getName()} (ID: {$file->getId()}) has wrong owner", + message: "[FileValidationHandler] checkOwnership: File {$fileName} (ID: {$fileId}) has wrong owner", context: ['file' => __FILE__, 'line' => __LINE__] ); @@ -297,14 +299,14 @@ public function checkOwnership(Node $file): void if ($ownershipFixed === false) { $this->logger->error( - message: '[FileValidationHandler] checkOwnership: '."Failed to fix ownership for file {$file->getName()}", + message: "[FileValidationHandler] checkOwnership: Failed to fix ownership for file {$fileName}", context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception("Failed to fix file ownership for file: ".$file->getName()); } $this->logger->info( - message: '[FileValidationHandler] checkOwnership: '."Fixed ownership for file {$file->getName()}", + message: "[FileValidationHandler] checkOwnership: Fixed ownership for file {$fileName}", context: ['file' => __FILE__, 'line' => __LINE__] ); @@ -312,33 +314,39 @@ public function checkOwnership(Node $file): void }//end if $this->logger->info( - message: '[FileValidationHandler] checkOwnership: '."File {$file->getName()} has correct owner but not accessible", + message: "[FileValidationHandler] checkOwnership: File {$fileName} has correct owner but not accessible", context: ['file' => __FILE__, 'line' => __LINE__] ); } catch (Exception $ownershipException) { + $ownerErr = $ownershipException->getMessage(); + $errMsg = "[FileValidationHandler] checkOwnership: Error for file {$fileName}: $ownerErr"; $this->logger->error( - message: '[FileValidationHandler] checkOwnership: '."Error for file {$file->getName()}: ".$ownershipException->getMessage(), + message: $errMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); throw new Exception("Ownership check failed for file: ".$file->getName()); }//end try } catch (NotPermittedException $e) { // Permission denied - likely an ownership issue. + $warnMsg = "[FileValidationHandler] checkOwnership: Permission denied for file {$fileName},"; + $warnMsg .= ' attempting ownership fix'; $this->logger->warning( - message: '[FileValidationHandler] checkOwnership: '."Permission denied for file {$file->getName()}, ".'attempting ownership fix', + message: $warnMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); try { // Try to fix the ownership. $this->ownFile(file: $file); + $fixMsg = "[FileValidationHandler] checkOwnership: Fixed ownership for file {$fileName}"; + $fixMsg .= ' after permission error'; $this->logger->info( - message: '[FileValidationHandler] checkOwnership: '."Fixed ownership for file {$file->getName()} ".'after permission error', + message: $fixMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); } catch (Exception $ownershipException) { - $fileName = $file->getName(); - $errMsg = '[FileValidationHandler] checkOwnership: '."Failed to fix for file {$fileName}: ".$ownershipException->getMessage(); + $ownerErr = $ownershipException->getMessage(); + $errMsg = "[FileValidationHandler] checkOwnership: Failed to fix for file {$fileName}: $ownerErr"; $this->logger->error(message: $errMsg, context: ['file' => __FILE__, 'line' => __LINE__]); throw new Exception("Ownership fix failed for file: ".$file->getName()); } diff --git a/lib/Service/File/FolderManagementHandler.php b/lib/Service/File/FolderManagementHandler.php index 10d4fa2dc..1f67598f6 100644 --- a/lib/Service/File/FolderManagementHandler.php +++ b/lib/Service/File/FolderManagementHandler.php @@ -76,14 +76,14 @@ class FolderManagementHandler /** * Constructor for FolderManagementHandler. * - * @param IRootFolder $rootFolder Root folder for file operations. - * @param MagicMapper $objectEntityMapper Mapper for object entities. - * @param RegisterMapper $registerMapper Mapper for registers. - * @param IUserSession $userSession User session for user context. - * @param IGroupManager $groupManager Group manager for group operations. - * @param LoggerInterface $logger Logger for logging operations. - * @param FileService|null $fileService File service facade for cross-handler coordination - * (injected lazily to avoid circular dependency). + * @param IRootFolder $rootFolder Root folder for file operations. + * @param MagicMapper $objectEntityMapper Mapper for object entities. + * @param RegisterMapper $registerMapper Mapper for registers. + * @param IUserSession $userSession User session for user context. + * @param IGroupManager $groupManager Group manager for group operations. + * @param LoggerInterface $logger Logger for logging operations. + * @param FileService|null $fileService File service facade for cross-handler coordination + * (injected lazily to avoid circular dependency). */ public function __construct( private readonly IRootFolder $rootFolder, @@ -312,8 +312,9 @@ public function getRegisterFolderById(Register $register): ?Folder // At this point $folderProperty is a non-empty string. // Check if it's a numeric string (folder ID) or a legacy path. if (is_numeric($folderProperty) === false) { + $registerId = $register->getId(); $this->logger->warning( - message: '[FolderManagementHandler] Invalid folder ID type for register '.$register->getId().', creating new folder', + message: "[FolderManagementHandler] Invalid folder ID type for register {$registerId}, creating new folder", context: ['file' => __FILE__, 'line' => __LINE__] ); return $this->createRegisterFolderById(register: $register); diff --git a/lib/Service/File/UpdateFileHandler.php b/lib/Service/File/UpdateFileHandler.php index 5c0cb298e..31bc145bc 100644 --- a/lib/Service/File/UpdateFileHandler.php +++ b/lib/Service/File/UpdateFileHandler.php @@ -221,8 +221,9 @@ public function updateFile( try { $folderFiles = $objectFolder->getDirectoryListing(); $fileNames = array_map(fn($f) => $f->getName(), $folderFiles); + $fileList = implode(', ', $fileNames); $this->logger->info( - message: '[UpdateFileHandler] updateFile: Files in object folder: '.implode(', ', $fileNames), + message: "[UpdateFileHandler] updateFile: Files in object folder: $fileList", context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -300,7 +301,8 @@ public function updateFile( $userFolder = $this->folderMgmtHandler->getOpenRegisterUserFolder(); $file = $userFolder->get(path: $filePath); $fileId = $file->getId(); - $msg = "[UpdateFileHandler] updateFile: Found file in user folder at path: $filePath (ID: $fileId)"; + $msg = "[UpdateFileHandler] updateFile: Found file in user folder at path:"; + $msg .= " $filePath (ID: $fileId)"; $this->logger->info(message: $msg, context: ['file' => __FILE__, 'line' => __LINE__]); } catch (NotFoundException $e) { $this->logger->error( @@ -336,8 +338,10 @@ public function updateFile( ); } } catch (Exception $e) { + $eMsg = $e->getMessage(); + $errMsg = "[UpdateFileHandler] updateFile: Error finding file by ID {$fileId}: {$eMsg}"; $this->logger->error( - message: "[UpdateFileHandler] updateFile: Error finding file by ID $fileId: ".$e->getMessage(), + message: $errMsg, context: ['file' => __FILE__, 'line' => __LINE__] ); }//end try diff --git a/lib/Service/ImportService.php b/lib/Service/ImportService.php index 98c05ddfa..31e942026 100644 --- a/lib/Service/ImportService.php +++ b/lib/Service/ImportService.php @@ -139,10 +139,10 @@ class ImportService * Constructor for the ImportService * * @param SchemaMapper $schemaMapper The schema mapper - * @param ObjectService $objectService The object service - * @param LoggerInterface $logger The logger interface - * @param IGroupManager $groupManager The group manager - * @param IJobList $jobList The background job list + * @param ObjectService $objectService The object service + * @param LoggerInterface $logger The logger interface + * @param IGroupManager $groupManager The group manager + * @param IJobList $jobList The background job list */ public function __construct( SchemaMapper $schemaMapper, @@ -151,11 +151,11 @@ public function __construct( IGroupManager $groupManager, IJobList $jobList ) { - $this->schemaMapper = $schemaMapper; - $this->objectService = $objectService; - $this->logger = $logger; - $this->groupManager = $groupManager; - $this->jobList = $jobList; + $this->schemaMapper = $schemaMapper; + $this->objectService = $objectService; + $this->logger = $logger; + $this->groupManager = $groupManager; + $this->jobList = $jobList; // Initialize cache arrays to prevent issues. $this->schemaPropertiesCache = []; diff --git a/lib/Service/Index/Backends/Solr/SolrQueryExecutor.php b/lib/Service/Index/Backends/Solr/SolrQueryExecutor.php index 7929cfb72..9928a4d09 100644 --- a/lib/Service/Index/Backends/Solr/SolrQueryExecutor.php +++ b/lib/Service/Index/Backends/Solr/SolrQueryExecutor.php @@ -138,11 +138,11 @@ public function search(array $params): array /** * Search with pagination. * - * @param array $query Query parameters + * @param array $query Query parameters * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters - * @param bool $published Filter for published only - * @param bool $deleted Include deleted items + * @param bool $published Filter for published only + * @param bool $deleted Include deleted items * * @return array Paginated search results with pagination info. * diff --git a/lib/Service/Index/BulkIndexer.php b/lib/Service/Index/BulkIndexer.php index 9ee2b2957..7227e4fc5 100644 --- a/lib/Service/Index/BulkIndexer.php +++ b/lib/Service/Index/BulkIndexer.php @@ -90,7 +90,7 @@ class BulkIndexer /** * BulkIndexer constructor * - * @param MagicMapper $objectMapper DB mapper for objects + * @param MagicMapper $objectMapper DB mapper for objects * @param SchemaMapper $schemaMapper DB mapper for schemas * @param DocumentBuilder $documentBuilder Document builder * @param SearchBackendInterface $searchBackend Search backend (Solr/Elastic) diff --git a/lib/Service/Index/ObjectHandler.php b/lib/Service/Index/ObjectHandler.php index 04e513adc..0eff4c6eb 100644 --- a/lib/Service/Index/ObjectHandler.php +++ b/lib/Service/Index/ObjectHandler.php @@ -68,11 +68,11 @@ public function __construct( /** * Search objects in Solr. * - * @param array $query Search query parameters + * @param array $query Search query parameters * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters - * @param bool $published Filter published objects - * @param bool $deleted Include deleted objects + * @param bool $published Filter published objects + * @param bool $deleted Include deleted objects * * @return (array|int|mixed)[] Search results in OpenRegister format * @@ -119,11 +119,11 @@ public function searchObjects( /** * Build Solr query from OpenRegister query parameters. * - * @param array $query OpenRegister query + * @param array $query OpenRegister query * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters - * @param bool $published Filter published objects - * @param bool $deleted Include deleted objects + * @param bool $published Filter published objects + * @param bool $deleted Include deleted objects * * @return (int|mixed|string[])[] Solr query parameters * diff --git a/lib/Service/Index/SearchBackendInterface.php b/lib/Service/Index/SearchBackendInterface.php index 212b53a2f..09a451741 100644 --- a/lib/Service/Index/SearchBackendInterface.php +++ b/lib/Service/Index/SearchBackendInterface.php @@ -126,7 +126,6 @@ public function deleteByQuery(string $query, bool $commit=false, bool $returnDet * @param array $query Query parameters (filters, pagination, facets, etc.). * @param bool $_rbac Whether to apply RBAC filtering. * @param bool $_multitenancy Whether to apply multitenancy filtering. - * @param bool $published Whether to filter for published objects only. * @param bool $deleted Whether to include deleted objects. * * @return array Search results with objects, pagination, and facets. diff --git a/lib/Service/IndexService.php b/lib/Service/IndexService.php index 5e012b920..92540f037 100644 --- a/lib/Service/IndexService.php +++ b/lib/Service/IndexService.php @@ -145,11 +145,11 @@ public function getChunkingStats(): array * * Delegates to ObjectHandler. * - * @param array $query Search query + * @param array $query Search query * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters - * @param bool $published Filter published objects - * @param bool $deleted Include deleted objects + * @param bool $published Filter published objects + * @param bool $deleted Include deleted objects * * @return (array|int|mixed)[] Search results * diff --git a/lib/Service/Mcp/McpResourcesService.php b/lib/Service/Mcp/McpResourcesService.php index e00628a81..1163114ba 100644 --- a/lib/Service/Mcp/McpResourcesService.php +++ b/lib/Service/Mcp/McpResourcesService.php @@ -90,10 +90,12 @@ public function listResources(): array foreach ($schemaIds as $schemaId) { try { $schema = $this->schemaMapper->find($schemaId); + $regTitle = $register->getTitle(); + $schTitle = $schema->getTitle(); $resources[] = [ 'uri' => 'openregister://objects/'.$register->getId().'/'.$schema->getId(), - 'name' => $register->getTitle().' — '.$schema->getTitle(), - 'description' => 'Objects in register "'.$register->getTitle().'" with schema "'.$schema->getTitle().'"', + 'name' => "$regTitle — $schTitle", + 'description' => "Objects in register \"{$regTitle}\" with schema \"{$schTitle}\"", 'mimeType' => 'application/json', ]; } catch (DoesNotExistException $e) { diff --git a/lib/Service/McpDiscoveryService.php b/lib/Service/McpDiscoveryService.php index 622f9093b..11618a387 100644 --- a/lib/Service/McpDiscoveryService.php +++ b/lib/Service/McpDiscoveryService.php @@ -138,6 +138,7 @@ public function getCatalog(): array [ 'id' => 'objects', 'name' => 'Objects', + // phpcs:ignore Generic.Files.LineLength.TooLong -- description string cannot be shortened 'description' => 'Data records stored in register/schema pairs. Full CRUD, filtering, pagination, lock/unlock, publish.', ], [ @@ -873,6 +874,7 @@ private function buildViewsCapability(): array [ 'method' => 'POST', 'path' => '/api/views', + // phpcs:ignore Generic.Files.LineLength.TooLong -- description string cannot be shortened 'description' => 'Create a view. Body: { "name": "...", "filters": {...}, "register": id, "schema": id }.', ], [ diff --git a/lib/Service/Object/CacheHandler.php b/lib/Service/Object/CacheHandler.php index f338b26cb..48cf649a0 100644 --- a/lib/Service/Object/CacheHandler.php +++ b/lib/Service/Object/CacheHandler.php @@ -204,7 +204,7 @@ public function getUser() return null; }//end getUser() }; - $this->container = $container; + $this->container = $container; }//end __construct() /** diff --git a/lib/Service/Object/CrudHandler.php b/lib/Service/Object/CrudHandler.php index 361cc4776..2992da3b6 100644 --- a/lib/Service/Object/CrudHandler.php +++ b/lib/Service/Object/CrudHandler.php @@ -52,9 +52,9 @@ class CrudHandler /** * Constructor * - * @param MagicMapper $objectMapper Object entity mapper - * @param ObjectService $objectService Object service for save/search operations - * @param LoggerInterface $logger PSR-3 logger + * @param MagicMapper $objectMapper Object entity mapper + * @param ObjectService $objectService Object service for save/search operations + * @param LoggerInterface $logger PSR-3 logger */ public function __construct( private readonly MagicMapper $objectMapper, @@ -67,7 +67,7 @@ public function __construct( * List objects with filters and pagination * * @param array $query Search query parameters - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * @param bool $deleted Include deleted objects * @param array|null $_ids Optional array of object IDs to filter @@ -145,7 +145,7 @@ public function list( * Get a single object by ID * * @param string $objectId Object ID or UUID - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return null Object entity or null if not found @@ -192,7 +192,7 @@ public function get(string $objectId, bool $_rbac=true, bool $_multitenancy=true * Create a new object * * @param array $data Object data - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return null Created object @@ -241,7 +241,7 @@ public function create(array $data, bool $_rbac=true, bool $_multitenancy=true) * * @param string $objectId Object ID or UUID * @param array $data Object data - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return null Updated object @@ -300,7 +300,7 @@ public function update( * * @param string $objectId Object ID or UUID * @param array $data Partial object data - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return ObjectEntity Patched object @@ -376,7 +376,7 @@ public function patch( * Delete an object * * @param string $objectId Object ID or UUID - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return true True if deleted successfully diff --git a/lib/Service/Object/DeleteObject.php b/lib/Service/Object/DeleteObject.php index 9d070b871..d08c0fc69 100644 --- a/lib/Service/Object/DeleteObject.php +++ b/lib/Service/Object/DeleteObject.php @@ -95,7 +95,7 @@ class DeleteObject /** * Constructor for DeleteObject handler. * - * @param MagicMapper $objectEntityMapper Object entity data mapper. + * @param MagicMapper $objectEntityMapper Object entity data mapper. * @param CacheHandler $cacheHandler Object cache service for entity and query caching * @param IUserSession $userSession User session service for tracking who deletes * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for logs diff --git a/lib/Service/Object/ExportHandler.php b/lib/Service/Object/ExportHandler.php index 31ae3102a..7b4392d6d 100644 --- a/lib/Service/Object/ExportHandler.php +++ b/lib/Service/Object/ExportHandler.php @@ -64,12 +64,12 @@ class ExportHandler /** * Constructor * - * @param MagicMapper $objectEntityMapper Object entity mapper - * @param SchemaMapper $schemaMapper Schema mapper - * @param ExportService $exportService Export service - * @param ImportService $importService Import service - * @param FileService $fileService File service - * @param LoggerInterface $logger PSR-3 logger + * @param MagicMapper $objectEntityMapper Object entity mapper + * @param SchemaMapper $schemaMapper Schema mapper + * @param ExportService $exportService Export service + * @param ImportService $importService Import service + * @param FileService $fileService File service + * @param LoggerInterface $logger PSR-3 logger */ public function __construct( private readonly MagicMapper $objectEntityMapper, @@ -190,15 +190,15 @@ public function export( /** * Import objects from uploaded file * - * @param Register $register Register entity - * @param array $uploadedFile Uploaded file data - * @param Schema|null $schema Schema entity (optional for Excel, required for CSV unless auto-detected) - * @param bool $validation Enable validation - * @param bool $events Enable events + * @param Register $register Register entity + * @param array $uploadedFile Uploaded file data + * @param Schema|null $schema Schema entity (optional for Excel, required for CSV unless auto-detected) + * @param bool $validation Enable validation + * @param bool $events Enable events * @param bool $_rbac Apply RBAC checks * @param bool $_multitenancy Apply multitenancy filtering - * @param bool $publish Publish imported objects (Excel only) - * @param IUser|null $currentUser Current user + * @param bool $publish Publish imported objects (Excel only) + * @param IUser|null $currentUser Current user * * @return array Import result with created, updated, errors, and performance stats. * diff --git a/lib/Service/Object/FacetHandler.php b/lib/Service/Object/FacetHandler.php index bd52a8732..de688bf1f 100644 --- a/lib/Service/Object/FacetHandler.php +++ b/lib/Service/Object/FacetHandler.php @@ -81,11 +81,11 @@ class FacetHandler /** * Constructor for FacetHandler. * - * @param MagicMapper $unifiedObjectMapper Unified object mapper with storage routing. - * @param SchemaMapper $schemaMapper Schema database mapper. - * @param ICacheFactory $cacheFactory Cache factory for distributed caching. - * @param IUserSession $userSession User session for tenant isolation. - * @param LoggerInterface $logger Logger for debugging and monitoring. + * @param MagicMapper $unifiedObjectMapper Unified object mapper with storage routing. + * @param SchemaMapper $schemaMapper Schema database mapper. + * @param ICacheFactory $cacheFactory Cache factory for distributed caching. + * @param IUserSession $userSession User session for tenant isolation. + * @param LoggerInterface $logger Logger for debugging and monitoring. * * @return void */ diff --git a/lib/Service/Object/GetObject.php b/lib/Service/Object/GetObject.php index 013ad4315..59a3a139e 100644 --- a/lib/Service/Object/GetObject.php +++ b/lib/Service/Object/GetObject.php @@ -54,9 +54,9 @@ class GetObject /** * Constructor for GetObject handler. * - * @param MagicMapper $objectMapper Object entity data mapper. - * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for logs. - * @param SettingsService $settingsService Settings service for accessing trail settings. + * @param MagicMapper $objectMapper Object entity data mapper. + * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for logs. + * @param SettingsService $settingsService Settings service for accessing trail settings. */ public function __construct( private readonly MagicMapper $objectMapper, diff --git a/lib/Service/Object/MergeHandler.php b/lib/Service/Object/MergeHandler.php index 5b55feb58..170b76931 100644 --- a/lib/Service/Object/MergeHandler.php +++ b/lib/Service/Object/MergeHandler.php @@ -45,9 +45,9 @@ class MergeHandler /** * Constructor for MergeHandler. * - * @param MagicMapper $objectEntityMapper Mapper for object entities. - * @param FileService $fileService Service for file operations. - * @param IUserSession $userSession User session for tracking deletions. + * @param MagicMapper $objectEntityMapper Mapper for object entities. + * @param FileService $fileService Service for file operations. + * @param IUserSession $userSession User session for tracking deletions. */ public function __construct( private readonly MagicMapper $objectEntityMapper, diff --git a/lib/Service/Object/PermissionHandler.php b/lib/Service/Object/PermissionHandler.php index ab3744f4f..58c0eece1 100644 --- a/lib/Service/Object/PermissionHandler.php +++ b/lib/Service/Object/PermissionHandler.php @@ -57,7 +57,7 @@ class PermissionHandler * @param IUserManager $userManager User manager for getting user objects. * @param IGroupManager $groupManager Group manager for checking user groups. * @param SchemaMapper $schemaMapper Mapper for schema operations. - * @param MagicMapper $objectEntityMapper Mapper for object entity operations. + * @param MagicMapper $objectEntityMapper Mapper for object entity operations. * @param LoggerInterface $logger Logger for permission auditing. * @param ContainerInterface $container Container for lazy loading services. */ @@ -88,7 +88,7 @@ public function __construct( * @param string $action The CRUD action (create, read, update, delete). * @param string|null $userId Optional user ID (defaults to current user). * @param string|null $objectOwner Optional object owner for ownership check. - * @param bool $_rbac Whether to apply RBAC checks (default: true). + * @param bool $_rbac Whether to apply RBAC checks (default: true). * @param ObjectEntity|null $object Optional object entity for conditional authorization matching. * * @return bool True if user has permission, false otherwise @@ -222,7 +222,7 @@ public function hasPermission( * @param string $action Action to check permission for. * @param string|null $userId User ID to check permissions for. * @param string|null $objectOwner Object owner ID. - * @param bool $_rbac Whether to enforce RBAC checks. + * @param bool $_rbac Whether to enforce RBAC checks. * @param ObjectEntity|null $object Optional object entity for conditional authorization matching. * * @return void @@ -266,7 +266,7 @@ public function checkPermission( * Removes objects from the array that the current user doesn't have permission to access * or that belong to a different organization in multi-tenant mode. * - * @param array> $objects Array of objects to filter. + * @param array> $objects Array of objects to filter. * @param bool $_rbac Whether to apply RBAC filtering. * @param bool $_multitenancy Whether to apply multitenancy filtering. * @@ -340,7 +340,7 @@ public function filterObjectsForPermissions(array $objects, bool $_rbac, bool $_ * Takes an array of UUIDs, loads the corresponding objects, and filters them * based on current user permissions and organization context. * - * @param array $uuids Array of object UUIDs to filter. + * @param array $uuids Array of object UUIDs to filter. * @param bool $_rbac Whether to apply RBAC filtering. * @param bool $_multitenancy Whether to apply multitenancy filtering. * diff --git a/lib/Service/Object/QueryHandler.php b/lib/Service/Object/QueryHandler.php index 9d9459ea6..81ca3ff46 100644 --- a/lib/Service/Object/QueryHandler.php +++ b/lib/Service/Object/QueryHandler.php @@ -56,15 +56,15 @@ class QueryHandler /** * Constructor for QueryHandler. * - * @param MagicMapper $objectMapper Unified mapper for objects. - * @param GetObject $getHandler Get handler. - * @param RenderObject $renderHandler Render handler. - * @param SearchQueryHandler $searchQueryHandler Search handler. - * @param FacetHandler $facetHandler Facet handler. - * @param PerformanceOptimizationHandler $performanceHandler Performance handler. - * @param IAppContainer $container App container. - * @param LoggerInterface $logger Logger. - * @param IRequest $request Request object. + * @param MagicMapper $objectMapper Unified mapper for objects. + * @param GetObject $getHandler Get handler. + * @param RenderObject $renderHandler Render handler. + * @param SearchQueryHandler $searchQueryHandler Search handler. + * @param FacetHandler $facetHandler Facet handler. + * @param PerformanceOptimizationHandler $performanceHandler Performance handler. + * @param IAppContainer $container App container. + * @param LoggerInterface $logger Logger. + * @param IRequest $request Request object. * * @SuppressWarnings(PHPMD.ExcessiveParameterList) Nextcloud DI requires constructor injection */ @@ -300,11 +300,11 @@ public function searchObjectsPaginated( _multitenancy: $_multitenancy, deleted: $deleted ); - $result['@self']['source'] = 'index'; - $result['@self']['query'] = $query; - $result['@self']['rbac'] = $_rbac; - $result['@self']['multi'] = $_multitenancy; - $result['@self']['deleted'] = $deleted; + $result['@self']['source'] = 'index'; + $result['@self']['query'] = $query; + $result['@self']['rbac'] = $_rbac; + $result['@self']['multi'] = $_multitenancy; + $result['@self']['deleted'] = $deleted; return $result; } @@ -318,11 +318,11 @@ public function searchObjectsPaginated( uses: $uses ); // Use source from result if available (e.g., magic_mapper for multi-schema), otherwise default to database. - $result['@self']['source'] = $result['@self']['source'] ?? 'database'; - $result['@self']['query'] = $query; - $result['@self']['rbac'] = $_rbac; - $result['@self']['multi'] = $_multitenancy; - $result['@self']['deleted'] = $deleted; + $result['@self']['source'] = $result['@self']['source'] ?? 'database'; + $result['@self']['query'] = $query; + $result['@self']['rbac'] = $_rbac; + $result['@self']['multi'] = $_multitenancy; + $result['@self']['deleted'] = $deleted; return $result; }//end searchObjectsPaginated() diff --git a/lib/Service/Object/ReferentialIntegrityService.php b/lib/Service/Object/ReferentialIntegrityService.php index d4d4da8b7..27acd38c5 100644 --- a/lib/Service/Object/ReferentialIntegrityService.php +++ b/lib/Service/Object/ReferentialIntegrityService.php @@ -19,7 +19,8 @@ * * @link https://OpenRegister.app * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Referential integrity requires coordination with schema, object, and mapper services + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Referential integrity requires coordination + * with schema, object, and mapper services */ declare(strict_types=1); @@ -95,11 +96,11 @@ class ReferentialIntegrityService /** * Constructor for ReferentialIntegrityService. * - * @param SchemaMapper $schemaMapper Schema data mapper. - * @param RegisterMapper $registerMapper Register data mapper. - * @param MagicMapper $objectEntityMapper Object entity data mapper. - * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for integrity action logging. - * @param LoggerInterface $logger Logger for debugging. + * @param SchemaMapper $schemaMapper Schema data mapper. + * @param RegisterMapper $registerMapper Register data mapper. + * @param MagicMapper $objectEntityMapper Object entity data mapper. + * @param AuditTrailMapper $auditTrailMapper Audit trail mapper for integrity action logging. + * @param LoggerInterface $logger Logger for debugging. */ public function __construct( private readonly SchemaMapper $schemaMapper, diff --git a/lib/Service/Object/RelationHandler.php b/lib/Service/Object/RelationHandler.php index 1a80fa4f5..f44e69190 100644 --- a/lib/Service/Object/RelationHandler.php +++ b/lib/Service/Object/RelationHandler.php @@ -52,7 +52,7 @@ class RelationHandler /** * Constructor for RelationHandler. * - * @param MagicMapper $objectEntityMapper Mapper for object entities. + * @param MagicMapper $objectEntityMapper Mapper for object entities. * @param SchemaMapper $schemaMapper Mapper for schemas. * @param PerformanceHandler $performanceHandler Handler for performance operations. * @param MagicRbacHandler $rbacHandler Handler for RBAC operations. diff --git a/lib/Service/Object/RenderObject.php b/lib/Service/Object/RenderObject.php index 7cb55e039..3ab0c2f6a 100644 --- a/lib/Service/Object/RenderObject.php +++ b/lib/Service/Object/RenderObject.php @@ -109,7 +109,7 @@ class RenderObject * Constructor for RenderObject handler. * * @param FileMapper $fileMapper File mapper for database operations. - * @param MagicMapper $objectEntityMapper Object entity mapper for database operations. + * @param MagicMapper $objectEntityMapper Object entity mapper for database operations. * @param RegisterMapper $registerMapper Register mapper for database operations. * @param SchemaMapper $schemaMapper Schema mapper for database operations. * @param ISystemTagManager $systemTagManager System tag manager for file tags. diff --git a/lib/Service/Object/SaveObject.php b/lib/Service/Object/SaveObject.php index d0662cd49..867698c9e 100644 --- a/lib/Service/Object/SaveObject.php +++ b/lib/Service/Object/SaveObject.php @@ -169,7 +169,7 @@ class SaveObject * Constructor for SaveObject handler. * * @param MagicMapper $objectEntityMapper Object entity mapper - * @param MagicMapper $unifiedObjectMapper Unified object mapper for object operations + * @param MagicMapper $unifiedObjectMapper Unified object mapper for object operations * @param MetadataHydrationHandler $metaHydrationHandler Handler for metadata extraction * @param FilePropertyHandler $filePropertyHandler Handler for file property operations * @param IUserSession $userSession User session service @@ -1702,6 +1702,7 @@ function ($item) { } // Prefixed UUID (e.g., "id-uuid" with or without dashes). + // phpcs:ignore Generic.Files.LineLength.TooLong -- UUID regex pattern cannot be shortened $prefixedPattern = '/^[a-z]+-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{32})$/i'; if (preg_match($prefixedPattern, $item) === 1) { return true; @@ -1838,6 +1839,7 @@ function ($object) { } // Prefixed UUID (e.g., "id-uuid" with or without dashes). + // phpcs:ignore Generic.Files.LineLength.TooLong -- UUID regex pattern cannot be shortened $prefixedPattern = '/^[a-z]+-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{32})$/i'; if (preg_match($prefixedPattern, $object) === 1) { return true; @@ -2287,6 +2289,7 @@ function ($uuid) { } // Prefixed UUID (e.g., "id-uuid" with or without dashes). + // phpcs:ignore Generic.Files.LineLength.TooLong -- UUID regex pattern cannot be shortened $prefixedPattern = '/^[a-z]+-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{32})$/i'; if (preg_match($prefixedPattern, $uuid) === 1) { return true; @@ -2555,8 +2558,9 @@ public function saveObject( // Try to update existing object if UUID provided AND it's not auto-generated. // Auto-generated UUIDs are for new objects, so skip the lookup. if ($uuid !== null && $isAutoGeneratedUuid === false) { + $debugMsg = '[SaveObject] UUID provided and not auto-generated, checking for existing object (UPDATE operation)'; $this->logger->debug( - message: '[SaveObject] UUID provided and not auto-generated, checking for existing object (UPDATE operation)', + message: $debugMsg, context: [ 'file' => __FILE__, 'line' => __LINE__, @@ -3474,8 +3478,10 @@ private function validateReferenceExists( _multitenancy: false ); } catch (DoesNotExistException $e) { + // phpcs:ignore Generic.Files.LineLength.TooLong -- validation message with 3 dynamic parts cannot be shortened + $validMsg = "Referenced object '{$uuid}' not found in schema '{$targetSchemaSlug}' for property '{$propertyName}'"; throw new ValidationException( - message: "Referenced object '{$uuid}' not found in schema '{$targetSchemaSlug}' for property '{$propertyName}'", + message: $validMsg, code: 422 ); } catch (Exception $e) { diff --git a/lib/Service/Object/SaveObject/RelationCascadeHandler.php b/lib/Service/Object/SaveObject/RelationCascadeHandler.php index 000b4ceb9..0ce014992 100644 --- a/lib/Service/Object/SaveObject/RelationCascadeHandler.php +++ b/lib/Service/Object/SaveObject/RelationCascadeHandler.php @@ -51,10 +51,10 @@ class RelationCascadeHandler /** * Constructor for RelationCascadeHandler. * - * @param MagicMapper $objectEntityMapper Object entity data mapper. - * @param SchemaMapper $schemaMapper Schema mapper for schema operations. - * @param RegisterMapper $registerMapper Register mapper for register operations. - * @param LoggerInterface $logger Logger interface for logging operations. + * @param MagicMapper $objectEntityMapper Object entity data mapper. + * @param SchemaMapper $schemaMapper Schema mapper for schema operations. + * @param RegisterMapper $registerMapper Register mapper for register operations. + * @param LoggerInterface $logger Logger interface for logging operations. */ public function __construct( private readonly MagicMapper $objectEntityMapper, diff --git a/lib/Service/Object/SaveObjects.php b/lib/Service/Object/SaveObjects.php index a0f2045e4..bef952ca9 100644 --- a/lib/Service/Object/SaveObjects.php +++ b/lib/Service/Object/SaveObjects.php @@ -78,7 +78,7 @@ class SaveObjects /** * Constructor for SaveObjects handler * - * @param MagicMapper $objectMapper Mapper for object entity database operations + * @param MagicMapper $objectMapper Mapper for object entity database operations * @param SchemaMapper $schemaMapper Mapper for schema operations * @param RegisterMapper $registerMapper Mapper for register operations * @param SaveObject $saveHandler Handler for individual object operations diff --git a/lib/Service/Object/ValidateObject.php b/lib/Service/Object/ValidateObject.php index c94a3e1e4..97430156d 100644 --- a/lib/Service/Object/ValidateObject.php +++ b/lib/Service/Object/ValidateObject.php @@ -78,11 +78,11 @@ class ValidateObject /** * Constructor for ValidateObject * - * @param IAppConfig $config Configuration service. - * @param MagicMapper $objectMapper Object mapper. - * @param SchemaMapper $schemaMapper Schema mapper. - * @param IURLGenerator $urlGenerator URL generator. - * @param LoggerInterface $logger Logger for logging operations. + * @param IAppConfig $config Configuration service. + * @param MagicMapper $objectMapper Object mapper. + * @param SchemaMapper $schemaMapper Schema mapper. + * @param IURLGenerator $urlGenerator URL generator. + * @param LoggerInterface $logger Logger for logging operations. */ public function __construct( private IAppConfig $config, @@ -403,6 +403,7 @@ private function transformPropertyForOpenRegister(object $propertySchema): void if (is_array($nestedPropertySchema) === true) { $nestedPropertySchema = (object) $nestedPropertySchema; } + $this->transformPropertyForOpenRegister(propertySchema: $nestedPropertySchema); } } diff --git a/lib/Service/Object/ValidationHandler.php b/lib/Service/Object/ValidationHandler.php index 67979bb32..6438148cd 100644 --- a/lib/Service/Object/ValidationHandler.php +++ b/lib/Service/Object/ValidationHandler.php @@ -51,12 +51,12 @@ class ValidationHandler /** * Constructor for ValidationHandler. * - * @param ValidateObject $validateHandler Handler for object validation. - * @param MagicMapper $objectEntityMapper Mapper for object entities. - * @param RegisterMapper $registerMapper Mapper for registers. - * @param SchemaMapper $schemaMapper Mapper for schemas. - * @param MagicMapper $magicMapper Mapper for magic tables. - * @param LoggerInterface $logger Logger for logging operations. + * @param ValidateObject $validateHandler Handler for object validation. + * @param MagicMapper $objectEntityMapper Mapper for object entities. + * @param RegisterMapper $registerMapper Mapper for registers. + * @param SchemaMapper $schemaMapper Mapper for schemas. + * @param MagicMapper $magicMapper Mapper for magic tables. + * @param LoggerInterface $logger Logger for logging operations. */ public function __construct( private readonly ValidateObject $validateHandler, diff --git a/lib/Service/Object/VectorizationHandler.php b/lib/Service/Object/VectorizationHandler.php index 63199fed6..027d59fe2 100644 --- a/lib/Service/Object/VectorizationHandler.php +++ b/lib/Service/Object/VectorizationHandler.php @@ -49,7 +49,7 @@ class VectorizationHandler * Constructor * * @param VectorizationService $vectorizationService Vectorization service - * @param MagicMapper $objectEntityMapper Object entity mapper + * @param MagicMapper $objectEntityMapper Object entity mapper * @param LoggerInterface $logger PSR-3 logger */ public function __construct( diff --git a/lib/Service/ObjectService.php b/lib/Service/ObjectService.php index e1c5b9ee7..b6d4a0015 100644 --- a/lib/Service/ObjectService.php +++ b/lib/Service/ObjectService.php @@ -210,8 +210,9 @@ class ObjectService * @param RegisterMapper $registerMapper Mapper for register operations. * @param SchemaMapper $schemaMapper Mapper for schema operations. * @param ViewMapper $viewMapper Mapper for view operations. - * @param MagicMapper $objectMapper Unified mapper for object - * operations (routes to magic tables). + * @param MagicMapper $objectMapper Unified mapper for object + * operations (routes to + * magic tables). * @param FileService $fileService Service for file operations. * @param IUserSession $userSession User session for getting current user. * @param SearchTrailService $searchTrailService Service for search trail operations. @@ -1919,8 +1920,11 @@ public function searchObjectsPaginated( try { $result['@self']['names'] = $this->collectNamesForResults(results: $resultsToProcess); } catch (\Throwable $e) { + $errMsg = $e->getMessage(); + $errFile = $e->getFile(); + $errLine = $e->getLine(); $this->logger->error( - message: '[ObjectService] _names extension failed: '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine(), + message: "[ObjectService] _names extension failed: {$errMsg} at {$errFile}:{$errLine}", context: ['file' => __FILE__, 'line' => __LINE__] ); $result['@self']['names'] = []; @@ -1953,11 +1957,11 @@ public function searchObjectsPaginated( uses: $uses ); // Preserve source from result (e.g., magic_mapper for multi-schema), only default to database if not set. - $result['@self']['source'] = $result['@self']['source'] ?? 'database'; - $result['@self']['query'] = $query; - $result['@self']['rbac'] = $_rbac; - $result['@self']['multi'] = $_multitenancy; - $result['@self']['deleted'] = $deleted; + $result['@self']['source'] = $result['@self']['source'] ?? 'database'; + $result['@self']['query'] = $query; + $result['@self']['rbac'] = $_rbac; + $result['@self']['multi'] = $_multitenancy; + $result['@self']['deleted'] = $deleted; // Add extended objects only if _extend is requested. // Normalize _extend to array (handles comma-separated string from URL). @@ -1983,8 +1987,10 @@ public function searchObjectsPaginated( try { $result['@self']['names'] = $this->collectNamesForResults(results: $resultsToProcess); } catch (\Throwable $e) { + $errFile = $e->getFile(); + $errLine = $e->getLine(); $this->logger->error( - message: '[ObjectService] _names extension failed: '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine(), + message: '[ObjectService] _names extension failed: '.$e->getMessage()." at {$errFile}:{$errLine}", context: ['file' => __FILE__, 'line' => __LINE__] ); $result['@self']['names'] = []; @@ -2371,7 +2377,6 @@ public function handleValidationException( return $this->validateHandler->handleValidationException($exception); }//end handleValidationException() - /** * Lock an object * @@ -2634,8 +2639,8 @@ public function deleteObjects(array $uuids=[], bool $_rbac=true, bool $_multiten $this->logger->warning( message: '[ObjectService] Bulk delete cache invalidation failed', context: [ - 'error' => $e->getMessage(), - 'deletedCount' => count($deletedObjectIds), + 'error' => $e->getMessage(), + 'deletedCount' => count($deletedObjectIds), ] ); } @@ -2644,7 +2649,6 @@ public function deleteObjects(array $uuids=[], bool $_rbac=true, bool $_multiten return $deletedObjectIds; }//end deleteObjects() - /** * Delete all objects belonging to a specific schema * @@ -2721,7 +2725,7 @@ public function getObjectContracts(string $objectId, array $filters=[]): array * * @param string $objectId Object ID or UUID * @param array $query Search query parameters - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return array Results with object entities and pagination info. @@ -2749,7 +2753,7 @@ public function getObjectUses( * * @param string $objectId Object ID or UUID * @param array $query Search query parameters - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * * @return array Paginated results with referencing objects @@ -2827,7 +2831,7 @@ public function getVectorizationCount(?array $_schemas=null) * List objects with filtering and pagination * * @param array $query Search query parameters - * @param bool $_rbac Apply RBAC filters + * @param bool $_rbac Apply RBAC filters * @param bool $_multitenancy Apply multitenancy filters * @param bool $_deleted Include deleted objects * @param array|null $_ids Optional array of object IDs to filter diff --git a/lib/Service/RegisterService.php b/lib/Service/RegisterService.php index 2331446f2..4301b3142 100644 --- a/lib/Service/RegisterService.php +++ b/lib/Service/RegisterService.php @@ -382,8 +382,9 @@ public function getSchemaObjectCounts(int $registerId, array $schemas): array } try { + $schemaCount = count($schemas); $this->logger->debug( - message: '[RegisterService] GetSchemaObjectCounts: Processing '.count($schemas).' schemas for register '.$registerId, + message: "[RegisterService] GetSchemaObjectCounts: Processing $schemaCount schemas for register $registerId", context: ['file' => __FILE__, 'line' => __LINE__] ); diff --git a/lib/Service/SchemaService.php b/lib/Service/SchemaService.php index f37b360ad..afb476595 100644 --- a/lib/Service/SchemaService.php +++ b/lib/Service/SchemaService.php @@ -71,9 +71,9 @@ class SchemaService /** * SchemaService constructor * - * @param SchemaMapper $schemaMapper Schema mapper for schema operations. - * @param MagicMapper $objectEntityMapper Object entity mapper for object queries. - * @param LoggerInterface $logger Logger for debugging and monitoring. + * @param SchemaMapper $schemaMapper Schema mapper for schema operations. + * @param MagicMapper $objectEntityMapper Object entity mapper for object queries. + * @param LoggerInterface $logger Logger for debugging and monitoring. */ public function __construct( SchemaMapper $schemaMapper, diff --git a/lib/Service/Settings/ConfigurationSettingsHandler.php b/lib/Service/Settings/ConfigurationSettingsHandler.php index cc376f591..98f60e01c 100644 --- a/lib/Service/Settings/ConfigurationSettingsHandler.php +++ b/lib/Service/Settings/ConfigurationSettingsHandler.php @@ -247,20 +247,20 @@ public function getSettings(): array $multitenancyConfig = $this->appConfig->getValueString($this->appName, 'multitenancy', ''); if (empty($multitenancyConfig) === true) { $data['multitenancy'] = [ - 'enabled' => true, - 'defaultUserTenant' => '', - 'defaultObjectTenant' => '', - 'adminOverride' => true, + 'enabled' => true, + 'defaultUserTenant' => '', + 'defaultObjectTenant' => '', + 'adminOverride' => true, ]; } if (empty($multitenancyConfig) === false) { $multitenancyData = json_decode($multitenancyConfig, true); $data['multitenancy'] = [ - 'enabled' => $multitenancyData['enabled'] ?? true, - 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', - 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', - 'adminOverride' => $multitenancyData['adminOverride'] ?? true, + 'enabled' => $multitenancyData['enabled'] ?? true, + 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', + 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', + 'adminOverride' => $multitenancyData['adminOverride'] ?? true, ]; } @@ -317,7 +317,11 @@ public function getSettings(): array $data['blobMigration'] = [ 'processed' => (int) $this->appConfig->getValueString($this->appName, 'blob_migration_processed', '0'), 'remaining' => (int) $this->appConfig->getValueString($this->appName, 'blob_migration_remaining', '0'), - 'complete' => $this->appConfig->getValueString($this->appName, 'blob_migration_complete', 'false') === 'true', + 'complete' => $this->appConfig->getValueString( + $this->appName, + 'blob_migration_complete', + 'false' + ) === 'true', 'lastRun' => $this->appConfig->getValueString($this->appName, 'blob_migration_last_run', ''), ]; @@ -542,10 +546,10 @@ public function updateSettings(array $data): array $multitenancyData = $data['multitenancy']; // Always store Multitenancy config with enabled state (default: true). $multitenancyConfig = [ - 'enabled' => $multitenancyData['enabled'] ?? true, - 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', - 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', - 'adminOverride' => $multitenancyData['adminOverride'] ?? true, + 'enabled' => $multitenancyData['enabled'] ?? true, + 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', + 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', + 'adminOverride' => $multitenancyData['adminOverride'] ?? true, ]; $this->appConfig->setValueString($this->appName, 'multitenancy', json_encode($multitenancyConfig)); } @@ -907,20 +911,20 @@ public function getMultitenancySettingsOnly(): array if (empty($multitenancyConfig) === true) { // Default: multitenancy enabled for proper data isolation. $multitenancyData = [ - 'enabled' => true, - 'defaultUserTenant' => '', - 'defaultObjectTenant' => '', - 'adminOverride' => true, + 'enabled' => true, + 'defaultUserTenant' => '', + 'defaultObjectTenant' => '', + 'adminOverride' => true, ]; } if (empty($multitenancyConfig) === false) { $storedData = json_decode($multitenancyConfig, true); $multitenancyData = [ - 'enabled' => $storedData['enabled'] ?? true, - 'defaultUserTenant' => $storedData['defaultUserTenant'] ?? '', - 'defaultObjectTenant' => $storedData['defaultObjectTenant'] ?? '', - 'adminOverride' => $storedData['adminOverride'] ?? true, + 'enabled' => $storedData['enabled'] ?? true, + 'defaultUserTenant' => $storedData['defaultUserTenant'] ?? '', + 'defaultObjectTenant' => $storedData['defaultObjectTenant'] ?? '', + 'adminOverride' => $storedData['adminOverride'] ?? true, ]; } @@ -947,10 +951,10 @@ public function updateMultitenancySettingsOnly(array $multitenancyData): array try { // Default: enabled=true for proper data isolation. $multitenancyConfig = [ - 'enabled' => $multitenancyData['enabled'] ?? true, - 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', - 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', - 'adminOverride' => $multitenancyData['adminOverride'] ?? true, + 'enabled' => $multitenancyData['enabled'] ?? true, + 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', + 'defaultObjectTenant' => $multitenancyData['defaultObjectTenant'] ?? '', + 'adminOverride' => $multitenancyData['adminOverride'] ?? true, ]; $this->appConfig->setValueString($this->appName, 'multitenancy', json_encode($multitenancyConfig)); diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index 5b959363e..d5ab95034 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -1170,11 +1170,11 @@ private function createBatchJobs(int $totalObjects, int $batchSize): array /** * Process batch jobs in serial mode * - * @param array $batchJobs Array of batch job definitions. + * @param array $batchJobs Array of batch job definitions. * @param \OCA\OpenRegister\Db\MagicMapper $objectMapper The object entity mapper. - * @param ObjectService|null $objectService The object service instance. - * @param array $results Results array to update. - * @param bool $collectErrors Whether to collect all errors. + * @param ObjectService|null $objectService The object service instance. + * @param array $results Results array to update. + * @param bool $collectErrors Whether to collect all errors. * * @return void * @@ -1248,8 +1248,10 @@ private function processJobsSerial( 'batch_mode' => 'serial_optimized', ]; + $objUuid = $object->getUuid(); + $errMsg = $e->getMessage(); $this->logger->error( - message: '[SettingsService] Mass validation failed for object '.$object->getUuid().': '.$e->getMessage(), + message: "[SettingsService] Mass validation failed for object {$objUuid}: {$errMsg}", context: ['file' => __FILE__, 'line' => __LINE__] ); @@ -1309,12 +1311,12 @@ private function processJobsSerial( /** * Process batch jobs in parallel mode * - * @param array $batchJobs Array of batch job definitions. + * @param array $batchJobs Array of batch job definitions. * @param \OCA\OpenRegister\Db\MagicMapper $objectMapper The object entity mapper. - * @param ObjectService|null $objectService The object service instance. - * @param array $results Results array to update. - * @param bool $collectErrors Whether to collect all errors. - * @param int $parallelBatches Number of parallel batches. + * @param ObjectService|null $objectService The object service instance. + * @param array $results Results array to update. + * @param bool $collectErrors Whether to collect all errors. + * @param int $parallelBatches Number of parallel batches. * * @return void */ @@ -1386,7 +1388,7 @@ private function processJobsParallel( /** * Process a single batch directly * - * @param \OCA\OpenRegister\Db\MagicMapper $objectMapper The object entity mapper. + * @param \OCA\OpenRegister\Db\MagicMapper $objectMapper The object entity mapper. * @param \OCA\OpenRegister\Service\ObjectService $objectService The object service instance. * @param array $job Batch job definition. * @param bool $collectErrors Whether to collect all errors. @@ -2004,10 +2006,10 @@ private function getDatabaseStats(): array return [ 'warnings' => [ - 'auditTrailsWithoutExpiry' => (int) ($row['audit_trails_without_expiry'] ?? 0), - 'searchTrailsWithoutExpiry' => (int) ($row['search_trails_without_expiry'] ?? 0), - 'expiredAuditTrails' => (int) ($row['expired_audit_trails'] ?? 0), - 'expiredSearchTrails' => (int) ($row['expired_search_trails'] ?? 0), + 'auditTrailsWithoutExpiry' => (int) ($row['audit_trails_without_expiry'] ?? 0), + 'searchTrailsWithoutExpiry' => (int) ($row['search_trails_without_expiry'] ?? 0), + 'expiredAuditTrails' => (int) ($row['expired_audit_trails'] ?? 0), + 'expiredSearchTrails' => (int) ($row['expired_search_trails'] ?? 0), ], 'totals' => [ 'totalObjects' => $magicCount, diff --git a/lib/Service/TextExtraction/ObjectHandler.php b/lib/Service/TextExtraction/ObjectHandler.php index da821f2d1..6965270e6 100644 --- a/lib/Service/TextExtraction/ObjectHandler.php +++ b/lib/Service/TextExtraction/ObjectHandler.php @@ -34,11 +34,11 @@ class ObjectHandler implements TextExtractionHandlerInterface /** * Constructor. * - * @param MagicMapper $objectMapper Object mapper. - * @param ChunkMapper $chunkMapper Chunk mapper. - * @param SchemaMapper $schemaMapper Schema mapper. - * @param RegisterMapper $registerMapper Register mapper. - * @param LoggerInterface $logger Logger. + * @param MagicMapper $objectMapper Object mapper. + * @param ChunkMapper $chunkMapper Chunk mapper. + * @param SchemaMapper $schemaMapper Schema mapper. + * @param RegisterMapper $registerMapper Register mapper. + * @param LoggerInterface $logger Logger. */ public function __construct( private readonly MagicMapper $objectMapper, diff --git a/lib/Service/TextExtractionService.php b/lib/Service/TextExtractionService.php index b733adf97..bfb15d313 100644 --- a/lib/Service/TextExtractionService.php +++ b/lib/Service/TextExtractionService.php @@ -116,7 +116,7 @@ class TextExtractionService * @param IRootFolder $rootFolder Nextcloud root folder * @param IDBConnection $db Database connection * @param LoggerInterface $logger Logger - * @param MagicMapper $objectEntityMapper Mapper for object entities + * @param MagicMapper $objectEntityMapper Mapper for object entities * @param SchemaMapper $schemaMapper Mapper for schemas * @param RegisterMapper $registerMapper Mapper for registers * @param EntityRecognitionHandler $entityHandler Handler for entity recognition diff --git a/lib/WorkflowEngine/WorkflowResult.php b/lib/WorkflowEngine/WorkflowResult.php index 98ed91df8..aa39a2f74 100644 --- a/lib/WorkflowEngine/WorkflowResult.php +++ b/lib/WorkflowEngine/WorkflowResult.php @@ -86,8 +86,9 @@ public function __construct( array $metadata=[] ) { if (in_array(needle: $status, haystack: self::VALID_STATUSES, strict: true) === false) { + $validList = implode(separator: ', ', array: self::VALID_STATUSES); throw new InvalidArgumentException( - message: "Invalid workflow result status '$status'. ".'Must be one of: '.implode(separator: ', ', array: self::VALID_STATUSES) + message: "Invalid workflow result status '$status'. Must be one of: $validList" ); }